"use client";

import * as React from "react";
import type { ReactNode } from "react";
import {
    DecoratorNode,
    DOMExportOutput,
    type LexicalEditor,
    type LexicalNode,
    type NodeKey,
    createEditor,
} from "lexical";
import { ParagraphNode, TextNode } from "lexical";

import ImageComponent from "@/components/editor/editor-ui/image-component";

export type ImagePayload = {
    src: string;
    altText?: string;
    width?: number;
    height?: number;
    // اختیاری: اگر خواستید بعداً از UI ست کنید
    align?: "left" | "center" | "right" | "justify";
    showCaption?: boolean;
    captionState?: string; // JSON string of caption editorState
};

type Align = "left" | "center" | "right" | "justify" | null;

function createCaptionEditor(initialStateJson?: string): LexicalEditor {
    const editor = createEditor({
        namespace: "TukanImageCaption",
        nodes: [ParagraphNode, TextNode],
        onError: (e) => console.error(e),
    });

    // اگر state اولیه داریم، اعمال کن
    if (initialStateJson) {
        try {
            const parsed = JSON.parse(initialStateJson);
            const es = editor.parseEditorState(parsed);
            editor.setEditorState(es);
        } catch {
            // ignore
        }
    }

    return editor;
}

export class ImageNode extends DecoratorNode<ReactNode> {
    __src: string;
    __altText: string;
    __width?: number;
    __height?: number;

    // ✅ امکانات مورد نیاز شما
    __align: Align;
    __showCaption: boolean;
    __captionEditor: LexicalEditor;
    __captionStateJson: string | null;

    static getType(): string {
        return "image";
    }

    getSrc(): string {
        return this.getLatest().__src;
    }

    getAltText(): string {
        return this.getLatest().__altText;
    }

    static clone(node: ImageNode): ImageNode {
        return new ImageNode(
            {
                src: node.__src,
                altText: node.__altText,
                width: node.__width,
                height: node.__height,
                align: node.__align ?? undefined,
                showCaption: node.__showCaption,
                captionState: node.__captionStateJson ?? undefined,
            },
            node.__key
        );
    }

    constructor(payload: ImagePayload, key?: NodeKey) {
        super(key);
        this.__src = payload.src;
        this.__altText = payload.altText ?? "";
        this.__width = typeof payload.width === "number" ? payload.width : undefined;
        this.__height = typeof payload.height === "number" ? payload.height : undefined;

        this.__align = payload.align ?? null;
        this.__showCaption = payload.showCaption ?? false;
        this.__captionStateJson = payload.captionState ?? null;
        this.__captionEditor = createCaptionEditor(
            this.__captionStateJson ?? undefined
        );
    }

    // ---------- Alignment API (برای ImageComponent/Toolbar) ----------
    getAlign(): Align {
        return this.getLatest().__align;
    }

    setAlign(align: Align): void {
        const writable = this.getWritable() as ImageNode;
        writable.__align = align;
    }

    // ---------- Caption/Size API (برای ImageResizer) ----------
    setShowCaption(show: boolean): void {
        const writable = this.getWritable() as ImageNode;
        writable.__showCaption = show;
    }

    setCaptionState(json: string): void {
        const writable = this.getWritable() as ImageNode;
        writable.__captionStateJson = json;
    }

    setWidthAndHeight(
        width?: number | "inherit",
        height?: number | "inherit"
    ): void {
        const writable = this.getWritable() as ImageNode;
        // lexical resizer گاهی "inherit" می‌دهد، شما عدد ذخیره می‌کنی
        writable.__width = typeof width === "number" ? width : undefined;
        writable.__height = typeof height === "number" ? height : undefined;
    }

    // ---------- JSON ----------
    static importJSON(serializedNode: any): ImageNode {
        const {
            src,
            altText,
            width,
            height,
            align,
            showCaption,
            captionState,
        } = serializedNode ?? {};

        return new ImageNode({
            src,
            altText,
            width,
            height,
            align,
            showCaption,
            captionState,
        });
    }

    exportJSON(): any {
        // ذخیره caption state
        let captionStateJson: string | null = this.__captionStateJson;
        try {
            const json = this.__captionEditor.getEditorState().toJSON();
            captionStateJson = JSON.stringify(json);
        } catch {
            // ignore
        }

        return {
            type: "image",
            version: 2,
            src: this.__src,
            altText: this.__altText,
            width: this.__width,
            height: this.__height,
            align: this.__align,
            showCaption: this.__showCaption,
            captionState: captionStateJson,
        };
    }

