"use client";

import Breadcrumbs from "@/components/user/components/Breadcrumbs";
import { useTranslation } from "@/hooks/useTranslation";
import {
    deleteChapter,
    getChapterDetail,
    publishChapter,
    updateChapter,
} from "@/libs/axios/modules/chapter";
import { getMyPostDetail } from "@/libs/axios/modules/post";
import { ChapterModel, PostModel } from "@/models";
import BlockquoteExtension from "@tiptap/extension-blockquote";
import BoldExtension from "@tiptap/extension-bold";
import DocumentExtension from "@tiptap/extension-document";
import HistoryExtension from "@tiptap/extension-history";
import ItalicExtension from "@tiptap/extension-italic";
import ParagraphExtension from "@tiptap/extension-paragraph";
import TextExtension from "@tiptap/extension-text";
import UnderlineExtension from "@tiptap/extension-underline";
import { EditorContent, useEditor } from "@tiptap/react";
import { format } from "date-fns";
import { AnimatePresence, motion } from "framer-motion";
import {
    AlertTriangle,
    Bold,
    Calendar,
    ChevronDown,
    Eye,
    Italic,
    Quote,
    Redo2,
    Send,
    Trash2,
    Underline,
    Undo2,
    X,
} from "lucide-react";
import { useRouter } from "next/navigation";
import { useCallback, useEffect, useRef, useState } from "react";
import { toast } from "react-toastify";

