"use client";

import { useTranslation } from "@/hooks/useTranslation";
import {
    getChapterComment,
    getChapterCommentAuthenticated,
    storeChapterComment,
    storeChapterCommentReply,
} from "@/libs/axios/modules/chapter";
import { getComment, getCommentDetail } from "@/libs/axios/modules/comment";
import { withSlug } from "@/utils/slug";
import { countCoinsClaim, getCoinsClaim, postCoinsClaim } from "@/libs/axios/modules/reward";
import { ChapterModel, CommentModel, PostModel } from "@/models";
import { format } from "date-fns";
import { AnimatePresence, motion } from "framer-motion";
import {
    ArrowLeft,
    BookOpen,
    ChevronLeft,
    ChevronRight,
    Lock,
    MessageCircle,
    Minus,
    Moon,
    Plus,
    Send,
    Settings,
    Sun,
    X
} from "lucide-react";
import { useRouter } from "next/navigation";
import {
    useCallback,
    useEffect,
    useMemo,
    useRef,
    useState,
} from "react";
import { toast } from "react-toastify";

const FONT_FAMILIES = ["Georgia", "Palatino Linotype", "Merriweather"] as const;
const FONT_SIZES = [13, 14, 15, 16, 17, 18, 20, 22, 24];
const LINE_SPACINGS = [1.4, 1.6, 1.8, 2.0];
const MAX_IDLE_MINUTES = 2;
const MAX_CHAPTER_MINUTES = 5;

function initialName(name: string) {
    if (!name) return "?";
    return name.split(" ").slice(0, 2).map((w) => w[0]).join("").toUpperCase();
}

function Avatar({ avatar, name, size = "w-8 h-8" }: { avatar?: string; name: string; size?: string }) {
    return avatar ? (
        <img src={avatar} alt={name} className={`${size} rounded-full object-cover shrink-0`} />
    ) : (
        <div className={`${size} rounded-full bg-primary-500 flex items-center justify-center shrink-0`}>
            <span className="text-[10px] font-bold text-white">{initialName(name)}</span>
        </div>
    );
}

function SettingsPanel({
    open,
    fontSize,
    fontFamily,
    lineSpacing,
    darkMode,
    onFontSize,
    onFontFamily,
    onLineSpacing,
    onDarkMode,
    onClose,
}: {
    open: boolean;
    fontSize: number;
    fontFamily: string;
    lineSpacing: number;
    darkMode: boolean;
    onFontSize: (v: number) => void;
    onFontFamily: (v: string) => void;
    onLineSpacing: (v: number) => void;
    onDarkMode: (v: boolean) => void;
    onClose: () => void;
}) {
    return (
        <AnimatePresence>
            {open && (
                <>
                    <motion.div className="fixed inset-0 z-9998" onClick={onClose}
                        initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}
                    />
                    <motion.div
                        initial={{ opacity: 0, y: 20 }}
                        animate={{ opacity: 1, y: 0 }}
                        exit={{ opacity: 0, y: 20 }}
                        transition={{ type: "spring", stiffness: 300, damping: 30 }}
                        className={`fixed bottom-24 left-1/2 -translate-x-1/2 z-9999 w-85 max-w-[90vw] rounded-3xl shadow-2xl border p-6 flex flex-col gap-5
                            ${darkMode ? "bg-zinc-900 border-zinc-700" : "bg-white border-slate-100"}`}
                    >
                        <div className="flex flex-col gap-2">
                            <p className={`text-xs font-semibold uppercase tracking-widest ${darkMode ? "text-zinc-400" : "text-slate-400"}`}>Ukuran Font</p>
                            <div className="flex items-center gap-3">
                                <button onClick={() => onFontSize(Math.max(13, fontSize - 1))}
                                    className={`w-8 h-8 rounded-full flex items-center justify-center cursor-pointer transition-colors ${darkMode ? "bg-zinc-700 text-white" : "bg-slate-100 text-slate-700"}`}>
                                    <Minus className="w-3.5 h-3.5" />
                                </button>
                                <span className={`flex-1 text-center font-bold text-lg ${darkMode ? "text-white" : "text-slate-800"}`}>{fontSize}px</span>
                                <button onClick={() => onFontSize(Math.min(24, fontSize + 1))}
                                    className={`w-8 h-8 rounded-full flex items-center justify-center cursor-pointer transition-colors ${darkMode ? "bg-zinc-700 text-white" : "bg-slate-100 text-slate-700"}`}>
                                    <Plus className="w-3.5 h-3.5" />
                                </button>
                            </div>
                        </div>

                        <div className="flex flex-col gap-2">
                            <p className={`text-xs font-semibold uppercase tracking-widest ${darkMode ? "text-zinc-400" : "text-slate-400"}`}>Font</p>
                            <div className="flex gap-2">
                                {FONT_FAMILIES.map((f) => (
                                    <button key={f} onClick={() => onFontFamily(f)}
                                        className={`flex-1 py-2 rounded-xl text-xs font-medium transition-all cursor-pointer
                                            ${fontFamily === f
                                                ? "bg-primary-500 text-white"
                                                : darkMode ? "bg-zinc-700 text-zinc-300" : "bg-slate-100 text-slate-600"}`}
                                        style={{ fontFamily: f }}
                                    >
                                        {f.split(" ")[0]}
                                    </button>
                                ))}
                            </div>
                        </div>

                        <div className="flex flex-col gap-2">
                            <p className={`text-xs font-semibold uppercase tracking-widest ${darkMode ? "text-zinc-400" : "text-slate-400"}`}>Spasi Baris</p>
                            <div className="flex gap-2">
                                {LINE_SPACINGS.map((s) => (
                                    <button key={s} onClick={() => onLineSpacing(s)}
                                        className={`flex-1 py-2 rounded-xl text-xs font-medium transition-all cursor-pointer
                                            ${lineSpacing === s
                                                ? "bg-primary-500 text-white"
                                                : darkMode ? "bg-zinc-700 text-zinc-300" : "bg-slate-100 text-slate-600"}`}
                                    >
                                        {s}
                                    </button>
                                ))}
                            </div>
                        </div>

                        <div className="flex gap-2">
                            <button onClick={() => onDarkMode(false)}
                                className={`flex-1 flex items-center justify-center gap-2 py-3 rounded-2xl text-sm font-semibold transition-all cursor-pointer
                                    ${!darkMode ? "bg-slate-800 text-white" : "bg-slate-100 text-slate-600"}`}>
                                <Sun className="w-4 h-4" /> Terang
                            </button>
                            <button onClick={() => onDarkMode(true)}
                                className={`flex-1 flex items-center justify-center gap-2 py-3 rounded-2xl text-sm font-semibold transition-all cursor-pointer
                                    ${darkMode ? "bg-zinc-700 text-white" : "bg-slate-100 text-slate-600"}`}>
                                <Moon className="w-4 h-4" /> Gelap
                            </button>
                        </div>
                    </motion.div>
                </>
            )}
        </AnimatePresence>
    );
}

