"use client";

import * as React from "react";
import { useEffect, useMemo, useRef, useState } from "react";
import type { SerializedEditorState } from "lexical";
import { createEditor, $getRoot } from "lexical";
import { $generateNodesFromDOM } from "@lexical/html";
import { $generateHtmlFromNodes } from "@lexical/html";

import { HeadingNode, QuoteNode } from "@lexical/rich-text";
import { LinkNode, AutoLinkNode } from "@lexical/link";
import { ListNode, ListItemNode } from "@lexical/list";

import { cn } from "@/lib/utils";
import { Editor } from "@/components/blocks/editor-x/editor";

export interface RichTextEditorProps {
    value: string;
    onChange: (value: string) => void;
    className?: string;
    placeholder?: string;
}

/**
 * Lexical root باید هیچ‌وقت خالی نباشد.
 */
const ensureNonEmptyRoot = (
    s: SerializedEditorState | undefined
): SerializedEditorState | undefined => {
    if (!s) return s;

    const root: any = (s as any).root;
    if (!root || !Array.isArray(root.children)) return s;

    if (root.children.length > 0) return s;

    root.children.push({
        children: [],
        direction: null,
        format: "",
        indent: 0,
        type: "paragraph",
        version: 1,
        textFormat: 0,
        textStyle: "",
    });

    return s;
};

const isProbablyHtml = (v: string) => {
    const t = (v ?? "").trim();
    return t.startsWith("<") && t.includes(">");
};

const parseMaybeLexicalJson = (
    raw: string
): SerializedEditorState | undefined => {
    const v = (raw ?? "").trim();
    if (!v) return undefined;
    if (isProbablyHtml(v)) return undefined;

    try {
        const first = JSON.parse(v);

        // مستقیم آبجکت
        if (first && typeof first === "object" && "root" in first) {
            return ensureNonEmptyRoot(first as SerializedEditorState);
        }

        // double-encoded
        if (typeof first === "string") {
            const second = JSON.parse(first);
            if (second && typeof second === "object" && "root" in second) {
                return ensureNonEmptyRoot(second as SerializedEditorState);
            }
        }

        return undefined;
    } catch {
        return undefined;
    }
};

/**
 * HTML legacy → SerializedEditorState (JSON)
 * نکته: این تبدیل باید sync و deterministic باشد؛
 * بنابراین از parseEditorState استفاده می‌کنیم، نه update + getEditorState.
 */
const htmlToSerializedSync = (html: string): SerializedEditorState => {
    const tempEditor = createEditor({
        namespace: "TukanHtmlImport",
        nodes: [
            HeadingNode,
            QuoteNode,
            LinkNode,
            AutoLinkNode,
            ListNode,
            ListItemNode,
        ],
        onError: (e) => console.error(e),
    });

    const parser = new DOMParser();
    const dom = parser.parseFromString(html, "text/html");

    let out: SerializedEditorState | undefined = undefined;

    tempEditor.update(() => {
        const root = $getRoot();
        root.clear();

        const nodes = $generateNodesFromDOM(tempEditor, dom);
        root.append(...nodes);

        // ✅ خروجی را داخل همان update و با read بگیر
        tempEditor.getEditorState().read(() => {
            out = tempEditor.getEditorState().toJSON() as SerializedEditorState;
        });
    });

    return (ensureNonEmptyRoot(out) ??
        ensureNonEmptyRoot({
            root: {
                children: [],
                direction: null,
                format: "",
                indent: 0,
                type: "root",
                version: 1,
            },
        } as any)!) as SerializedEditorState;
};

export function RichTextEditor({
    value,
    onChange,
    className,
}: RichTextEditorProps) {
    const lastEmitted = useRef<string>("");
    const lastInput = useRef<string>("");
    const [mountKey, setMountKey] = useState(0);

    const htmlValue = useMemo(() => (value ?? "").trim(), [value]);

    useEffect(() => {
        // فقط وقتی value از بیرون (لود محصول) تغییر می‌کند remount کن
        if (!htmlValue) return;
        if (htmlValue === lastEmitted.current) return;
        if (htmlValue === lastInput.current) return;

        lastInput.current = htmlValue;
        setMountKey((k) => k + 1);
    }, [htmlValue]);

    return (
        <div className={cn(className)}>
            <Editor
                key={mountKey}
                initialHtml={htmlValue || "<p></p>"}
                onHtmlChange={(html: string) => {
                    const next = (html ?? "").trim();
                    if (!next) return;

                    // جلوگیری از loop
                    if (next === lastEmitted.current) return;
                    lastEmitted.current = next;

                    // ✅ این باید فیلد فرم را آپدیت کند => ذخیره درست می‌شود
                    onChange(next);
                }}
            />
        </div>
    );
}

export { RichTextEditor as default };