function wordLength(val: string): number {
    if (!val) return 0;
    const cleanText = val
        .replace(/<\/?strong>/g, "")
        .replace(/<\/?em>/g, "")
        .replace(/<\/?b>/g, "")
        .replace(/<\/?i>/g, "")
        .replace(/<\/?u>/g, "")
        .replace(/<\/?blockquote>/g, "")
        .replace(/<[^>]+>/g, " ")
        .replace(/&nbsp;/gi, " ")
        .replace(/&amp;/gi, "&")
        .replace(/&lt;/gi, "<")
        .replace(/&gt;/gi, ">")
        .replace(/(\r\n|\n|\r)/gm, " ")
        .replace(/\s+/g, " ")
        .trim();
    const matches = cleanText.match(/\b[\wÀ-ÿ]+(?:[-'][\wÀ-ÿ]+)*\b/g);
    return matches ? matches.length : 0;
}

function wordCount(html: string) {
    const clean = html
        .replace(/&nbsp;/gi, " ")
        .replace(/<p[^>]*>/gi, "<div>")
        .replace(/<\/p>/gi, "</div>")
        .replace(/<(?!\/?(div|b|i|u|blockquote)\b)[^>]*>/gi, "");
    return wordLength(clean);
}

function wordCountColor(count: number) {
    if (count < 800) return "text-amber-500 bg-amber-50";
    if (count <= 1200) return "text-green-600 bg-green-50";
    return "text-red-500 bg-red-50";
}


function PreviewModal({
    open, title, novelTitle, content, onClose,
}: {
    open: boolean;
    title: string;
    novelTitle: string;
    content: string;
    onClose: () => void;
}) {
    useEffect(() => {
        document.body.style.overflow = open ? "hidden" : "";
        return () => { document.body.style.overflow = ""; };
    }, [open]);

    if (!open) return null;
    return (
        <AnimatePresence>
            {open && (
                <>
                    <motion.div
                        className="fixed inset-0 z-9999 bg-black/40 backdrop-blur-sm"
                        onClick={onClose}
                        initial={{ opacity: 0 }}
                        animate={{ opacity: 1 }}
                        exit={{ opacity: 0 }}
                        transition={{ duration: 0.2 }}
                    />
                    <div className="fixed inset-0 z-10000 flex flex-col justify-center items-center">
                        <motion.div
                            className="flex flex-col bg-slate-50 w-full h-full md:rounded-2xl md:max-w-2xl md:max-h-[90vh] md:m-auto md:shadow-xl overflow-hidden"
                            initial={{ y: "100%" }}
                            animate={{ y: 0 }}
                            exit={{ y: "100%" }}
                            transition={{ type: "spring", stiffness: 300, damping: 30 }}
                        >
                            <div className="flex items-center px-6 py-4 bg-slate-50 shrink-0">
                                <p className="flex-1 text-lg font-semibold text-slate-800 capitalize">Preview</p>
                                <button onClick={onClose} className="p-2 hover:bg-slate-200 rounded-xl transition-colors cursor-pointer">
                                    <X className="w-5 h-5 text-slate-800" />
                                </button>
                            </div>
                            <div className="flex-1 overflow-y-auto">
                                <div className="px-6 pt-2 pb-3 flex flex-col gap-1">
                                    <h1 className="text-3xl font-bold text-slate-800 capitalize">{title || "Tanpa Judul"}</h1>
                                    <p className="text-sm text-slate-400 capitalize">{novelTitle}</p>
                                </div>
                                <div
                                    className="px-6 py-4 prose prose-slate prose-sm max-w-none leading-relaxed [&_p]:mb-4 [&_p:last-child]:mb-0 prose-blockquote:border-l-4 prose-blockquote:border-primary-300 prose-blockquote:text-slate-500 prose-blockquote:italic"
                                    dangerouslySetInnerHTML={{ __html: content }}
                                />
                            </div>
                        </motion.div>
                    </div>
                </>
            )}
        </AnimatePresence>
    );
}

function NotesModal({
    open,
    notes,
    onClose,
}: {
    open: boolean;
    notes: Array<{ title: string; description: string }>;
    onClose: () => void;
}) {
    useEffect(() => {
        document.body.style.overflow = open ? "hidden" : "";
        return () => { document.body.style.overflow = ""; };
    }, [open]);

    if (!open) return null;
    return (
        <AnimatePresence>
            {open && (
                <>
                    <motion.div
                        className="fixed inset-0 z-9999 bg-black/40 backdrop-blur-sm"
                        onClick={onClose}
                        initial={{ opacity: 0 }}
                        animate={{ opacity: 1 }}
                        exit={{ opacity: 0 }}
                    />
                    <div className="fixed inset-0 z-10000 flex items-end md:items-center justify-center">
                        <motion.div
                            className="bg-white w-full md:max-w-lg md:rounded-2xl rounded-t-2xl overflow-hidden shadow-xl"
                            initial={{ y: "100%" }}
                            animate={{ y: 0 }}
                            exit={{ y: "100%" }}
                            transition={{ type: "spring", stiffness: 300, damping: 30 }}
                        >
                            <div className="flex items-center justify-between px-6 py-4 border-b border-slate-100">
                                <div className="flex items-center gap-2">
                                    <AlertTriangle className="w-4 h-4 text-amber-500" />
                                    <span className="font-semibold text-slate-800">Catatan Revisi</span>
                                </div>
                                <button onClick={onClose} className="p-2 hover:bg-slate-100 rounded-xl transition-colors cursor-pointer">
                                    <X className="w-4 h-4 text-slate-600" />
                                </button>
                            </div>
                            <div className="p-6 flex flex-col gap-4 max-h-[60vh] overflow-y-auto">
                                {notes.map((note, i) => (
                                    <div key={i} className="flex flex-col gap-1 p-4 bg-amber-50 rounded-xl border border-amber-100">
                                        <p className="text-sm font-semibold text-amber-700">{note.title}</p>
                                        <p className="text-sm text-slate-600 leading-relaxed">{note.description}</p>
                                    </div>
                                ))}
                            </div>
                        </motion.div>
                    </div>
                </>
            )}
        </AnimatePresence>
    );
}

function ConfirmModal({
    open,
    title,
    description,
    confirmLabel,
    danger,
    loading,
    onConfirm,
    onClose,
}: {
    open: boolean;
    title: string;
    description: string;
    confirmLabel: string;
    danger?: boolean;
    loading?: boolean;
    onConfirm: () => void;
    onClose: () => void;
}) {
    if (!open) return null;
    return (
        <AnimatePresence>
            {open && (
                <>
                    <motion.div
                        className="fixed inset-0 z-9999 bg-black/40 backdrop-blur-sm"
                        onClick={onClose}
                        initial={{ opacity: 0 }}
                        animate={{ opacity: 1 }}
                        exit={{ opacity: 0 }}
                    />
                    <div className="fixed inset-0 z-10000 flex items-center justify-center p-4">
                        <motion.div
                            className="bg-white rounded-2xl shadow-xl p-6 w-full max-w-sm flex flex-col gap-4"
                            initial={{ scale: 0.9, opacity: 0 }}
                            animate={{ scale: 1, opacity: 1 }}
                            exit={{ scale: 0.9, opacity: 0 }}
                            transition={{ type: "spring", stiffness: 300, damping: 25 }}
                        >
                            <div className="flex flex-col gap-1.5">
                                <p className="font-semibold text-slate-800">{title}</p>
                                <p className="text-sm text-slate-500">{description}</p>
                            </div>
                            <div className="flex gap-2 justify-end">
                                <button
                                    onClick={onClose}
                                    disabled={loading}
                                    className="px-4 py-2 text-sm text-slate-600 hover:bg-slate-100 rounded-xl transition-colors cursor-pointer"
                                >
                                    Batal
                                </button>
                                <button
                                    onClick={onConfirm}
                                    disabled={loading}
                                    className={`px-4 py-2 text-sm font-semibold rounded-xl transition-colors cursor-pointer
                                        ${danger
                                            ? "bg-red-500 text-white hover:bg-red-600"
                                            : "bg-primary-500 text-white hover:bg-primary-600"}
                                        ${loading ? "opacity-60 cursor-not-allowed" : ""}`}
                                >
                                    {loading ? "Memproses..." : confirmLabel}
                                </button>
                            </div>
                        </motion.div>
                    </div>
                </>
            )}
        </AnimatePresence>
    );
}

function OptionsDropdown({
    open,
    canPublish,
    onPreview,
    onPublish,
    onDelete,
    onClose,
}: {
    open: boolean;
    canPublish: boolean;
    onPreview: () => void;
    onPublish: () => void;
    onDelete: () => void;
    onClose: () => void;
}) {
    useEffect(() => {
        if (!open) return;
        const handler = (e: MouseEvent) => {
            const target = e.target as HTMLElement;
            if (!target.closest("[data-options-dropdown]")) onClose();
        };
        document.addEventListener("mousedown", handler);
        return () => document.removeEventListener("mousedown", handler);
    }, [open, onClose]);

    return (
        <div className="relative" data-options-dropdown>
            <AnimatePresence>
                {open && (
                    <motion.div
                        className="absolute right-0 top-full mt-2 bg-white rounded-2xl shadow-xl border border-slate-100 w-52 overflow-hidden z-50"
                        initial={{ opacity: 0, y: -8, scale: 0.96 }}
                        animate={{ opacity: 1, y: 0, scale: 1 }}
                        exit={{ opacity: 0, y: -8, scale: 0.96 }}
                        transition={{ duration: 0.15 }}
                    >
                        <button
                            onClick={onPreview}
                            className="w-full flex items-center gap-3 px-4 py-3 text-sm text-slate-700 hover:bg-slate-50 transition-colors cursor-pointer"
                        >
                            <Eye className="w-4 h-4 text-slate-400" />
                            Preview
                        </button>
                        {canPublish && (
                            <button
                                onClick={onPublish}
                                className="w-full flex items-center gap-3 px-4 py-3 text-sm text-slate-700 hover:bg-slate-50 transition-colors cursor-pointer border-t border-slate-50"
                            >
                                <Send className="w-4 h-4 text-green-500" />
                                Publikasikan
                            </button>
                        )}
                        <button
                            onClick={onDelete}
                            className="w-full flex items-center gap-3 px-4 py-3 text-sm text-red-500 hover:bg-red-50 transition-colors cursor-pointer border-t border-slate-50"
                        >
                            <Trash2 className="w-4 h-4" />
                            Hapus Chapter
                        </button>
                    </motion.div>
                )}
            </AnimatePresence>
        </div>
    );
}

function ToolbarBtn({
    active, disabled, onClick, children, title,
}: {
    active?: boolean;
    disabled?: boolean;
    onClick: () => void;
    children: React.ReactNode;
    title?: string;
}) {
    return (
        <button
            type="button"
            title={title}
            onClick={onClick}
            disabled={disabled}
            className={`w-9 h-9 flex items-center justify-center rounded-lg transition-all cursor-pointer
                ${active ? "bg-slate-900 text-white" : "text-slate-500 hover:bg-slate-100 hover:text-slate-800"}
                ${disabled ? "opacity-30 cursor-not-allowed pointer-events-none" : ""}`}
        >
            {children}
        </button>
    );
}

interface Props {
    token: string;
    postId: string;
    chapterId: string;
}

export default function EditChapterPage({ token, postId, chapterId }: Props) {
    const router = useRouter();
    const { t } = useTranslation();

    const [novel, setNovel] = useState<PostModel | null>(null);
    const [chapter, setChapter] = useState<ChapterModel | null>(null);
    const [title, setTitle] = useState("");
    const [publishedAt, setPublishedAt] = useState<Date>(new Date());
    const [words, setWords] = useState(0);
    const [notes, setNotes] = useState<Array<{ title: string; description: string }>>([]);

    const [saving, setSaving] = useState(false);
    const [deleting, setDeleting] = useState(false);
    const [publishing, setPublishing] = useState(false);
    const [loading, setLoading] = useState(true);

    const [showPreview, setShowPreview] = useState(false);
    const [showNotes, setShowNotes] = useState(false);
    const [showOptions, setShowOptions] = useState(false);
    const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
    const [showPublishConfirm, setShowPublishConfirm] = useState(false);

    const dateRef = useRef<HTMLInputElement>(null);

    const editor = useEditor({
        immediatelyRender: false,
        extensions: [
            DocumentExtension,
            ParagraphExtension,
            TextExtension,
            BoldExtension,
            ItalicExtension,
            UnderlineExtension,
            BlockquoteExtension,
            HistoryExtension,
        ],
        content: "",
        onUpdate: ({ editor }) => {
            setWords(wordCount(editor.getHTML()));
        },
        editorProps: {
            attributes: {
                class: "outline-none min-h-[400px] px-6 py-6 text-sm text-slate-800 leading-relaxed prose prose-slate prose-sm max-w-none [&_p]:mb-4 [&_p:last-child]:mb-0 prose-blockquote:border-l-4 prose-blockquote:border-primary-300 prose-blockquote:pl-4 prose-blockquote:text-slate-500 prose-blockquote:italic",
            },
        },
    });

    const canSave = !!(title && editor && !editor.isEmpty && publishedAt);

    useEffect(() => {
        const load = async () => {
            try {
                const [{ data: novelRes }, { data: chapterRes }] = await Promise.all([
                    getMyPostDetail(token, postId),
                    getChapterDetail(chapterId),
                ]);
                if (novelRes?.data) setNovel(novelRes.data);
                if (chapterRes?.data) {
                    const c = chapterRes.data;
                    setChapter(c);
                    setTitle(c.title);
                    setPublishedAt(new Date(c.published_at));
                    setWords(c.total_words ?? 0);
                    setNotes(c.notes ?? []);
                    editor?.commands.setContent(c.description);
                }
            } catch (err) {
                console.error(err);
            } finally {
                setLoading(false);
            }
        };
        load();
    }, [chapterId, postId, token, editor]);

    const onSave = useCallback(async () => {
        if (!canSave || saving || !editor) return;
        if (words > 1200) {
            toast.error(t("errors.maxLength"));
            return;
        }
        setSaving(true);
        try {
            await updateChapter(token, {
                id: chapterId,
                title,
                description: editor.getHTML(),
                post_id: postId,
                total_words: words,
                published_at: publishedAt,
            });
            toast.success("Chapter berhasil diperbarui");
            router.back();
        } catch (err: any) {
            toast.error(err?.data?.message ?? err.message ?? "Terjadi kesalahan");
        } finally {
            setSaving(false);
        }
    }, [canSave, saving, editor, title, chapterId, postId, words, publishedAt, token, router]);

    const onDelete = useCallback(async () => {
        setDeleting(true);
        try {
            await deleteChapter(token, { id: chapterId });
            toast.success("Chapter berhasil dihapus");
            router.back();
        } catch (err: any) {
            toast.error(err?.data?.message ?? err.message ?? "Terjadi kesalahan");
        } finally {
            setDeleting(false);
            setShowDeleteConfirm(false);
        }
    }, [token, chapterId, router]);

    const onPublish = useCallback(async () => {
        if (!editor) return;
        setPublishing(true);
        try {
            await publishChapter(token, {
                id: chapterId,
                title,
                description: editor.getHTML(),
                post_id: postId,
                total_words: words,
                published_at: publishedAt,
            });
            toast.success("Chapter berhasil dipublikasikan");
            router.back();
        } catch (err: any) {
            toast.error(err?.data?.message ?? err.message ?? "Terjadi kesalahan");
        } finally {
            setPublishing(false);
            setShowPublishConfirm(false);
        }
    }, [token, chapterId, title, editor, postId, words, publishedAt, router]);

    const toInputValue = (d: Date) => format(d, "yyyy-MM-dd'T'HH:mm");

    if (loading) {
        return (
            <div className="flex flex-col gap-6 w-full animate-pulse">
                <div className="h-8 bg-slate-100 rounded-xl w-64" />
                <div className="h-14 bg-slate-100 rounded-xl" />
                <div className="h-96 bg-slate-100 rounded-xl" />
            </div>
        );
    }

    return (
        <div className="flex flex-col gap-6 w-full">
            <Breadcrumbs
                title="Dashboard"
                subtitle={[
                    { title: "Daftar Novel", href: "/user/novel" },
                    { title: novel?.title || "", href: "/user/novel" },
                    { title: "Edit Chapter", href: `/user/novel/chapter/${postId}/edit/${chapterId}` },
                ]}
                href="/user"
            />

            <div className="sticky top-0 z-10 bg-white border-b border-slate-100 rounded-t-xl shadow-sm">

                <div className="flex items-center justify-between px-4 py-3">
                    <div className="flex items-center gap-2">
                        <button
                            onClick={() => router.back()}
                            className="w-9 h-9 rounded-xl border border-slate-200 flex items-center justify-center hover:bg-slate-50 transition-colors cursor-pointer"
                        >
                            <svg className="w-4 h-4 text-slate-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
                            </svg>
                        </button>
                        <span className="text-base font-semibold text-slate-800">Edit Bab</span>
                    </div>

                    <div className="flex items-center gap-2">
                        <button
                            onClick={onSave}
                            disabled={!canSave || saving}
                            className={`px-4 py-1.5 rounded-full text-sm font-semibold border transition-all cursor-pointer
                                ${canSave && !saving
                                    ? "border-primary-500 text-primary-500 hover:bg-primary-50"
                                    : "border-slate-200 text-slate-300 cursor-not-allowed"}`}
                        >
                            {saving ? "Menyimpan..." : "Simpan"}
                        </button>

                        <div className="relative">
                            <button
                                onClick={() => setShowOptions((v) => !v)}
                                className="w-9 h-9 flex items-center justify-center rounded-xl border border-slate-200 hover:bg-slate-50 transition-colors cursor-pointer"
                            >
                                <ChevronDown className="w-4 h-4 text-slate-600" />
                            </button>
                            <OptionsDropdown
                                open={showOptions}
                                canPublish={words >= 800}
                                onPreview={() => { setShowOptions(false); setShowPreview(true); }}
                                onPublish={() => { setShowOptions(false); setShowPublishConfirm(true); }}
                                onDelete={() => { setShowOptions(false); setShowDeleteConfirm(true); }}
                                onClose={() => setShowOptions(false)}
                            />
                        </div>
                    </div>
                </div>

                <div className="flex items-center gap-2 px-4 bg-slate-50 border-t border-slate-100">
                    <input
                        type="text"
                        value={title}
                        onChange={(e) => setTitle(e.target.value)}
                        placeholder="Tulis judul bab..."
                        className="flex-1 py-3 bg-transparent text-sm text-slate-800 placeholder:text-slate-400 outline-none font-medium"
                    />
                    {notes.length > 0 && (
                        <button
                            onClick={() => setShowNotes(true)}
                            className="flex items-center gap-1 px-2.5 py-1 rounded-full bg-amber-50 border border-amber-200 text-amber-600 text-xs font-semibold cursor-pointer hover:bg-amber-100 transition-colors shrink-0"
                        >
                            <AlertTriangle className="w-3 h-3" />
                            {notes.length} Revisi
                        </button>
                    )}
                </div>

                <div
                    className="flex items-center gap-2 px-4 py-2.5 bg-slate-50 border-t border-slate-100 cursor-pointer hover:bg-slate-100 transition-colors"
                    onClick={() => dateRef.current?.showPicker()}
                >
                    <Calendar className="w-4 h-4 text-slate-400 shrink-0" />
                    <span className="text-xs text-slate-400">
                        Tanggal Terbit:{" "}
                        <span className="font-semibold text-slate-700">
                            {format(publishedAt, "dd MMM yyyy, HH:mm")}
                        </span>
                    </span>
                    <input
                        ref={dateRef}
                        type="datetime-local"
                        value={toInputValue(publishedAt)}
                        onChange={(e) => e.target.value && setPublishedAt(new Date(e.target.value))}
                        className="sr-only"
                        readOnly
                    />
                </div>

                <div className="flex items-center gap-1 px-3 py-2 border-t border-slate-100 bg-white">
                    <ToolbarBtn title="Bold" active={editor?.isActive("bold")} onClick={() => editor?.chain().focus().toggleBold().run()}>
                        <Bold className="w-4 h-4" />
                    </ToolbarBtn>
                    <ToolbarBtn title="Italic" active={editor?.isActive("italic")} onClick={() => editor?.chain().focus().toggleItalic().run()}>
                        <Italic className="w-4 h-4" />
                    </ToolbarBtn>
                    <ToolbarBtn title="Underline" active={editor?.isActive("underline")} onClick={() => editor?.chain().focus().toggleUnderline().run()}>
                        <Underline className="w-4 h-4" />
                    </ToolbarBtn>
                    <ToolbarBtn title="Blockquote" active={editor?.isActive("blockquote")} onClick={() => editor?.chain().focus().toggleBlockquote().run()}>
                        <Quote className="w-4 h-4" />
                    </ToolbarBtn>
                    <div className="w-px h-5 bg-slate-200 mx-1" />
                    <ToolbarBtn title="Undo" disabled={!editor?.can().undo()} onClick={() => editor?.chain().focus().undo().run()}>
                        <Undo2 className="w-4 h-4" />
                    </ToolbarBtn>
                    <ToolbarBtn title="Redo" disabled={!editor?.can().redo()} onClick={() => editor?.chain().focus().redo().run()}>
                        <Redo2 className="w-4 h-4" />
                    </ToolbarBtn>
                    <div className="ml-auto flex items-center gap-2">
                        <button
                            onClick={() => setShowPreview(true)}
                            className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs text-slate-500 hover:bg-slate-100 transition-colors cursor-pointer"
                        >
                            <Eye className="w-3.5 h-3.5" />
                            <span>Preview</span>
                        </button>
                        <span className={`text-xs font-semibold px-2.5 py-1 rounded-full ${wordCountColor(words)}`}>
                            {words} kata
                        </span>
                    </div>
                </div>
            </div>

            <div className="bg-white min-h-screen rounded-xl shadow-sm" onClick={() => editor?.commands.focus()}>
                <EditorContent editor={editor} />
            </div>

            <div className="sticky bottom-0 bg-green-600 px-6 py-3 flex items-center justify-end gap-2">
                <span className="text-xs text-white font-medium">{words} kata</span>
                <span className="text-xs text-green-200">(800 – 1.200 kata per bab)</span>
            </div>

            <PreviewModal
                open={showPreview}
                title={title}
                novelTitle={novel?.title ?? ""}
                content={editor?.getHTML() ?? ""}
                onClose={() => setShowPreview(false)}
            />

            <NotesModal
                open={showNotes}
                notes={notes}
                onClose={() => setShowNotes(false)}
            />

            <ConfirmModal
                open={showDeleteConfirm}
                title="Hapus Chapter"
                description="Chapter ini akan dihapus permanen dan tidak dapat dikembalikan."
                confirmLabel="Hapus"
                danger
                loading={deleting}
                onConfirm={onDelete}
                onClose={() => setShowDeleteConfirm(false)}
            />

            <ConfirmModal
                open={showPublishConfirm}
                title="Publikasikan Chapter"
                description="Chapter akan dipublikasikan dan dapat dibaca oleh pembaca."
                confirmLabel="Publikasikan"
                loading={publishing}
                onConfirm={onPublish}
                onClose={() => setShowPublishConfirm(false)}
            />
        </div>
    );
}