    // ---------- DOM import/export (برای HTML) ----------
    static importDOM(): Record<string, any> | null {
        return {
            img: (_domNode: Node) => {
                const domNode = _domNode as HTMLImageElement;
                return {
                    conversion: () => {
                        const src = domNode.getAttribute("src") || "";
                        const alt = domNode.getAttribute("alt") || "";
                        const widthAttr = domNode.getAttribute("width");
                        const heightAttr = domNode.getAttribute("height");
                        const width = widthAttr ? Number(widthAttr) : undefined;
                        const height = heightAttr
                            ? Number(heightAttr)
                            : undefined;

                        if (!src) return { node: null };

                        // Check for caption in figcaption
                        let captionState = null;
                        const parent = domNode.parentElement;
                        if (parent && parent.tagName === "FIGURE") {
                            const figcaption = parent.querySelector("figcaption");
                            if (figcaption && figcaption.textContent) {
                                // Construct a minimal Lexical JSON for the caption
                                const text = figcaption.textContent;
                                captionState = JSON.stringify({
                                    root: {
                                        children: [
                                            {
                                                children: [
                                                    {
                                                        detail: 0,
                                                        format: 0,
                                                        mode: "normal",
                                                        style: "",
                                                        text: text,
                                                        type: "text",
                                                        version: 1,
                                                    },
                                                ],
                                                direction: null,
                                                format: "",
                                                indent: 0,
                                                type: "paragraph",
                                                version: 1,
                                            },
                                        ],
                                        direction: null,
                                        format: "",
                                        indent: 0,
                                        type: "root",
                                        version: 1,
                                    },
                                });
                            }
                        }

                        // اگر img داخل عنصر align دار باشد، تا حد امکان بخوان
                        const ta = parent?.style?.textAlign;
                        const align =
                            ta === "left" ||
                                ta === "center" ||
                                ta === "right" ||
                                ta === "justify"
                                ? ta
                                : undefined;

                        return {
                            node: new ImageNode({
                                src,
                                altText: alt,
                                width,
                                height,
                                align,
                                showCaption: !!captionState,
                                captionState: captionState || undefined,
                            }),
                        };
                    },
                    priority: 2,
                };
            },
        };
    }

    exportDOM(): DOMExportOutput {
        // ✅ Use span wrapper to avoid breaking parent <p> (Phantom Lines)
        const element = document.createElement("span");
        element.className = "editor-image"; // helper class
        element.style.display = "inline-block"; // Allows text-align to work from parent

        const img = document.createElement("img");
        img.setAttribute("src", this.__src);
        if (this.__altText) img.setAttribute("alt", this.__altText);
        if (this.__width) img.setAttribute("width", String(this.__width));
        if (this.__height) img.setAttribute("height", String(this.__height));

        img.style.maxWidth = "100%";
        img.style.borderRadius = "8px";
        img.style.display = "block"; // img block inside inline-block span keeps it clean

        // If there's explicit alignment on the node, we can set it, but usually parent handles it.
        // If we want to support internal alignment:
        if (this.__align) {
            element.style.textAlign = this.__align;
        }

        element.appendChild(img);

        // ✅ Export Caption
        let captionText = "";

        // Try reading from parsed JSON
        if (this.__captionStateJson && this.__showCaption) {
            try {
                const state = JSON.parse(this.__captionStateJson);
                const root = state.root;
                if (root && root.children) {
                    const textParts = root.children.map((block: any) =>
                        block.children ? block.children.map((c: any) => c.text).join("") : ""
                    );
                    captionText = textParts.join("\n").trim();
                }
            } catch (e) { }
        }

        if (captionText) {
            const captionSpan = document.createElement("span");
            captionSpan.className = "editor-image-caption";
            captionSpan.innerText = captionText;
            captionSpan.style.display = "block"; // stacked below image
            captionSpan.style.fontSize = "14px";
            captionSpan.style.color = "#666";
            captionSpan.style.marginTop = "4px";
            captionSpan.style.textAlign = "center";
            element.appendChild(captionSpan);
        }

        return { element };
    }

    createDOM(): HTMLElement {
        // DecoratorNode نیاز به container دارد
        const span = document.createElement("span");
        return span;
    }

    updateDOM(): false {
        return false;
    }

    decorate(): ReactNode {
        // هر بار serialize caption state را به‌روز نگه دار
        try {
            const json = this.__captionEditor.getEditorState().toJSON();
            this.__captionStateJson = JSON.stringify(json);
        } catch {
            // ignore
        }

        // ✅ اینجا ریشه‌ی فعال شدن کپشن/ریسایز است
        return (
            <ImageComponent
                src={this.__src}
                altText={this.__altText}
                nodeKey={this.getKey()}
                width={this.__width ?? "inherit"}
                height={this.__height ?? "inherit"}
                maxWidth={1200}
                resizable={true}
                showCaption={this.__showCaption}
                caption={this.__captionEditor}
                captionsEnabled={true}
            />
        );
    }
}

export function $createImageNode(payload: ImagePayload): ImageNode {
    return new ImageNode(payload);
}

export function $isImageNode(
    node: LexicalNode | null | undefined
): node is ImageNode {
    return node instanceof ImageNode;
}
