import { type Component, createEffect, untrack, createSignal, Show } from "solid-js";
import { createTiptapEditor } from "solid-tiptap";
import StarterKit from "@tiptap/starter-kit";
import Placeholder from "@tiptap/extension-placeholder";
import TaskList from "@tiptap/extension-task-list";
import { CustomTaskItem } from "./CustomTaskItem";
import Image from "@tiptap/extension-image";
import Underline from "@tiptap/extension-underline";
import { X } from "lucide-solid";
import { cn } from "@/lib/utils";
import { store } from "@/store";

import { SlashCommands } from "@/lib/slash-command";
import { suggestion } from "@/lib/slash-renderer";
import { MobileIndent } from "@/lib/mobile-indent";

// New Extensions
import { Link } from "@tiptap/extension-link";
import { Highlight } from "@tiptap/extension-highlight";
import { TextAlign } from "@tiptap/extension-text-align";
import { Table } from "@tiptap/extension-table";
import { TableRow } from "@tiptap/extension-table-row";
import { TableCell } from "@tiptap/extension-table-cell";
import { TableHeader } from "@tiptap/extension-table-header";
import { Typography } from "@tiptap/extension-typography";
import { Dropcursor } from "@tiptap/extension-dropcursor";
import { Mention } from "@tiptap/extension-mention";
import { userSuggestion, noteSuggestion } from "@/lib/mention-suggestion";

interface TaskEditorProps {
    content?: string;
    onUpdate: (html: string) => void;
    onEditorReady?: (editor: any) => void;
    editable?: boolean;
    onUserMention?: (userName: string) => void;
    onNoteOpen?: (noteId: string) => void;
    class?: string;
}

