'use client';

import { useEditor, EditorContent, type Editor } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
import Underline from '@tiptap/extension-underline';
import Link from '@tiptap/extension-link';
import Image from '@tiptap/extension-image';
import Placeholder from '@tiptap/extension-placeholder';
import CharacterCount from '@tiptap/extension-character-count';
import TextAlign from '@tiptap/extension-text-align';
import Highlight from '@tiptap/extension-highlight';
import {
  Bold, Italic, UnderlineIcon, Strikethrough, Heading1, Heading2, Heading3,
  List, ListOrdered, Quote, Link as LinkIcon, Image as ImageIcon,
  AlignLeft, AlignCenter, AlignRight, Undo, Redo, Highlighter, Sparkles,
} from 'lucide-react';
import { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from 'react';
import { cn } from '@/lib/utils';
import { ALL_SPAM_TRIGGERS } from '@/modules/spam-check/lib/triggers';

export interface MarketingEditorProps {
  initialJson?: object;
  onChange?: (json: object, html: string, text: string) => void;
  placeholder?: string;
  className?: string;
  /**
   * KI-Brief-Trigger — wenn gesetzt, erscheint ein Magenta-Sparkles-Button in der Toolbar.
   * Der Klick wird vom Parent (page.tsx) verarbeitet, der wiederum POST /api/draft-brief feuert
   * und am Ende editorRef.current.replaceContent(json) aufruft.
   */
  onAiDraftBrief?: () => void;
  /** True → Button disabled (z.B. weil isBriefingReady() false ist). Tooltip ändert sich. */
  aiDraftBriefDisabled?: boolean;
  /** True → Button zeigt Spinner statt Sparkles. */
  aiDraftBriefBusy?: boolean;
}

/**
 * Imperative API für Parent-Komponenten — exposed via forwardRef.
 *
 * - `insertPlaceholder`: Merge-Tags `{{column_name}}` an der Cursor-Position einfügen (Zielgruppe-Tab)
 * - `replaceContent`: kompletten Editor-Inhalt ersetzen (KI-Brief-Auto-Fill); emit's onUpdate damit
 *   Parent-State + Auto-Save synchronisiert werden.
 *
 * Setzt voraus, dass der MarketingEditor mounted bleibt (siehe page.tsx: `hidden` statt unmount).
 */
export interface MarketingEditorHandle {
  insertPlaceholder(columnName: string): void;
  replaceContent(json: object): void;
  hasContent(): boolean;
}

export const MarketingEditor = forwardRef<MarketingEditorHandle, MarketingEditorProps>(function MarketingEditor(
  { initialJson, onChange, placeholder, className, onAiDraftBrief, aiDraftBriefDisabled, aiDraftBriefBusy },
  ref,
) {
  const editor = useEditor({
    extensions: [
      StarterKit.configure({
        heading: { levels: [1, 2, 3] },
      }),
      Underline,
      Link.configure({ openOnClick: false, autolink: true, HTMLAttributes: { class: 'text-blue-600 underline' } }),
      Image.configure({ HTMLAttributes: { class: 'rounded-md max-w-full' } }),
      Placeholder.configure({
        placeholder: placeholder ?? 'Schreiben Sie hier den Brief Ihrer Marketing-Mail. Tipp: Beginnen Sie mit dem Schmerzpunkt Ihres Kunden …',
      }),
      CharacterCount,
      TextAlign.configure({ types: ['heading', 'paragraph'] }),
      Highlight.configure({ multicolor: false, HTMLAttributes: { class: 'bg-amber-200/60 rounded px-0.5' } }),
    ],
    content: initialJson ?? '',
    editorProps: {
      attributes: {
        class: 'prose prose-zinc dark:prose-invert max-w-none focus:outline-none min-h-[460px] px-8 py-6 leading-relaxed',
      },
    },
    onUpdate: ({ editor }) => {
      onChange?.(editor.getJSON(), editor.getHTML(), editor.getText());
    },
    immediatelyRender: false,
  });

  // Spam-Trigger Live-Highlighting (Debounced über getText)
  useEffect(() => {
    if (!editor) return;
    const handler = () => {
      const text = editor.getText().toLowerCase();
      const hits = ALL_SPAM_TRIGGERS.filter((t) => text.includes(t.toLowerCase()));
      // (UI-Anzeige im Footer; hier würden wir ein Decoration-Plugin setzen — minimal: Footer-Counter via Custom Event)
      window.dispatchEvent(new CustomEvent('mailforge:triggers', { detail: hits }));
    };
    editor.on('update', handler);
    return () => { editor.off('update', handler); };
  }, [editor]);

  // Imperative API: erlaubt dem Parent (page.tsx) das Einfügen von `{{key}}` aus
  // anderen Tabs (z.B. Zielgruppe). `insertContentAt(selection.from, ...)` respektiert
  // die zuletzt aktive Cursor-Position — funktioniert nur, weil der Editor zwischen
  // Tab-Wechseln NICHT unmounted wird (siehe page.tsx: hidden statt conditional render).
  useImperativeHandle(ref, () => ({
    insertPlaceholder(columnName: string) {
      if (!editor) return;
      const pos = editor.state.selection.from;
      editor.chain().focus().insertContentAt(pos, `{{${columnName}}}`).run();
    },
    replaceContent(json: object) {
      if (!editor) return;
      // TipTap 2.11.x: setContent(content, emitUpdate?: boolean, parseOptions?). Der zweite
      // Parameter MUSS `true` sein, sonst läuft onUpdate nicht und page.tsx's
      // content.{json,html,text} bleibt stale → Auto-Save persistiert leeren State.
      editor.commands.setContent(json, true);
      // Belt-and-suspenders: Page-State manuell syncen, falls TipTap's onUpdate aus irgendeinem
      // Grund nicht feuert (Edge-Cases mit React-Strict-Mode, Race mit pending Selection-Updates).
      // setContent(...) im Page-State ist idempotent → Doppel-Updates sind harmlos.
      onChange?.(editor.getJSON(), editor.getHTML(), editor.getText());
    },
    hasContent() {
      if (!editor) return false;
      return editor.getText().trim().length > 0;
    },
  }), [editor]);

  if (!editor) return <div className="h-[600px] animate-pulse bg-zinc-50" />;

  return (
    <div className={cn('flex flex-col rounded-lg border border-zinc-200 bg-white shadow-sm dark:border-zinc-800 dark:bg-zinc-950', className)}>
      <Toolbar
        editor={editor}
        onAiDraftBrief={onAiDraftBrief}
        aiDraftBriefDisabled={aiDraftBriefDisabled}
        aiDraftBriefBusy={aiDraftBriefBusy}
      />
      <EditorContent editor={editor} />
      <EditorFooter editor={editor} />
    </div>
  );
});

function Toolbar({
  editor,
  onAiDraftBrief,
  aiDraftBriefDisabled,
  aiDraftBriefBusy,
}: {
  editor: Editor;
  onAiDraftBrief?: () => void;
  aiDraftBriefDisabled?: boolean;
  aiDraftBriefBusy?: boolean;
}) {
  const setLink = useCallback(() => {
    const prev = editor.getAttributes('link').href;
    const url = window.prompt('Link-URL eingeben (leer lassen zum Entfernen):', prev ?? '');
    if (url === null) return;
    if (url === '') { editor.chain().focus().extendMarkRange('link').unsetLink().run(); return; }
    editor.chain().focus().extendMarkRange('link').setLink({ href: url }).run();
  }, [editor]);

  const addImage = useCallback(() => {
    const url = window.prompt('Bild-URL (oder leer für Auto-Hero im AI-Schritt):');
    if (!url) return;
    editor.chain().focus().setImage({ src: url, alt: '' }).run();
  }, [editor]);

  return (
    <div className="sticky top-0 z-10 flex flex-wrap items-center gap-0.5 border-b border-zinc-200 bg-white/95 px-2 py-2 backdrop-blur dark:border-zinc-800 dark:bg-zinc-950/95">
      <TbBtn onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()} active={editor.isActive('heading', { level: 1 })} title="Überschrift 1"><Heading1 className="h-4 w-4" /></TbBtn>
      <TbBtn onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()} active={editor.isActive('heading', { level: 2 })} title="Überschrift 2"><Heading2 className="h-4 w-4" /></TbBtn>
      <TbBtn onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()} active={editor.isActive('heading', { level: 3 })} title="Überschrift 3"><Heading3 className="h-4 w-4" /></TbBtn>
      <Sep />
      <TbBtn onClick={() => editor.chain().focus().toggleBold().run()} active={editor.isActive('bold')} title="Fett (⌘B)"><Bold className="h-4 w-4" /></TbBtn>
      <TbBtn onClick={() => editor.chain().focus().toggleItalic().run()} active={editor.isActive('italic')} title="Kursiv (⌘I)"><Italic className="h-4 w-4" /></TbBtn>
      <TbBtn onClick={() => editor.chain().focus().toggleUnderline().run()} active={editor.isActive('underline')} title="Unterstrichen (⌘U)"><UnderlineIcon className="h-4 w-4" /></TbBtn>
      <TbBtn onClick={() => editor.chain().focus().toggleStrike().run()} active={editor.isActive('strike')} title="Durchgestrichen"><Strikethrough className="h-4 w-4" /></TbBtn>
      <TbBtn onClick={() => editor.chain().focus().toggleHighlight().run()} active={editor.isActive('highlight')} title="Markieren"><Highlighter className="h-4 w-4" /></TbBtn>
      <Sep />
      <TbBtn onClick={() => editor.chain().focus().toggleBulletList().run()} active={editor.isActive('bulletList')} title="Aufzählung"><List className="h-4 w-4" /></TbBtn>
      <TbBtn onClick={() => editor.chain().focus().toggleOrderedList().run()} active={editor.isActive('orderedList')} title="Nummerierte Liste"><ListOrdered className="h-4 w-4" /></TbBtn>
      <TbBtn onClick={() => editor.chain().focus().toggleBlockquote().run()} active={editor.isActive('blockquote')} title="Zitat"><Quote className="h-4 w-4" /></TbBtn>
      <Sep />
      <TbBtn onClick={() => editor.chain().focus().setTextAlign('left').run()} active={editor.isActive({ textAlign: 'left' })} title="Linksbündig"><AlignLeft className="h-4 w-4" /></TbBtn>
      <TbBtn onClick={() => editor.chain().focus().setTextAlign('center').run()} active={editor.isActive({ textAlign: 'center' })} title="Zentriert"><AlignCenter className="h-4 w-4" /></TbBtn>
      <TbBtn onClick={() => editor.chain().focus().setTextAlign('right').run()} active={editor.isActive({ textAlign: 'right' })} title="Rechtsbündig"><AlignRight className="h-4 w-4" /></TbBtn>
      <Sep />
      <TbBtn onClick={setLink} active={editor.isActive('link')} title="Link"><LinkIcon className="h-4 w-4" /></TbBtn>
      <TbBtn onClick={addImage} title="Bild"><ImageIcon className="h-4 w-4" /></TbBtn>
      <Sep />
      <TbBtn onClick={() => editor.chain().focus().undo().run()} title="Rückgängig"><Undo className="h-4 w-4" /></TbBtn>
      <TbBtn onClick={() => editor.chain().focus().redo().run()} title="Wiederherstellen"><Redo className="h-4 w-4" /></TbBtn>
      {onAiDraftBrief && (
        <>
          <Sep />
          <AiDraftBriefBtn
            onClick={onAiDraftBrief}
            disabled={aiDraftBriefDisabled}
            busy={aiDraftBriefBusy}
            hasContent={editor.getText().trim().length > 0}
          />
        </>
      )}
    </div>
  );
}

