"use client";

import { useState, useRef, useEffect } from "react";
import { Send, User, Bot, Copy, FileText, X, Sparkles, Eraser } from "lucide-react";
import { cn } from "@/lib/utils";
import { useSettingsStore } from "@/lib/settings-store";
import { Editor } from "@tiptap/react";
import { marked } from "marked";
import { sanitizeHtml } from "@/lib/sanitize-html";

interface Message {
    id: string;
    role: "user" | "assistant" | "system";
    content: string;
}

interface AIChatPanelProps {
    editor: Editor | null;
    isOpen: boolean;
    onClose: () => void;
}

export function AIChatPanel({ editor, isOpen, onClose }: AIChatPanelProps) {
    const { aiConfig } = useSettingsStore();
    const [messages, setMessages] = useState<Message[]>([]);
    const [input, setInput] = useState("");
    const [isLoading, setIsLoading] = useState(false);
    const [useContext, setUseContext] = useState(true);
    const [tokenCount, setTokenCount] = useState(0);
    const messagesEndRef = useRef<HTMLDivElement>(null);
    const abortControllerRef = useRef<AbortController | null>(null);

    useEffect(() => {
        const text = messages.map((m) => m.content).join("") + input;
        setTokenCount(Math.ceil(text.length * 0.7));
    }, [messages, input]);

    useEffect(() => {
        messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
    }, [messages]);

    useEffect(() => {
        if (!isOpen) return;
        const onKeyDown = (event: KeyboardEvent) => {
            if (event.key === "Escape") {
                event.preventDefault();
                onClose();
            }
        };
        window.addEventListener("keydown", onKeyDown);
        return () => window.removeEventListener("keydown", onKeyDown);
    }, [isOpen, onClose]);

    const handleStop = () => {
        if (abortControllerRef.current) {
            abortControllerRef.current.abort();
            abortControllerRef.current = null;
        }
        setIsLoading(false);
    };

    const handleSend = async () => {
        if (!input.trim() || isLoading) return;
        if (!aiConfig.apiKey) {
            setMessages((prev) => [
                ...prev,
                { id: Date.now().toString(), role: "system", content: "未配置 API Key，请先到设置页完成配置。" },
            ]);
            return;
        }

        const userMsg: Message = { id: Date.now().toString(), role: "user", content: input };
        setMessages((prev) => [...prev, userMsg]);
        setInput("");
        setIsLoading(true);
        abortControllerRef.current = new AbortController();

        const contextMsg: Message | null =
            useContext && editor
                ? { id: "context", role: "system", content: `当前文档上下文：\n${editor.getText().slice(0, 4000)}...` }
                : null;

        const apiMessages = [...(contextMsg ? [contextMsg] : []), ...messages.filter((m) => m.role !== "system"), userMsg];

        try {
            const res = await fetch("/api/ai/chat", {
                method: "POST",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify({
                    messages: apiMessages.map((m) => ({ role: m.role, content: m.content })),
                    config: aiConfig,
                }),
                signal: abortControllerRef.current.signal,
            });

            if (!res.ok) throw new Error(res.statusText);
            if (!res.body) throw new Error("No response body");

            const reader = res.body.getReader();
            const decoder = new TextDecoder();
            const assistantMsg: Message = { id: (Date.now() + 1).toString(), role: "assistant", content: "" };
            setMessages((prev) => [...prev, assistantMsg]);

            while (true) {
                const { done, value } = await reader.read();
                if (done) break;

                const chunk = decoder.decode(value);
                const lines = chunk.split("\n\n");

                for (const line of lines) {
                    if (!line.startsWith("data: ")) continue;
                    const data = line.slice(6);
                    if (data === "[DONE]") break;
                    try {
                        const parsed = JSON.parse(data);
                        const content = parsed.choices?.[0]?.delta?.content || "";
                        if (content) {
                            assistantMsg.content += content;
                            setMessages((prev) => prev.map((m) => (m.id === assistantMsg.id ? { ...assistantMsg } : m)));
                        }
                    } catch (e) {
                        console.error("Parse error", e);
                    }
                }
            }
        } catch (e: unknown) {
            const isAbortError = e instanceof Error && e.name === "AbortError";
            if (isAbortError) {
                setMessages((prev) => [...prev, { id: Date.now().toString(), role: "system", content: "生成已停止。" }]);
            } else {
                setMessages((prev) => [
                    ...prev,
                    {
                        id: Date.now().toString(),
                        role: "system",
                        content: `请求失败：${e instanceof Error ? e.message : "未知错误"}`,
                    },
                ]);
            }
        } finally {
            setIsLoading(false);
            abortControllerRef.current = null;
        }
    };

    const handleInsert = (content: string) => {
        if (editor) {
            editor.commands.insertContent(content);
        }
    };

    if (!isOpen) return null;

    return (
        <div
            className="fixed inset-0 z-50 flex w-full flex-col bg-background shadow-xl animate-in slide-in-from-right duration-300 md:left-auto md:w-96 md:border-l md:border-border/70"
            role="dialog"
            aria-modal="true"
            aria-label="AI 助手对话面板"
        >
            <div className="flex items-center justify-between border-b border-border/70 p-4">
                <div className="flex items-center gap-2">
                    <Sparkles className="h-5 w-5 text-primary" />
                    <div>
                        <h2 className="text-lg font-semibold leading-none">AI 助手</h2>
                        <p className="mt-0.5 font-mono text-[10px] text-muted-foreground opacity-80">{aiConfig.model || "gpt-3.5-turbo"}</p>
                    </div>
                </div>
                <div className="flex items-center gap-2">
                    <span className="mr-1 hidden text-xs text-muted-foreground sm:inline">估算 Tokens: {tokenCount}</span>
                    <button onClick={onClose} className="ui-icon-btn h-10 w-10 md:h-8 md:w-8" aria-label="关闭 AI 助手">
                        <X size={18} />
                    </button>
                </div>
            </div>

            <div className="flex-1 space-y-4 overflow-y-auto p-4">
                {messages.length === 0 && (
                    <div className="mt-20 text-center text-muted-foreground">
                        <p>有什么我可以帮你的吗？</p>
                        <p className="mt-2 text-sm">我可以帮你写作、润色、总结或回答问题。</p>
                    </div>
                )}
                {messages.map((msg) => (
                    <div key={msg.id} className={cn("flex gap-3", msg.role === "user" ? "flex-row-reverse" : "")}> 
                        <div
                            className={cn(
                                "flex h-8 w-8 shrink-0 items-center justify-center rounded-full",
                                msg.role === "user" ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"
                            )}
                        >
                            {msg.role === "user" ? <User size={16} /> : <Bot size={16} />}
                        </div>
                        <div
                            className={cn(
                                "group relative max-w-[92%] rounded-lg p-3 text-sm sm:max-w-[85%]",
                                msg.role === "user" ? "bg-primary text-primary-foreground" : "bg-muted text-foreground",
                                msg.role === "system" && "w-full max-w-full bg-destructive/10 text-destructive"
                            )}
                        >
                            {msg.role === "assistant" ? (
                                <div
                                    className="prose prose-sm max-w-none break-words dark:prose-invert [&>ol]:list-decimal [&>ol]:pl-4 [&>p]:mb-2 [&>ul]:list-disc [&>ul]:pl-4"
                                    dangerouslySetInnerHTML={{ __html: sanitizeHtml(marked.parse(msg.content) as string) }}
                                />
                            ) : (
                                <p className="whitespace-pre-wrap">{msg.content}</p>
                            )}

                            {msg.role === "assistant" && !isLoading && (
                                <div className="mt-2 flex gap-2 opacity-100 sm:absolute sm:-bottom-6 sm:left-0 sm:mt-0 sm:opacity-0 sm:transition-opacity sm:group-hover:opacity-100">
                                    <button
                                        onClick={() => handleInsert(msg.content)}
                                        className="flex items-center gap-1 rounded border bg-background px-1 py-1 text-xs shadow hover:bg-muted"
                                        title="插入到编辑器"
                                    >
                                        <FileText size={12} /> 插入
                                    </button>
                                    <button
                                        onClick={() => navigator.clipboard.writeText(msg.content)}
                                        className="rounded border bg-background p-1 text-xs shadow hover:bg-muted"
                                        title="复制"
                                    >
                                        <Copy size={12} />
                                    </button>
                                </div>
                            )}
                        </div>
                    </div>
                ))}
                <div ref={messagesEndRef} />
            </div>

            <div className="border-t border-border/70 bg-muted/20 p-3 pb-[max(0.75rem,env(safe-area-inset-bottom))] sm:p-4">
                <div className="mb-2 flex items-center justify-between">
                    <label className="flex cursor-pointer select-none items-center gap-2 text-[11px] text-muted-foreground sm:text-xs">
                        <input
                            type="checkbox"
                            checked={useContext}
                            onChange={(e) => setUseContext(e.target.checked)}
                            className="h-5 w-5 rounded border-input text-primary focus:ring-primary"
                            aria-label="关联当前文档上下文"
                        />
                        关联当前文档上下文
                    </label>
                    <button
                        onClick={() => setMessages([])}
                        className="flex items-center gap-1 text-[11px] text-muted-foreground hover:text-foreground sm:text-xs"
                        title="清空对话"
                    >
                        <Eraser size={12} /> 清空
                    </button>
                </div>
                <div className="relative">
                    <textarea
                        value={input}
                        onChange={(e) => setInput(e.target.value)}
                        onKeyDown={(e) => {
                            if (e.key === "Enter" && !e.shiftKey) {
                                e.preventDefault();
                                handleSend();
                            }
                        }}
                        placeholder="输入消息..."
                        className="min-h-[86px] w-full resize-none rounded-md border border-input bg-background p-3 pr-10 text-sm outline-none focus:ring-1 focus:ring-primary"
                        aria-label="输入给 AI 的消息"
                    />
                    <button
                        onClick={isLoading ? handleStop : handleSend}
                        disabled={!input.trim() && !isLoading}
                        className={cn(
                            "absolute bottom-2 right-2 rounded-md p-2 transition-all disabled:cursor-not-allowed disabled:opacity-50",
                            isLoading ? "bg-red-500 text-white" : "bg-primary text-primary-foreground"
                        )}
                        title={isLoading ? "停止生成" : "发送"}
                        aria-label={isLoading ? "停止生成" : "发送消息"}
                    >
                        {isLoading ? <div className="h-4 w-4 animate-pulse rounded-sm bg-current" /> : <Send size={16} />}
                    </button>
                </div>
            </div>
        </div>
    );
}