function ChaptersPanel({
    open,
    chapters,
    currentId,
    novelTitle,
    onSelect,
    onClose,
    darkMode,
}: {
    open: boolean;
    chapters: ChapterModel[];
    currentId: string;
    novelTitle: string;
    onSelect: (c: ChapterModel) => void;
    onClose: () => void;
    darkMode: boolean;
}) {
    const activeRef = useRef<HTMLButtonElement>(null);
    useEffect(() => {
        if (open) setTimeout(() => activeRef.current?.scrollIntoView({ block: "center", behavior: "smooth" }), 200);
    }, [open]);

    useEffect(() => {
        document.body.style.overflow = open ? "hidden" : "";
        return () => { document.body.style.overflow = ""; };
    }, [open]);

    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 justify-center">
                        <motion.div
                            className={`w-full max-w-lg rounded-t-3xl overflow-hidden shadow-2xl flex flex-col max-h-[80vh]
                                ${darkMode ? "bg-zinc-900" : "bg-white"}`}
                            initial={{ y: "100%" }} animate={{ y: 0 }} exit={{ y: "100%" }}
                            transition={{ type: "spring", stiffness: 300, damping: 30 }}
                        >
                            <div className={`px-6 pt-5 pb-4 border-b ${darkMode ? "border-zinc-700" : "border-slate-100"}`}>
                                <p className={`font-bold text-lg ${darkMode ? "text-white" : "text-slate-800"}`}>{novelTitle}</p>
                                <p className={`text-xs mt-0.5! ${darkMode ? "text-zinc-400" : "text-slate-400"}`}>{chapters.length} bab</p>
                            </div>
                            <div className="flex-1 overflow-y-auto">
                                {chapters.map((c) => (
                                    <button
                                        key={c.id}
                                        ref={c.id === currentId ? activeRef : undefined}
                                        onClick={() => { onSelect(c); onClose(); }}
                                        className={`w-full flex items-center justify-between px-6 py-4 border-b text-left transition-colors cursor-pointer
                                            ${c.id === currentId
                                                ? darkMode ? "border-primary-400 bg-primary-500/10" : "border-primary-300 bg-primary-50"
                                                : darkMode ? "border-zinc-800 hover:bg-zinc-800" : "border-slate-50 hover:bg-slate-50"}`}
                                    >
                                        <span className={`text-sm font-medium ${c.id === currentId
                                            ? "text-primary-500"
                                            : c.is_paid ? darkMode ? "text-zinc-500" : "text-slate-400"
                                                : darkMode ? "text-white" : "text-slate-800"}`}>
                                            {String(c.order).padStart(2, "0")} {c.title}
                                        </span>
                                        {c.is_paid && <Lock className="w-3.5 h-3.5 text-slate-400 shrink-0" />}
                                    </button>
                                ))}
                            </div>
                        </motion.div>
                    </div>
                </>
            )}
        </AnimatePresence>
    );
}