/**
 * Magenta-Sparkles-Button am Ende der Toolbar — triggert in der Page einen POST /api/draft-brief.
 * Wenn der Editor schon Inhalt hat, kommt vor dem Trigger ein Confirm-Dialog,
 * weil die Server-Antwort den kompletten Editor-Inhalt überschreibt.
 */
function AiDraftBriefBtn({
  onClick,
  disabled,
  busy,
  hasContent,
}: {
  onClick: () => void;
  disabled?: boolean;
  busy?: boolean;
  hasContent: boolean;
}) {
  const handleClick = () => {
    if (disabled || busy) return;
    if (hasContent) {
      const ok = window.confirm('Editor-Inhalt mit KI-Brief überschreiben? Aktueller Text geht verloren.');
      if (!ok) return;
    }
    onClick();
  };
  const title = disabled
    ? 'Erst Briefing-Pflichtfelder ausfüllen (Tab 2)'
    : busy
    ? 'KI schreibt …'
    : 'KI-Brief aus Briefing schreiben';
  return (
    <button
      type="button"
      onClick={handleClick}
      disabled={disabled || busy}
      title={title}
      className={cn(
        'ml-auto inline-flex h-8 items-center gap-1.5 rounded-md bg-[#ff006a] px-2.5 text-xs font-semibold text-white transition hover:bg-[#e60060] disabled:cursor-not-allowed disabled:bg-zinc-300 disabled:text-zinc-500 dark:disabled:bg-zinc-700 dark:disabled:text-zinc-500',
      )}
    >
      <Sparkles className={cn('h-3.5 w-3.5', busy && 'animate-pulse')} />
      <span>{busy ? 'Schreibt …' : 'KI-Brief'}</span>
    </button>
  );
}