export const TaskEditor: Component<TaskEditorProps> = (props) => {
    let editorRef: HTMLDivElement | undefined;
    const [fullscreenImage, setFullscreenImage] = createSignal<string | null>(null);
    const [zoomScale, setZoomScale] = createSignal(1);
    const [zoomOffset, setZoomOffset] = createSignal({ x: 0, y: 0 });
    const [isDragging, setIsDragging] = createSignal(false);
    const [dragStart, setDragStart] = createSignal({ x: 0, y: 0 });
    const [previewNote, setPreviewNote] = createSignal<{ noteId: string, x: number, y: number } | null>(null);

    const resetZoom = () => {
        setZoomScale(1);
        setZoomOffset({ x: 0, y: 0 });
    };

    const editor = createTiptapEditor(() => ({
        element: editorRef!,
        extensions: [
            StarterKit.configure({
                heading: {
                    levels: [1, 2, 3],
                },
            }),
            Placeholder.configure({
                placeholder: ({ editor }) => {
                    // Only show placeholder if first node is a paragraph and doc is empty/short
                    if (editor.state.doc.childCount > 1 || (editor.state.doc.firstChild && editor.state.doc.firstChild.type.name !== 'paragraph')) {
                        return "";
                    }
                    return "Type '/' for commands or start writing...";
                },
                emptyEditorClass: "is-editor-empty before:content-[attr(data-placeholder)] before:text-muted-foreground before:float-left before:pointer-events-none before:h-0",
            }),
            TaskList.configure({
                HTMLAttributes: {
                    class: "not-prose pl-2",
                },
            }),
            CustomTaskItem.configure({
                nested: true,
                HTMLAttributes: {
                    class: "flex gap-2 items-start my-1",
                },
            }),
            SlashCommands.configure({
                suggestion,
            }),
            Image.configure({
                HTMLAttributes: {
                    class: "rounded-lg border border-border max-w-full h-auto",
                },
            }),
            Underline.configure({}),
            MobileIndent.configure({}),
            Link.configure({
                autolink: true,
                openOnClick: false,
                HTMLAttributes: {
                    class: "text-primary underline underline-offset-4 cursor-pointer hover:text-primary/80 transition-colors",
                },
            }),
            Highlight.configure({
                multicolor: true,
            }),
            TextAlign.configure({
                types: ["heading", "paragraph"],
            }),
            Table.configure({
                resizable: true,
                allowTableNodeSelection: true,
            }),
            TableRow,
            TableHeader,
            TableCell,
            Typography.configure({
                openDoubleQuote: false,
                closeDoubleQuote: false,
                openSingleQuote: false,
                closeSingleQuote: false,
            }),
            Mention.configure({
                HTMLAttributes: {
                    class: "mention bg-primary/10 text-primary font-medium py-0.5 px-1 rounded-md border border-primary/20",
                },
                suggestion: {
                    ...userSuggestion,
                    command: ({ editor, range, props: mentionProps }: any) => {
                        editor
                            .chain()
                            .focus()
                            .insertContentAt(range, [
                                {
                                    type: "mention",
                                    attrs: mentionProps,
                                },
                                {
                                    type: "text",
                                    text: " ",
                                },
                            ])
                            .run();

                        if (mentionProps.label) {
                            props.onUserMention?.(mentionProps.label);
                        }
                    }
                },
            }),
            Mention.extend({
                name: "noteMention",
            }).configure({
                suggestion: {
                    ...noteSuggestion,
                    char: "#",
                },
                HTMLAttributes: {
                    class: "note-mention bg-muted text-muted-foreground font-medium py-0.5 px-1 rounded-md border border-border italic cursor-pointer hover:bg-muted/80",
                },
            }),
            Dropcursor.configure({
                color: "var(--primary)",
                width: 2,
            }),
        ],
        // Use untrack so the editor doesn't re-initialize when props.content changes
        content: untrack(() => props.content) || "",
        editable: props.editable ?? true,
        onUpdate: ({ editor }) => {
            props.onUpdate(editor.getHTML());
        },
        editorProps: {
            attributes: {
                class: cn(
                    "prose prose-sm dark:prose-invert max-w-none focus:outline-none min-h-[150px]",
                    "prose-headings:font-semibold prose-h1:text-2xl prose-h2:text-xl prose-h3:text-lg",
                    "prose-p:my-1 prose-headings:my-2 prose-ul:my-1 prose-ol:my-1",
                    "prose-pre:bg-muted prose-pre:rounded-lg prose-pre:p-4",
                    "prose-img:rounded-lg prose-img:border prose-img:border-border prose-img:cursor-zoom-in",
                    // New Extension styles
                    "prose-a:text-primary prose-a:underline prose-a:underline-offset-4",
                    "prose-blockquote:border-l-4 prose-blockquote:border-primary prose-blockquote:pl-4 prose-blockquote:italic",
                    "[&_table]:border-collapse [&_table]:w-full [&_table]:my-4",
                    "[&_th]:border [&_th]:border-border [&_th]:bg-muted/50 [&_th]:p-2 [&_th]:text-left [&_th]:font-bold",
                    "[&_td]:border [&_td]:border-border [&_td]:p-2 [&_td]:align-top",
                    "[&_mark]:bg-primary/20 dark:[&_mark]:bg-primary/40 [&_mark]:text-foreground dark:[&_mark]:text-primary-foreground [&_mark]:px-0.5 [&_mark]:rounded-sm",
                    "[&_.mention]:mx-0.5 [&_.note-mention]:mx-0.5",
                    // Custom Task List Styling
                    "[&_ul[data-type='taskList']]:list-none [&_ul[data-type='taskList']]:p-0",
                    "[&_li[data-type='taskItem']]:flex [&_li[data-type='taskItem']]:items-start",
                    "[&_.tiptap-task-content]:flex-1 [&_.tiptap-task-content]:min-w-0 [&_.tiptap-task-content]:min-h-[1.5rem]",
                    "[&_.tiptap-task-content>p]:min-h-[1.5rem] [&_.tiptap-task-content>p]:m-0 [&_.tiptap-task-content>p]:w-full",
                    "[&_.tiptap-task-content>p:empty]:after:content-['\\200B'] [&_.tiptap-task-content>p:empty]:after:inline-block",
                    "[&_.tiptap-task-content>p>br]:after:content-['\\200B'] [&_.tiptap-task-content>p>br]:after:inline-block", // if tiptap adds br
                    props.class
                ),
            },
        },
    }));

    // Expose editor to parent
    createEffect(() => {
        const e = editor();
        if (e && props.onEditorReady) {
            props.onEditorReady(e);
        }
    });

    // Sync content updates from outside if needed (but only if NOT focused to avoid jumps)
    createEffect(() => {
        const content = props.content;
        const e = editor();
        if (e && content !== undefined && !e.isFocused && content !== e.getHTML()) {
            e.commands.setContent(content, { emitUpdate: false });
        }
    });

    // Handle note mention clicks
    createEffect(() => {
        const e = editor();
        if (!e) return;

        const handleClick = (event: MouseEvent) => {
            const target = event.target as HTMLElement;
            if (target.classList.contains('note-mention')) {
                const noteId = target.getAttribute('data-id');
                if (noteId) {
                    const rect = target.getBoundingClientRect();
                    setPreviewNote({ noteId, x: rect.left, y: rect.bottom + window.scrollY });
                    return;
                }
            }
            // Close preview if clicking elsewhere
            setPreviewNote(null);
        };

        const element = e.view.dom;
        if (element) {
            element.addEventListener('click', handleClick);
        }
    });

    // Handle full screen images as before
    return (
        <div class="relative w-full h-full flex flex-col">
            <div
                class="absolute -top-6 -left-4 -right-4 h-8 cursor-pointer group flex items-center justify-center z-10"
                onClick={() => {
                    const e = editor();
                    if (!e) return;
                    e.chain().insertContentAt(0, '<p></p>').focus('start').run();
                }}
                title="Add empty line at the top"
            >
                <span class="opacity-0 group-hover:opacity-100 text-[10px] uppercase font-bold text-muted-foreground tracking-widest transition-opacity mt-1">
                    Click to insert newline above
                </span>
            </div>
            <div
                ref={editorRef}
                class="w-full flex-1 cursor-text"
                onClick={(e) => {
                    const target = e.target as HTMLElement;
                    if (target.tagName.toLowerCase() === 'img') {
                        setFullscreenImage((target as HTMLImageElement).src);
                    } else if (e.target === editorRef) {
                        // Focus end if clicking on padding below content
                        editor()?.chain().focus().run();
                    }
                }}
            />

            {/* Note Preview Popover */}
            <Show when={previewNote() && store.notes.find(n => n.id === previewNote()!.noteId)}>
                {(note) => {
                    const pos = previewNote()!;
                    return (
                        <div
                            class="fixed z-[250] max-w-[280px] w-full bg-popover border border-border shadow-xl rounded-lg p-3 animate-in fade-in zoom-in-95 duration-200 pointer-events-auto"
                            style={{ left: `${Math.min(pos.x, window.innerWidth - 300)}px`, top: `${pos.y + 4}px` }}
                            onMouseDown={(e) => e.stopPropagation()}
                        >
                            <h4 class="font-bold text-sm mb-1 truncate text-foreground">{note().title}</h4>
                            <p class="text-xs text-muted-foreground line-clamp-3 mb-3 break-words whitespace-pre-wrap">
                                {note().content?.replace(/<[^>]*>?/gm, '') || "Empty note"}
                            </p>
                            <div class="flex justify-end gap-2">
                                <button
                                    type="button"
                                    class="text-xs px-2.5 py-1.5 rounded bg-muted hover:bg-muted/80 text-foreground font-medium transition-colors"
                                    onClick={(e) => {
                                        e.preventDefault();
                                        setPreviewNote(null);
                                    }}
                                >
                                    Close
                                </button>
                                <button
                                    type="button"
                                    class="text-xs px-2.5 py-1.5 rounded bg-primary hover:bg-primary/90 text-primary-foreground font-medium transition-colors shadow-sm"
                                    onClick={(e) => {
                                        e.preventDefault();
                                        if (props.onNoteOpen) {
                                            props.onNoteOpen(note().id);
                                        }
                                        setPreviewNote(null);
                                    }}
                                >
                                    Open Note
                                </button>
                            </div>
                        </div>
                    );
                }}
            </Show>

            <Show when={fullscreenImage()}>
                <div
                    class="fixed inset-0 z-[9999] p-4 bg-background/90 backdrop-blur-sm flex items-center justify-center animate-in fade-in duration-200 overflow-hidden"
                    onClick={(e) => {
                        if (e.target === e.currentTarget) {
                            setFullscreenImage(null);
                            resetZoom();
                        }
                    }}
                    onWheel={(e) => {
                        e.preventDefault();
                        const scaleSpeed = 0.05;
                        const delta = e.deltaY < 0 ? 1 : -1;
                        setZoomScale(s => Math.min(Math.max(1, s + delta * scaleSpeed), 5));
                    }}
                    onPointerDown={(e) => {
                        if (zoomScale() > 1 && e.target.tagName.toLowerCase() === 'img') {
                            setIsDragging(true);
                            setDragStart({ x: e.clientX - zoomOffset().x, y: e.clientY - zoomOffset().y });
                            (e.target as HTMLElement).setPointerCapture(e.pointerId);
                        }
                    }}
                    onPointerMove={(e) => {
                        if (isDragging()) {
                            setZoomOffset({
                                x: e.clientX - dragStart().x,
                                y: e.clientY - dragStart().y
                            });
                        }
                    }}
                    onPointerUp={(e) => {
                        setIsDragging(false);
                        (e.target as HTMLElement).releasePointerCapture(e.pointerId);
                    }}
                    onPointerCancel={(e) => {
                        setIsDragging(false);
                        (e.target as HTMLElement).releasePointerCapture(e.pointerId);
                    }}
                >
                    <button
                        class="absolute top-4 right-4 p-2 bg-background/50 hover:bg-background/80 rounded-full transition-colors z-[10000]"
                        onClick={(e) => {
                            e.stopPropagation();
                            setFullscreenImage(null);
                            resetZoom();
                        }}
                    >
                        <X size={24} />
                    </button>
                    <div
                        class="relative flex items-center justify-center w-full h-full pointer-events-none"
                    >
                        <img
                            src={fullscreenImage()!}
                            class={cn(
                                "max-w-full max-h-[90vh] object-contain rounded-md shadow-2xl pointer-events-auto transition-transform duration-75",
                                isDragging() ? "cursor-grabbing" : (zoomScale() > 1 ? "cursor-grab" : "cursor-zoom-in")
                            )}
                            style={{
                                transform: `translate(${zoomOffset().x}px, ${zoomOffset().y}px) scale(${zoomScale()})`,
                            }}
                            draggable={false}
                            onClick={(e) => {
                                e.stopPropagation();
                                if (zoomScale() === 1) {
                                    setZoomScale(2);
                                } else if (!isDragging()) {
                                    // Optional: Click to single-zoom-out or do nothing during pan
                                }
                            }}
                        />
                    </div>
                </div>
            </Show>
        </div>
    );
};
