import React, { useRef, useEffect, useState, useImperativeHandle, forwardRef, useMemo } from 'react';
import {
  Bold, Italic, Underline, AlignLeft, AlignCenter, AlignRight, List, Heading1, Heading2,
  Copy, Wand2, Check, RefreshCw, Maximize2, Loader2, MousePointerClick, History, RotateCcw,
  ChevronDown, ChevronUp, Layers
} from 'lucide-react';

export interface RichTextEditorHandle {
  insertHtml: (html: string) => void;
}

interface RichTextEditorProps {
  initialContent: string;
  onChange?: (html: string) => void;
  onSave?: (html: string) => void;
  onSelectionChange?: (text: string) => void;
  onAiTransform?: (text: string, mode: 'correct' | 'rewrite' | 'expand' | 'continue') => Promise<string>;
}

interface Version {
  id: string;
  timestamp: number;
  type: string;
  content: string; // Full HTML snapshot
  snippet: string; // Selected text snippet before change
  topOffset: number; // Y position relative to editor top
}

interface VersionGroup {
  id: string;
  topOffset: number;
  versions: Version[];
}

const RichTextEditor = forwardRef<RichTextEditorHandle, RichTextEditorProps>(({ initialContent, onChange, onSave, onSelectionChange, onAiTransform }, ref) => {
  const contentRef = useRef<HTMLDivElement>(null);
  const scrollContainerRef = useRef<HTMLDivElement>(null);
  const [isFocused, setIsFocused] = useState(false);

  // Auto-Save State
  const [saveStatus, setSaveStatus] = useState<'saved' | 'saving' | 'unsaved'>('saved');
  const saveTimeoutRef = useRef<NodeJS.Timeout | null>(null);

  // Context Menu State
  const [contextMenu, setContextMenu] = useState<{ x: number; y: number } | null>(null);
  const [isAiLoading, setIsAiLoading] = useState(false);

  // History State
  const [versions, setVersions] = useState<Version[]>([]);
  const [showHistoryMargin, setShowHistoryMargin] = useState(true);
  const [expandedGroupIds, setExpandedGroupIds] = useState<Set<string>>(new Set());

  // Refs to track selection
  const savedRange = useRef<Range | null>(null);
  const lastCursorPosition = useRef<Range | null>(null);

  // --- Helpers ---

  // Group versions by proximity (within 60px) to stack them
  const versionGroups = useMemo(() => {
    const sortedVersions = [...versions].sort((a, b) => b.timestamp - a.timestamp);
    const groups: VersionGroup[] = [];

    sortedVersions.forEach(v => {
      // Find an existing group close to this version
      const existingGroup = groups.find(g => Math.abs(g.topOffset - v.topOffset) < 60);

      if (existingGroup) {
        existingGroup.versions.push(v);
        // Keep the group timestamp sorted
        existingGroup.versions.sort((a, b) => b.timestamp - a.timestamp);
      } else {
        groups.push({
          id: `group-${v.id}`,
          topOffset: v.topOffset,
          versions: [v]
        });
      }
    });

    return groups;
  }, [versions]);

  const toggleGroup = (groupId: string) => {
    const newSet = new Set(expandedGroupIds);
    if (newSet.has(groupId)) {
      newSet.delete(groupId);
    } else {
      newSet.add(groupId);
    }
    setExpandedGroupIds(newSet);
  };

  const getSelectionTopOffset = () => {
    const sel = window.getSelection();
    if (sel && sel.rangeCount > 0 && contentRef.current) {
      const range = sel.getRangeAt(0);
      const rect = range.getBoundingClientRect();
      // We need offset relative to the content container (contentRef)
      // contentRef is the white page div.
      const containerRect = contentRef.current.getBoundingClientRect();
      return rect.top - containerRect.top;
    }
    return 0;
  };

  const saveVersion = (type: string, textSnippet: string) => {
    if (!contentRef.current) return;

    const topOffset = getSelectionTopOffset();

    const newVersion: Version = {
      id: Date.now().toString(),
      timestamp: Date.now(),
      type: type,
      content: contentRef.current.innerHTML,
      snippet: textSnippet.substring(0, 80) + (textSnippet.length > 80 ? '...' : ''),
      topOffset
    };

    setVersions(prev => [newVersion, ...prev]);
    setShowHistoryMargin(true);
  };

  const restoreVersion = (version: Version) => {
    if (!contentRef.current) return;
    if (confirm('Restaurer cette version ? Le contenu actuel sera remplacé.')) {
      contentRef.current.innerHTML = version.content;
      handleInput();
    }
  };

  // --- Exposed Methods ---

  useImperativeHandle(ref, () => ({
    insertHtml: (text: string) => {
      saveVersion('Insertion Chat', 'Insertion depuis le panneau IA');

      contentRef.current?.focus();

      const sel = window.getSelection();
      if (lastCursorPosition.current) {
        sel?.removeAllRanges();
        sel?.addRange(lastCursorPosition.current);
      } else if (contentRef.current) {
        const range = document.createRange();
        range.selectNodeContents(contentRef.current);
        range.collapse(false);
        sel?.removeAllRanges();
        sel?.addRange(range);
      }

      const htmlToInsert = text.includes('<') ? text : text.replace(/\n/g, '<br>');
      document.execCommand('insertHTML', false, htmlToInsert);
      handleInput();
    }
  }));

  // --- Effects ---

  useEffect(() => {
    if (contentRef.current && contentRef.current.innerHTML !== initialContent) {
      // Only update if difference is significant to avoid cursor jumps on small re-renders?
      // OR better: Only update if NOT focused?
      if (!isFocused && Math.abs(contentRef.current.innerHTML.length - initialContent.length) > 5) {
        contentRef.current.innerHTML = initialContent;
      }
    }
  }, [initialContent, isFocused]);

  // --- Event Handlers ---

  const execCommand = (command: string, value: string | undefined = undefined) => {
    document.execCommand(command, false, value);
    handleInput();
    contentRef.current?.focus();
  };

  const handleInput = () => {
    if (contentRef.current) {
      if (onChange) onChange(contentRef.current.innerHTML);

      // Auto-Save Debounce
      if (onSave) {
        setSaveStatus('unsaved');
        if (saveTimeoutRef.current) clearTimeout(saveTimeoutRef.current);

        saveTimeoutRef.current = setTimeout(async () => {
          setSaveStatus('saving');
          await onSave(contentRef.current?.innerHTML || "");
          setSaveStatus('saved');
        }, 2000); // 2 seconds
      }
    }
  };

  const saveSelection = () => {
    const sel = window.getSelection();
    if (sel && sel.rangeCount > 0 && contentRef.current?.contains(sel.anchorNode)) {
      lastCursorPosition.current = sel.getRangeAt(0).cloneRange();
    }
  };

  const handleSelection = () => {
    const selection = window.getSelection();
    saveSelection();

    if (selection && selection.toString().length > 0 && onSelectionChange) {
      onSelectionChange(selection.toString());
    } else if (onSelectionChange) {
      onSelectionChange("");
    }
  };

  const handleContextMenu = (e: React.MouseEvent) => {
    e.preventDefault();
    const selection = window.getSelection();

    if (selection && selection.rangeCount > 0) {
      const range = selection.getRangeAt(0);
      if (contentRef.current?.contains(range.commonAncestorContainer)) {
        savedRange.current = range.cloneRange();
        setContextMenu({ x: e.clientX, y: e.clientY });
        return;
      }
    }

    savedRange.current = null;
    setContextMenu({ x: e.clientX, y: e.clientY });
  };

  const handleAiAction = async (mode: 'correct' | 'rewrite' | 'expand' | 'continue') => {
    if (!onAiTransform) return;

    const range = savedRange.current;
    const text = range?.toString() || "";

    if (!text && mode !== 'continue') return;

    const typeLabels: Record<string, string> = {
      correct: 'Correction',
      rewrite: 'Reformulation',
      expand: 'Développement',
      continue: 'Continuation'
    };
    saveVersion(typeLabels[mode], text || "Position curseur");

    setIsAiLoading(true);
    try {
      const result = await onAiTransform(text, mode);

      if (result) {
        contentRef.current?.focus();
        const sel = window.getSelection();
        sel?.removeAllRanges();

        if (range) {
          sel?.addRange(range);
        }

        if (mode === 'continue') {
          sel?.collapseToEnd();
          document.execCommand('insertText', false, " " + result);
        } else {
          document.execCommand('insertText', false, result);
        }

        handleInput();
      }
    } catch (e) {
      console.error("AI Action failed", e);
    } finally {
      setIsAiLoading(false);
      setContextMenu(null);
    }
  };

  const handleCopy = () => {
    if (savedRange.current) {
      const sel = window.getSelection();
      sel?.removeAllRanges();
      sel?.addRange(savedRange.current);
      document.execCommand('copy');
    }
    setContextMenu(null);
  };

  const handleSelectAll = () => {
    contentRef.current?.focus();
    document.execCommand('selectAll');
    handleSelection();
    setContextMenu(null);
  }

  const ToolbarButton = ({ icon: Icon, cmd, arg, label, onClick, isActive }: any) => (
    <button
      onMouseDown={(e) => {
        if (onClick) {
          e.preventDefault();
          onClick();
        } else {
          e.preventDefault();
          execCommand(cmd, arg);
        }
      }}
      className={`p-1.5 rounded transition-colors ${isActive ? 'bg-indigo-100 text-indigo-700' : 'text-slate-500 hover:text-slate-800 hover:bg-slate-200'}`}
      title={label}
    >
      <Icon size={18} />
    </button>
  );

  const hasSelection = savedRange.current && !savedRange.current.collapsed;

  return (
    <div className="flex flex-col h-full bg-white rounded-lg shadow-sm border border-slate-200 overflow-hidden relative">
      <style>{`
        .editor-content:empty::before {
            content: attr(data-placeholder);
            color: #cbd5e1;
            font-style: italic;
            cursor: text;
        }
      `}</style>

      {/* Toolbar */}
      <div className="flex items-center gap-1 p-2 bg-slate-50 border-b border-slate-200 flex-wrap relative z-20 shadow-sm">
        <ToolbarButton icon={Bold} cmd="bold" label="Gras" />
        <ToolbarButton icon={Italic} cmd="italic" label="Italique" />
        <ToolbarButton icon={Underline} cmd="underline" label="Souligné" />
        <div className="w-px h-6 bg-slate-300 mx-1" />
        <ToolbarButton icon={Heading1} cmd="formatBlock" arg="H1" label="Titre 1" />
        <ToolbarButton icon={Heading2} cmd="formatBlock" arg="H2" label="Titre 2" />
        <div className="w-px h-6 bg-slate-300 mx-1" />
        <ToolbarButton icon={AlignLeft} cmd="justifyLeft" label="Aligner à gauche" />
        <ToolbarButton icon={AlignCenter} cmd="justifyCenter" label="Centrer" />
        <ToolbarButton icon={AlignRight} cmd="justifyRight" label="Aligner à droite" />
        <div className="w-px h-6 bg-slate-300 mx-1" />
        <ToolbarButton icon={List} cmd="insertUnorderedList" label="Liste" />

        <div className="flex-1" />

        {/* Save Status Indicator */}
        <div className="flex items-center gap-2 mr-4 text-xs font-medium text-slate-400">
          {saveStatus === 'saving' && <><Loader2 size={12} className="animate-spin" /> Sauvegarde...</>}
          {saveStatus === 'saved' && <><Check size={12} className="text-green-500" /> Sauvegardé</>}
          {saveStatus === 'unsaved' && <span className="text-amber-500">Modifications non enregistrées...</span>}
        </div>

        <div className="w-px h-6 bg-slate-300 mx-1" />
        <ToolbarButton
          icon={History}
          label="Marge d'historique"
          onClick={() => setShowHistoryMargin(!showHistoryMargin)}
          isActive={showHistoryMargin}
        />
      </div>

      {/* Main Container - Scrollable Area */}
      <div
        className="flex-1 overflow-y-auto relative bg-slate-100"
        ref={scrollContainerRef}
      >
        <div className="flex justify-center relative min-h-full py-8">

          {/* Editor Content Page */}
          <div
            ref={contentRef}
            contentEditable
            suppressContentEditableWarning
            className="bg-white shadow-sm w-[800px] min-h-[1000px] p-12 outline-none font-serif text-lg leading-relaxed text-slate-900 editor-content"
            onInput={handleInput}
            onBlur={() => { setIsFocused(false); saveSelection(); }}
            onFocus={() => setIsFocused(true)}
            onKeyUp={saveSelection}
            onMouseUp={saveSelection}
            onSelect={handleSelection}
            onClick={() => contentRef.current?.focus()}
            onContextMenu={handleContextMenu}
            data-placeholder="Commencez à écrire votre chef-d'œuvre... (Clic droit pour outils IA)"
          />

          {/* History Track - Moving with the page */}
          {showHistoryMargin && (
            <div className="absolute left-[calc(50%+420px)] top-0 bottom-0 w-80 pt-8 pointer-events-none">
              {/* Placeholder for empty history */}
              {versionGroups.length === 0 && (
                <div className="sticky top-10 text-center text-slate-300 p-4">
                  <History size={48} className="mx-auto mb-2 opacity-20" />
                  <p className="text-xs">L'historique des modifications IA apparaîtra ici, aligné avec votre texte.</p>
                </div>
              )}

              {/* Render Groups */}
              {versionGroups.map((group) => {
                const isExpanded = expandedGroupIds.has(group.id);
                const isStack = group.versions.length > 1;
                const latest = group.versions[0];

                return (
                  <div
                    key={group.id}
                    className="absolute w-72 pointer-events-auto transition-all duration-300 ease-in-out"
                    style={{ top: `${group.topOffset + 32}px` }} // +32 for padding
                  >
                    <div className={`relative bg-white rounded-lg border shadow-sm transition-all duration-200 ${isStack && !isExpanded ? 'border-indigo-200 shadow-md translate-x-1 translate-y-1' : 'border-slate-200'}`}>

                      {/* Stack Effect Background Card */}
                      {isStack && !isExpanded && (
                        <div className="absolute inset-0 bg-white border border-indigo-100 rounded-lg transform -translate-x-1 -translate-y-1 -z-10 shadow-sm" />
                      )}

                      {/* Main Card Header */}
                      <div
                        className="p-2 border-b border-slate-100 flex justify-between items-center bg-slate-50 rounded-t-lg cursor-pointer hover:bg-slate-100"
                        onClick={() => isStack && toggleGroup(group.id)}
                      >
                        <div className="flex items-center gap-2">
                          {isStack && (
                            <Layers size={14} className="text-indigo-500" />
                          )}
                          <span className={`text-[10px] font-bold px-1.5 py-0.5 rounded uppercase tracking-wide ${latest.type.includes('Correction') ? 'bg-green-100 text-green-700' :
                              latest.type.includes('Insertion') ? 'bg-blue-100 text-blue-700' :
                                'bg-purple-100 text-purple-700'
                            }`}>
                            {latest.type}
                          </span>
                        </div>
                        <div className="flex items-center gap-1">
                          <span className="text-[10px] text-slate-400">
                            {new Date(latest.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
                          </span>
                          {isStack && (
                            isExpanded ? <ChevronUp size={14} className="text-slate-400" /> : <ChevronDown size={14} className="text-slate-400" />
                          )}
                        </div>
                      </div>

                      {/* Card Content (Latest) */}
                      {!isExpanded && (
                        <div className="p-2">
                          <div className="text-xs text-slate-500 italic line-clamp-2">
                            "{latest.snippet}"
                          </div>
                          <button
                            onClick={() => restoreVersion(latest)}
                            className="mt-2 w-full flex items-center justify-center gap-1 text-[10px] bg-slate-50 hover:bg-indigo-50 text-slate-600 hover:text-indigo-700 py-1 rounded transition-colors"
                          >
                            <RotateCcw size={10} /> Restaurer
                          </button>
                        </div>
                      )}

                      {/* Expanded Stack View */}
                      {isExpanded && (
                        <div className="divide-y divide-slate-100 max-h-64 overflow-y-auto">
                          {group.versions.map((v, i) => (
                            <div key={v.id} className="p-2 bg-white hover:bg-slate-50 transition-colors">
                              <div className="flex justify-between items-center mb-1">
                                <span className="text-[10px] font-semibold text-slate-600">
                                  {i === 0 ? 'Dernière version' : `Version -${i}`}
                                </span>
                                <span className="text-[9px] text-slate-400">
                                  {new Date(v.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' })}
                                </span>
                              </div>
                              <div className="text-xs text-slate-500 italic bg-slate-50 p-1.5 rounded mb-2 border border-slate-100">
                                "{v.snippet}"
                              </div>
                              <button
                                onClick={() => restoreVersion(v)}
                                className="w-full flex items-center justify-center gap-1 text-[10px] bg-white border border-slate-200 text-slate-600 hover:text-indigo-600 hover:border-indigo-200 py-1 rounded transition-colors"
                              >
                                <RotateCcw size={10} /> Restaurer cette version
                              </button>
                            </div>
                          ))}
                        </div>
                      )}
                    </div>
                  </div>
                );
              })}
            </div>
          )}
        </div>
      </div>

      {/* Context Menu Overlay */}
      {contextMenu && (
        <>
          <div
            className="fixed inset-0 z-40 bg-transparent"
            onClick={() => setContextMenu(null)}
            onContextMenu={(e) => { e.preventDefault(); setContextMenu(null); }}
          />
          <div
            className="fixed z-50 bg-white border border-slate-200 rounded-lg shadow-xl py-1 w-56 animate-in fade-in zoom-in-95 duration-100 flex flex-col"
            style={{ top: Math.min(contextMenu.y, window.innerHeight - 200), left: Math.min(contextMenu.x, window.innerWidth - 224) }}
          >
            {isAiLoading ? (
              <div className="flex flex-col items-center justify-center py-4 text-indigo-600 gap-2">
                <Loader2 className="animate-spin" size={24} />
                <span className="text-xs font-medium">L'IA travaille...</span>
              </div>
            ) : (
              <>
                <div className="px-3 py-1 text-[10px] font-bold text-slate-400 uppercase tracking-wider">
                  Outils IA
                </div>

                <button
                  onClick={() => handleAiAction('correct')}
                  disabled={!hasSelection}
                  className={`flex items-center gap-2 px-3 py-2 text-sm text-left transition-colors ${!hasSelection ? 'text-slate-300 cursor-not-allowed' : 'text-slate-700 hover:bg-indigo-50 hover:text-indigo-700'}`}
                >
                  <Check size={14} /> Corriger l'orthographe
                </button>

                <button
                  onClick={() => handleAiAction('rewrite')}
                  disabled={!hasSelection}
                  className={`flex items-center gap-2 px-3 py-2 text-sm text-left transition-colors ${!hasSelection ? 'text-slate-300 cursor-not-allowed' : 'text-slate-700 hover:bg-indigo-50 hover:text-indigo-700'}`}
                >
                  <RefreshCw size={14} /> Reformuler
                </button>

                <button
                  onClick={() => handleAiAction('expand')}
                  disabled={!hasSelection}
                  className={`flex items-center gap-2 px-3 py-2 text-sm text-left transition-colors ${!hasSelection ? 'text-slate-300 cursor-not-allowed' : 'text-slate-700 hover:bg-indigo-50 hover:text-indigo-700'}`}
                >
                  <Maximize2 size={14} /> Développer
                </button>

                <button
                  onClick={() => handleAiAction('continue')}
                  className="flex items-center gap-2 px-3 py-2 text-sm text-slate-700 hover:bg-indigo-50 hover:text-indigo-700 text-left transition-colors"
                >
                  <Wand2 size={14} /> Continuer l'écriture
                </button>

                <div className="h-px bg-slate-100 my-1" />

                <div className="px-3 py-1 text-[10px] font-bold text-slate-400 uppercase tracking-wider">
                  Édition
                </div>

                <button
                  onClick={handleCopy}
                  disabled={!hasSelection}
                  className={`flex items-center gap-2 px-3 py-2 text-sm text-left transition-colors ${!hasSelection ? 'text-slate-300 cursor-not-allowed' : 'text-slate-700 hover:bg-slate-50'}`}
                >
                  <Copy size={14} /> Copier
                </button>

                <button
                  onClick={handleSelectAll}
                  className="flex items-center gap-2 px-3 py-2 text-sm text-slate-700 hover:bg-slate-50 text-left transition-colors"
                >
                  <MousePointerClick size={14} /> Tout sélectionner
                </button>
              </>
            )}
          </div>
        </>
      )}
    </div>
  );
});

export default RichTextEditor;
