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 TaskItem from "@tiptap/extension-task-item";
import Image from "@tiptap/extension-image";
import Underline from "@tiptap/extension-underline";
import { X } from "lucide-solid";
import { cn } from "@/lib/utils";

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

interface TaskEditorProps {
    content?: string;
    onUpdate: (html: string) => void;
    onEditorReady?: (editor: any) => void;
    editable?: boolean;
    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 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",
                },
            }),
            TaskItem.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,
            MobileIndent,
        ],
        // 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",
                    // 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",
                    "[&_li[data-type='taskItem']>label]:mr-3 [&_li[data-type='taskItem']>label]:mt-1 [&_li[data-type='taskItem']>label]:select-none",
                    "[&_li[data-type='taskItem']>label>input]:w-5 [&_li[data-type='taskItem']>label>input]:h-5 [&_li[data-type='taskItem']>label>input]:cursor-pointer",
                    "[&_li[data-type='taskItem']>div]:flex-1 [&_li[data-type='taskItem']>div]:min-h-[1.5rem]",
                    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 });
        }
    });

    return (
        <>
            <div
                ref={editorRef}
                class="w-full cursor-text"
                onClick={(e) => {
                    const target = e.target as HTMLElement;
                    if (target.tagName.toLowerCase() === 'img') {
                        setFullscreenImage((target as HTMLImageElement).src);
                    } else {
                        editor()?.chain().focus().run();
                    }
                }}
            />
            <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>
        </>
    );
};