function TbBtn({ onClick, active, title, children }: { onClick: () => void; active?: boolean; title: string; children: React.ReactNode }) {
  return (
    <button
      type="button"
      onClick={onClick}
      title={title}
      className={cn(
        'inline-flex h-8 w-8 items-center justify-center rounded-md text-zinc-600 transition hover:bg-zinc-100 hover:text-zinc-900 dark:text-zinc-300 dark:hover:bg-zinc-800 dark:hover:text-zinc-100',
        active && 'bg-zinc-900 text-white hover:bg-zinc-900 hover:text-white dark:bg-zinc-100 dark:text-zinc-900',
      )}
    >
      {children}
    </button>
  );
}

function Sep() {
  return <div className="mx-1 h-5 w-px bg-zinc-200 dark:bg-zinc-700" />;
}

function EditorFooter({ editor }: { editor: Editor }) {
  const chars = editor.storage.characterCount.characters() as number;
  const words = editor.storage.characterCount.words() as number;
  return (
    <div className="flex items-center justify-between border-t border-zinc-200 bg-zinc-50/50 px-4 py-2 text-xs text-zinc-500 dark:border-zinc-800 dark:bg-zinc-900/40 dark:text-zinc-400">
      <div className="flex items-center gap-3">
        <span>{words} Wörter</span>
        <span className="text-zinc-300 dark:text-zinc-700">·</span>
        <span>{chars} Zeichen</span>
      </div>
      <SpamTriggerIndicator />
    </div>
  );
}

function SpamTriggerIndicator() {
  const [hits, setHits] = useState<string[]>([]);
  useEffect(() => {
    const onTriggers = (e: Event) => setHits((e as CustomEvent<string[]>).detail);
    window.addEventListener('mailforge:triggers', onTriggers);
    return () => window.removeEventListener('mailforge:triggers', onTriggers);
  }, []);
  if (hits.length === 0) {
    return <span className="inline-flex items-center gap-1.5 text-emerald-600"><Sparkles className="h-3 w-3" /> sauber</span>;
  }
  return (
    <span className="inline-flex items-center gap-1.5 text-amber-600" title={hits.join(', ')}>
      <Sparkles className="h-3 w-3" /> {hits.length} Spam-Trigger erkannt
    </span>
  );
}