function CommentsPanel({
    open,
    chapterId,
    token,
    darkMode,
    onClose,
}: {
    open: boolean;
    chapterId: string;
    token?: string;
    darkMode: boolean;
    onClose: () => void;
}) {
    const { t } = useTranslation();
    const [comments, setComments] = useState<CommentModel[]>([]);
    const [loading, setLoading] = useState(false);
    const [text, setText] = useState("");
    const [replyTo, setReplyTo] = useState<CommentModel | null>(null);
    const [replyComments, setReplyComments] = useState<CommentModel[]>([]);
    const [replyLoading, setReplyLoading] = useState(false);
    const [replyText, setReplyText] = useState("");
    const [showReply, setShowReply] = useState(false);
    const inputRef = useRef<HTMLTextAreaElement>(null);
    const scrollRef = useRef<HTMLDivElement>(null);

    useEffect(() => {
        document.body.style.overflow = open ? "hidden" : "";
        return () => { document.body.style.overflow = ""; };
    }, [open]);

    useEffect(() => {
        if (open) fetchComments();
    }, [open]);

    const fetchComments = async () => {
        setLoading(true);
        try {
            const { data: res } = token
                ? await getChapterCommentAuthenticated(token, { chapter_id: chapterId })
                : await getChapterComment({ chapter_id: chapterId });
            if (res?.data) setComments(res.data);
        } finally { setLoading(false); }
    };

    const fetchReplies = async (commentId: string) => {
        setReplyLoading(true);
        try {
            const [detailRes, repliesRes] = await Promise.all([
                getCommentDetail(commentId),
                getComment({ id: commentId }),
            ]);
            if (detailRes.data?.data) setReplyTo(detailRes.data.data);
            if (repliesRes.data?.data) setReplyComments(repliesRes.data.data);
        } finally { setReplyLoading(false); }
    };

    const openReply = (comment: CommentModel) => {
        setShowReply(true);
        fetchReplies(comment.id);
    };

    const submitComment = async () => {
        if (!text.trim() || !token) return;
        try {
            await storeChapterComment(token, { id: chapterId, text });
            setText("");
            fetchComments();
            setTimeout(() => scrollRef.current?.scrollTo({ top: scrollRef.current.scrollHeight, behavior: "smooth" }), 100);
        } catch (err: any) {
            toast.error(err?.data?.message ?? "Gagal mengirim");
        }
    };

    const submitReply = async () => {
        if (!replyText.trim() || !replyTo || !token) return;
        try {
            await storeChapterCommentReply(token, { id: replyTo.id, text: replyText });
            setReplyText("");
            fetchReplies(replyTo.id);
        } catch (err: any) {
            toast.error(err?.data?.message ?? "Gagal mengirim");
        }
    };

    const bg = darkMode ? "bg-zinc-900" : "bg-white";
    const border = darkMode ? "border-zinc-700" : "border-slate-100";
    const textPrimary = darkMode ? "text-white" : "text-slate-800";
    const textSecondary = darkMode ? "text-zinc-400" : "text-slate-400";
    const inputBg = darkMode ? "bg-zinc-800 text-white placeholder:text-zinc-500" : "bg-slate-50 text-slate-800 placeholder:text-slate-400";

    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 justify-center">
                        <motion.div
                            className={`w-full max-w-lg rounded-t-3xl overflow-hidden shadow-2xl flex flex-col max-h-[85vh] ${bg}`}
                            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 pt-5 pb-4 border-b ${border} shrink-0`}>
                                <div className="flex items-center gap-2">
                                    {showReply && (
                                        <button onClick={() => setShowReply(false)}
                                            className={`w-8 h-8 rounded-xl flex items-center justify-center cursor-pointer ${darkMode ? "hover:bg-zinc-700" : "hover:bg-slate-100"}`}>
                                            <ChevronLeft className={`w-4 h-4 ${textPrimary}`} />
                                        </button>
                                    )}
                                    <p className={`font-bold text-base ${textPrimary}`}>
                                        {showReply ? "Balasan" : `Komentar (${comments.length})`}
                                    </p>
                                </div>
                                <button onClick={onClose}
                                    className={`w-8 h-8 rounded-xl flex items-center justify-center cursor-pointer ${darkMode ? "hover:bg-zinc-700" : "hover:bg-slate-100"}`}>
                                    <X className={`w-4 h-4 ${textPrimary}`} />
                                </button>
                            </div>

                            <div ref={scrollRef} className="flex-1 overflow-y-auto">
                                {!showReply ? (
                                    loading ? (
                                        <div className="flex flex-col gap-3 p-6">
                                            {Array.from({ length: 4 }).map((_, i) => (
                                                <div key={i} className={`flex gap-3 animate-pulse`}>
                                                    <div className={`w-8 h-8 rounded-full shrink-0 ${darkMode ? "bg-zinc-700" : "bg-slate-100"}`} />
                                                    <div className="flex-1 flex flex-col gap-2">
                                                        <div className={`h-3 rounded-full w-1/3 ${darkMode ? "bg-zinc-700" : "bg-slate-100"}`} />
                                                        <div className={`h-3 rounded-full w-2/3 ${darkMode ? "bg-zinc-700" : "bg-slate-100"}`} />
                                                    </div>
                                                </div>
                                            ))}
                                        </div>
                                    ) : comments.length === 0 ? (
                                        <p className={`text-sm text-center py-12 ${textSecondary}`}>Belum ada komentar</p>
                                    ) : (
                                        <div className="flex flex-col">
                                            {comments.map((c, i) => (
                                                <motion.div key={c.id}
                                                    initial={{ opacity: 0, y: 6 }} animate={{ opacity: 1, y: 0 }}
                                                    transition={{ delay: i * 0.03 }}
                                                    className={`flex gap-3 px-6 py-4 border-b ${border}`}
                                                >
                                                    <Avatar avatar={c.user?.avatar} name={c.user?.name ?? ""} />
                                                    <div className="flex-1 min-w-0">
                                                        <p className={`font-semibold text-sm ${textPrimary}`}>{c.user?.name}</p>
                                                        <p className={`text-sm mt-1! leading-relaxed ${textSecondary}`}>{c.text}</p>
                                                        <div className="flex items-center justify-between mt-2!">
                                                            <p className={`text-xs ${textSecondary}`}>{format(new Date(c.created_at), "dd MMM yyyy")}</p>
                                                            <button onClick={() => openReply(c)}
                                                                className={`flex items-center gap-1 text-xs cursor-pointer ${darkMode ? "text-zinc-400 hover:text-white" : "text-slate-400 hover:text-slate-700"}`}>
                                                                <MessageCircle className="w-3.5 h-3.5" />
                                                                {c.total_comments ?? 0}
                                                            </button>
                                                        </div>
                                                    </div>
                                                </motion.div>
                                            ))}
                                        </div>
                                    )
                                ) : (
                                    <div className="flex flex-col">
                                        {replyTo && (
                                            <div className={`px-6 py-5 border-b-4 ${border}`}>
                                                <div className="flex gap-3">
                                                    <Avatar avatar={replyTo.user?.avatar} name={replyTo.user?.name ?? ""} size="w-9 h-9" />
                                                    <div>
                                                        <p className={`font-semibold text-sm ${textPrimary}`}>{replyTo.user?.name}</p>
                                                        <p className={`text-sm mt-1! ${textSecondary}`}>{replyTo.text}</p>
                                                        <p className={`text-xs mt-2! ${textSecondary}`}>{format(new Date(replyTo.created_at), "dd MMM yyyy")}</p>
                                                    </div>
                                                </div>
                                            </div>
                                        )}
                                        {replyLoading ? (
                                            <div className="w-full flex justify-center">
                                                <div className={`w-6 h-6 border-2 border-primary-500 border-t-transparent rounded-full animate-spin mx-auto my-8!`} />
                                            </div>
                                        ) : replyComments.map((r, i) => (
                                            <div key={r.id} className={`flex gap-3 px-6 py-4 border-b ${border}`}>
                                                <Avatar avatar={r.user?.avatar} name={r.user?.name ?? ""} />
                                                <div className="flex-1">
                                                    <p className={`font-semibold text-sm ${textPrimary}`}>{r.user?.name}</p>
                                                    <p className={`text-sm mt-1! ${textSecondary}`}>{r.text}</p>
                                                    <p className={`text-xs mt-2! ${textSecondary}`}>{format(new Date(r.created_at), "dd MMM yyyy")}</p>
                                                </div>
                                            </div>
                                        ))}
                                    </div>
                                )}
                            </div>

                            {token && (
                                <div className={`px-4 py-3 border-t ${border} shrink-0`}>
                                    <div className={`flex items-end gap-2 rounded-2xl px-4 py-2 ${darkMode ? "bg-zinc-800" : "bg-slate-50"}`}>
                                        <textarea
                                            ref={inputRef}
                                            value={showReply ? replyText : text}
                                            onChange={(e) => showReply ? setReplyText(e.target.value) : setText(e.target.value)}
                                            placeholder={t("give me your feedback")}
                                            rows={1}
                                            className={`flex-1 text-sm outline-none resize-none bg-transparent leading-relaxed py-1 ${darkMode ? "text-white placeholder:text-zinc-500" : "text-slate-800 placeholder:text-slate-400"}`}
                                            onKeyDown={(e) => {
                                                if (e.key === "Enter" && !e.shiftKey) {
                                                    e.preventDefault();
                                                    showReply ? submitReply() : submitComment();
                                                }
                                            }}
                                        />
                                        <button
                                            onClick={showReply ? submitReply : submitComment}
                                            disabled={!(showReply ? replyText : text).trim()}
                                            className={`w-8 h-8 rounded-full flex items-center justify-center shrink-0 transition-all cursor-pointer
                                                ${(showReply ? replyText : text).trim() ? "bg-primary-500 text-white" : darkMode ? "bg-zinc-700 text-zinc-500" : "bg-slate-200 text-slate-400"}`}
                                        >
                                            <Send className="w-3.5 h-3.5" />
                                        </button>
                                    </div>
                                </div>
                            )}
                        </motion.div>
                    </div>
                </>
            )}
        </AnimatePresence>
    );
}

function FloatingToolbar({
    chapter,
    chapters,
    darkMode,
    readingMinutes,
    onPrev,
    onNext,
    onChapters,
    onComments,
    onSettings,
    onBack,
    hasPrev,
    hasNext,
    nextLocked,
    claimable,
    handleClaim
}: {
    chapter: ChapterModel;
    chapters: ChapterModel[];
    darkMode: boolean;
    readingMinutes: number;
    onPrev: () => void;
    onNext: () => void;
    onChapters: () => void;
    onComments: () => void;
    onSettings: () => void;
    onBack: () => void;
    hasPrev: boolean;
    hasNext: boolean;
    nextLocked: boolean;
    claimable: number | null;
    handleClaim: () => void;
}) {
    const [expanded, setExpanded] = useState(false);

    const bg = darkMode ? "bg-zinc-900/95 border-zinc-700" : "bg-white/95 border-slate-200";
    const iconColor = darkMode ? "text-zinc-300" : "text-slate-600";

    return (
        <motion.div
            className="fixed bottom-6 left-0 right-0 flex justify-center z-50 px-4"
            initial={{ y: 100, opacity: 0 }}
            animate={{ y: 0, opacity: 1 }}
            transition={{ delay: 0.5, type: "spring", stiffness: 200, damping: 22 }}
        >
            <motion.div
                layout
                transition={{ type: "spring", stiffness: 400, damping: 35 }}
                className={`${bg} backdrop-blur-xl border rounded-[28px] shadow-2xl overflow-hidden`}
            >
                <div className="flex items-center gap-1 px-2 py-2">
                    <button onClick={onBack}
                        className={`w-10 h-10 rounded-full flex items-center justify-center transition-colors cursor-pointer hover:bg-slate-100/20 ${iconColor}`}>
                        <ArrowLeft className="w-4 h-4" />
                    </button>

                    <div className={`w-px h-5 ${darkMode ? "bg-zinc-700" : "bg-slate-200"}`} />

                    <button onClick={onPrev} disabled={!hasPrev}
                        className={`w-10 h-10 rounded-full flex items-center justify-center transition-colors cursor-pointer ${!hasPrev ? "opacity-30 cursor-not-allowed" : "hover:bg-slate-100/20"} ${iconColor}`}>
                        <ChevronLeft className="w-4 h-4" />
                    </button>

                    <button onClick={onChapters}
                        className={`flex items-center gap-2 px-4 py-2.5 rounded-full transition-colors cursor-pointer ${darkMode ? "bg-zinc-700 hover:bg-zinc-600" : "bg-slate-100 hover:bg-slate-200"}`}>
                        <BookOpen className={`w-3.5 h-3.5 ${darkMode ? "text-zinc-300" : "text-slate-600"}`} />
                        <span className={`text-xs font-bold ${darkMode ? "text-white" : "text-slate-800"}`}>
                            Bab {chapter.order}
                        </span>
                        {/* <span className={`text-[10px] ${darkMode ? "text-zinc-400" : "text-slate-400"}`}>
                            {readingMinutes}m
                        </span> */}
                    </button>

                    <button onClick={onNext} disabled={!hasNext}
                        className={`w-10 h-10 rounded-full flex items-center justify-center transition-colors cursor-pointer relative
                            ${!hasNext ? "opacity-30 cursor-not-allowed" : "hover:bg-slate-100/20"} ${iconColor}`}>
                        <ChevronRight className="w-4 h-4" />
                        {nextLocked && hasNext && (
                            <span className="absolute -top-0.5 -right-0.5 w-3 h-3 rounded-full bg-amber-400 flex items-center justify-center">
                                <Lock className="w-1.5 h-1.5 text-white" />
                            </span>
                        )}
                    </button>

                    <div className={`w-px h-5 ${darkMode ? "bg-zinc-700" : "bg-slate-200"}`} />

                    <button onClick={onComments}
                        className={`w-10 h-10 rounded-full flex items-center justify-center transition-colors cursor-pointer hover:bg-slate-100/20 relative ${iconColor}`}>
                        <MessageCircle className="w-4 h-4" />
                        {(chapter.total_comments ?? 0) > 0 && (
                            <span className="absolute -top-0.5 -right-0.5 min-w-3.5 h-3.5 rounded-full bg-primary-500 text-[9px] font-bold text-white flex items-center justify-center px-0.5">
                                {chapter.total_comments}
                            </span>
                        )}
                    </button>

                    <button onClick={onSettings}
                        className={`w-10 h-10 rounded-full flex items-center justify-center transition-colors cursor-pointer hover:bg-slate-100/20 ${iconColor}`}>
                        <Settings className="w-4 h-4" />
                    </button>

                    {/* {claimable && (
                        <button
                            onClick={handleClaim}
                            className="bg-white text-primary-500 flex items-center gap-2 px-2 cursor-pointer rounded-full py-1 hover:bg-gray-100"
                        >
                            <Image src={"/assets/Coin/GreenCoin.png"} alt="Green Coin Kutu Buku" height={20} width={20} />
                            <span>
                                {
                                    claimable === 3 ? '100' :
                                        (claimable === 10 ? '100' :
                                            (claimable === 20 ? '125' :
                                                claimable === 30 ? '125' :
                                                    (claimable === 45 ? '150' :
                                                        (claimable === 60 ? '200' :
                                                            (claimable === 120 ? '200' :
                                                                (claimable === 180 ? '1000' : ''
                                                                ))))))
                                }
                            </span>
                        </button>
                    )} */}
                </div>
            </motion.div>
        </motion.div>
    );
}

interface Props {
    chapter: ChapterModel;
    chapters: ChapterModel[];
    novel: PostModel;
    token: string;
}

export default function ChapterDetailPage({ chapter: initialChapter, chapters, novel, token }: Props) {
    const { t, language } = useTranslation();
    const router = useRouter();

    const [chapter, setChapter] = useState<ChapterModel>(initialChapter);
    const [darkMode, setDarkMode] = useState(false);
    const [fontSize, setFontSize] = useState(16);
    const [fontFamily, setFontFamily] = useState<string>("Georgia");
    const [lineSpacing, setLineSpacing] = useState(2);
    const [showSettings, setShowSettings] = useState(false);
    const [showChapters, setShowChapters] = useState(false);
    const [showComments, setShowComments] = useState(false);
    const [readingMinutes, setReadingMinutes] = useState(0);
    const [claimable, setClaimable] = useState<number | null>(null);

    const lastInteractionRef = useRef<number>(Date.now());
    const chapterSecondsRef = useRef(0);
    const totalSecondsRef = useRef(0);
    const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);

    const markInteraction = useCallback(() => {
        lastInteractionRef.current = Date.now();
    }, []);

    const TODAY = format(new Date(), "yyyy-MM-dd");
    const getChapterKey = (chapterId: string) => `reading_${chapterId}_${TODAY}`;
    const getTotalKey = () => `reading_total_${TODAY}`;

    useEffect(() => {
        const handleActivity = () => markInteraction();
        window.addEventListener("touchstart", handleActivity);
        window.addEventListener("touchmove", handleActivity);
        window.addEventListener("scroll", handleActivity);
        window.addEventListener("click", handleActivity);

        return () => {
            window.removeEventListener("touchstart", handleActivity);
            window.removeEventListener("touchmove", handleActivity);
            window.removeEventListener("scroll", handleActivity);
            window.removeEventListener("click", handleActivity);
        };
    }, [markInteraction]);

    useEffect(() => {
        chapterSecondsRef.current = getChapterSeconds(chapter.id);

        totalSecondsRef.current = getTotalSeconds();
        setReadingMinutes(Math.floor(totalSecondsRef.current / 60));

        lastInteractionRef.current = Date.now();

        if (chapterSecondsRef.current >= MAX_CHAPTER_MINUTES * 60) {
            // toast.info("Kamu sudah membaca bab ini hari ini 📖", { toastId: "chapter-limit" });
            return;
        }

        intervalRef.current = setInterval(() => {
            const idleSeconds = (Date.now() - lastInteractionRef.current) / 1000;
            if (idleSeconds > MAX_IDLE_MINUTES * 60) return;

            chapterSecondsRef.current += 1;
            totalSecondsRef.current += 1;

            saveChapterSeconds(chapter.id, chapterSecondsRef.current);
            saveTotalSeconds(totalSecondsRef.current);

            setReadingMinutes(Math.floor(totalSecondsRef.current / 60));

            if (chapterSecondsRef.current >= MAX_CHAPTER_MINUTES * 60) {
                clearInterval(intervalRef.current!);
                // toast.info("Ayo lanjut ke bab berikutnya! 📖", { toastId: "chapter-limit" });
            }
        }, 1_000);

        return () => { if (intervalRef.current) clearInterval(intervalRef.current); };
    }, [chapter.id]);

    useEffect(() => {
        let claim = null;

        if (readingMinutes >= 3 && readingMinutes < 10) claim = 3;
        else if (readingMinutes >= 10 && readingMinutes < 20) claim = 10;
        else if (readingMinutes >= 20 && readingMinutes < 30) claim = 20;
        else if (readingMinutes >= 30 && readingMinutes < 45) claim = 30;
        else if (readingMinutes >= 45 && readingMinutes < 60) claim = 45;
        else if (readingMinutes >= 60 && readingMinutes < 120) claim = 60;
        else if (readingMinutes >= 120 && readingMinutes < 180) claim = 120;
        else if (readingMinutes >= 180) claim = 180;

        setClaimable(claim);
    }, [readingMinutes]);

    useEffect(() => {
        const thresholds = [3, 10, 20, 30, 45, 60, 120, 180];
        const hit = thresholds.findLast((t) => readingMinutes >= t) ?? null;
        if (!hit || !token) { setClaimable(null); return; }

        const check = async () => {
            try {
                const { data: res } = await getCoinsClaim(token, {
                    post_id: novel.id,
                    minutes: readingMinutes,
                });
                if (res?.message === "Transaksi Belum Diambil") {
                    setClaimable(hit);
                } else {
                    setClaimable(null);
                }
            } catch {
                setClaimable(null);
            }
        };
        check();
    }, [readingMinutes]);

    const currentIndex = chapters.findIndex((c) => c.id === chapter.id);
    const prevChapter = currentIndex > 0 ? chapters[currentIndex - 1] : null;
    const nextChapter = currentIndex < chapters.length - 1 ? chapters[currentIndex + 1] : null;

    const openApp = () => {
        const appSchemeUrl = `kutubuku://novel/${novel.id}`;
        const playStoreUrl = "https://play.google.com/store/apps/details?id=com.kutubuku";

        const fallbackTimer = setTimeout(() => {
            window.location.href = playStoreUrl;
        }, 1500);

        const onVisibilityChange = () => {
            if (document.hidden) {
                clearTimeout(fallbackTimer);
                document.removeEventListener("visibilitychange", onVisibilityChange);
            }
        };
        document.addEventListener("visibilitychange", onVisibilityChange);

        window.location.href = appSchemeUrl;
    };

    const goToChapter = (c: ChapterModel) => {
        if (c.is_paid) {
            openApp();
            return;
        }
        window.scrollTo({ top: 0, behavior: "smooth" });
        setChapter(c);
        router.replace(`/${language}/novel/${withSlug(novel.id, novel.slug)}/read/${withSlug(c.id, c.slug)}`, { scroll: false });
    };

    const nextRequiresApp = chapter.order > 5 || !!nextChapter?.is_paid;

    const goToNextChapter = () => {
        if (chapter.order > 5) {
            openApp();
            return;
        }
        if (nextChapter) goToChapter(nextChapter);
    };

    const handleClaim = async () => {
        if (!token || !claimable) return;
        try {
            const { data: countRes } = await countCoinsClaim(token, {
                post_id: novel.id,
                minutes: readingMinutes,
            });

            const CLAIM_TITLES: Record<number, string> = {
                3: "Hadiah untuk Anda yang rajin membaca selama 3 menit",
                10: "Hadiah untuk Anda yang rajin membaca selama 10 menit",
                20: "Hadiah untuk Anda yang rajin membaca selama 20 menit",
                30: "Hadiah untuk Anda yang rajin membaca selama 30 menit",
                45: "Hadiah untuk Anda yang rajin membaca selama 45 menit",
                60: "Hadiah untuk Anda yang rajin membaca selama 60 menit",
                120: "Hadiah untuk Anda yang rajin membaca selama 120 menit",
                180: "Hadiah untuk Anda yang rajin membaca selama 180 menit",
            };

            const title = CLAIM_TITLES[claimable];
            const filtered = countRes.data.filter((item: any) => item.title === title);

            if (filtered.length >= 2) {
                // toast.error(t("you have reached today's claim limit"));
                setClaimable(null);
                return;
            }

            const fourHoursAgo = new Date(Date.now() - 4 * 60 * 60 * 1000);
            const recentClaims = filtered.filter(
                (item: any) => new Date(item.created_at) > fourHoursAgo
            );
            if (recentClaims.length > 0) {
                // toast.error(t("you can't claim again at this minute"));
                setClaimable(null);
                return;
            }

            const { data: res } = await postCoinsClaim(token, {
                post_id: novel.id,
                minutes: readingMinutes,
            });
            if (res?.data) {
                // toast.success(t("success.claim"));
                setClaimable(null);
            }
        } catch (err: any) {
            // toast.error(err?.data?.message ?? "Gagal klaim");
        }
    };

    const getChapterSeconds = (chapterId: string): number => {
        try {
            const raw = localStorage.getItem(getChapterKey(chapterId));
            return raw ? parseInt(raw) : 0;
        } catch { return 0; }
    };

    const getTotalSeconds = (): number => {
        try {
            const raw = localStorage.getItem(getTotalKey());
            return raw ? parseInt(raw) : 0;
        } catch { return 0; }
    };

    const saveChapterSeconds = (chapterId: string, seconds: number) => {
        localStorage.setItem(getChapterKey(chapterId), String(seconds));
    };

    const saveTotalSeconds = (seconds: number) => {
        localStorage.setItem(getTotalKey(), String(seconds));
    };

    const bodyColor = darkMode ? "#e8e4dc" : "#2c2416";
    const bg = darkMode ? "bg-[#1a1a1a]" : "bg-[#ffffff]";
    const textColor = darkMode ? "text-[#e8e4dc]" : "text-[#2c2416]";

    const chapterBodyStyle = useMemo(
        () => `
            .chapter-content p, .chapter-content div, .chapter-content span {
                font-family: ${fontFamily};
                font-size: ${fontSize}px;
                color: ${bodyColor};
                line-height: ${lineSpacing};
            }
            .chapter-content p, .chapter-content div {
                margin-bottom: ${fontSize}px;
            }
        `,
        [fontFamily, fontSize, bodyColor, lineSpacing],
    );

    return (
        <div
            className={`min-h-screen w-full transition-colors duration-300 flex justify-center ${bg}`}
            onClick={markInteraction}
        >
            <div className="max-w-2xl mx-auto px-5 sm:px-8 pt-12 pb-40">

                <motion.div
                    key={chapter.id}
                    initial={{ opacity: 0, y: 20 }}
                    animate={{ opacity: 1, y: 0 }}
                    transition={{ duration: 0.5 }}
                    className="mb-10!"
                >
                    <p className={`text-xs font-semibold uppercase tracking-[0.2em] mb-3! ${darkMode ? "text-zinc-500" : "text-slate-400"}`}>
                        {novel.title}
                    </p>
                    <h1
                        className={`font-bold leading-tight mb-2! ${textColor}`}
                        style={{ fontFamily, fontSize: fontSize + 10 }}
                    >
                        Bab {chapter.order}
                    </h1>
                    <h2
                        className={`font-bold leading-tight ${textColor}`}
                        style={{ fontFamily, fontSize: fontSize + 8 }}
                    >
                        {chapter.title}
                    </h2>
                    <div className={`mt-6! h-px ${darkMode ? "bg-zinc-700" : "bg-slate-200"}`} />
                </motion.div>

                <style>{chapterBodyStyle}</style>

                <motion.div
                    key={`body-${chapter.id}`}
                    initial={{ opacity: 0 }}
                    animate={{ opacity: 1 }}
                    transition={{ delay: 0.2, duration: 0.6 }}
                    className={`chapter-content leading-relaxed ${textColor}`}
                    style={{ fontFamily, fontSize, lineHeight: lineSpacing }}
                    dangerouslySetInnerHTML={{ __html: chapter.description ?? "" }}
                />

                <motion.div
                    initial={{ opacity: 0, y: 16 }}
                    animate={{ opacity: 1, y: 0 }}
                    transition={{ delay: 0.5 }}
                    className={`mt-16! pt-8 border-t ${darkMode ? "border-zinc-700" : "border-slate-200"}`}
                >
                    <div className="flex items-center justify-between gap-4">
                        <button
                            onClick={() => setShowComments(true)}
                            className={`flex items-center gap-2 px-4 py-3 rounded-2xl text-sm font-medium transition-colors cursor-pointer
                                ${darkMode ? "bg-zinc-800 text-zinc-300 hover:bg-zinc-700" : "bg-slate-100 text-slate-600 hover:bg-slate-200"}`}
                        >
                            <MessageCircle className="w-4 h-4" />
                            {chapter.total_comments ?? 0} Komentar
                        </button>

                        {nextChapter && (
                            <button
                                onClick={goToNextChapter}
                                className={`flex-1 flex items-center justify-center gap-2 py-3 rounded-2xl text-sm font-bold transition-all cursor-pointer
                                    ${nextRequiresApp
                                        ? "bg-amber-50 text-amber-600 border border-amber-200"
                                        : "bg-primary-500 text-white hover:bg-primary-600"}`}
                            >
                                {nextRequiresApp ? <Lock className="w-4 h-4" /> : <ChevronRight className="w-4 h-4" />}
                                {nextRequiresApp ? "Buka di Aplikasi" : "Bab Selanjutnya"}
                            </button>
                        )}
                    </div>
                </motion.div>
            </div>

            <FloatingToolbar
                chapter={chapter}
                chapters={chapters}
                darkMode={darkMode}
                readingMinutes={readingMinutes}
                onPrev={() => prevChapter && goToChapter(prevChapter)}
                onNext={goToNextChapter}
                onChapters={() => setShowChapters(true)}
                onComments={() => setShowComments(true)}
                onSettings={() => setShowSettings(true)}
                onBack={() => router.push(`/${language}/novel/${withSlug(novel.id, novel.slug)}`)}
                hasPrev={!!prevChapter}
                hasNext={!!nextChapter}
                nextLocked={nextRequiresApp}
                claimable={claimable}
                handleClaim={handleClaim}
            />

            <SettingsPanel
                open={showSettings}
                fontSize={fontSize}
                fontFamily={fontFamily}
                lineSpacing={lineSpacing}
                darkMode={darkMode}
                onFontSize={setFontSize}
                onFontFamily={setFontFamily}
                onLineSpacing={setLineSpacing}
                onDarkMode={setDarkMode}
                onClose={() => setShowSettings(false)}
            />
            <ChaptersPanel
                open={showChapters}
                chapters={chapters}
                currentId={chapter.id}
                novelTitle={novel.title}
                onSelect={goToChapter}
                onClose={() => setShowChapters(false)}
                darkMode={darkMode}
            />
            <CommentsPanel
                open={showComments}
                chapterId={chapter.id}
                token={token}
                darkMode={darkMode}
                onClose={() => setShowComments(false)}
            />
        </div>
    );
}