"use client";

/**
 * ChartQAPanel — Q&A AI streaming gắn với một lá số đã lưu.
 *
 * Persistence: backend tự tạo/resume AIConversation và lưu từng message vào DB
 * khi assistant stream xong. Trên trang refresh, server load lại history qua
 * `initialMessages` prop.
 *
 * Auth & quota: server gate. UI chỉ hiển thị error 401/402 đẹp với link upgrade.
 */

import { useEffect, useRef, useState } from "react";
import { Send, Loader2, Sparkles, AlertCircle, Crown } from "lucide-react";
import Link from "next/link";
import { cn } from "@/lib/utils";

export type QAMessage = {
  id: string;
  role: "user" | "assistant" | "system";
  content: string;
  createdAt: string;
};

type Props = {
  chartId: string;
  /** Most recent conversation pre-loaded server-side, if any */
  initialConversationId: string | null;
  initialMessages: QAMessage[];
  plan: "FREE" | "PREMIUM";
};

const SUGGESTED_QUESTIONS = [
  "Tổng quan vận mệnh cuộc đời tôi",
  "Sự nghiệp tôi nên đi theo hướng nào?",
  "Khi nào tôi gặp được người bạn đời?",
  "Tài lộc của tôi như thế nào?",
  "Tôi nên cẩn trọng điều gì trong 2 năm tới?",
];

export function ChartQAPanel({ chartId, initialConversationId, initialMessages, plan }: Props) {
  const [messages, setMessages] = useState<QAMessage[]>(initialMessages);
  const [conversationId, setConversationId] = useState<string | null>(initialConversationId);
  const [input, setInput] = useState("");
  const [streaming, setStreaming] = useState(false);
  const [streamingText, setStreamingText] = useState("");
  const [error, setError] = useState<{ message: string; upgrade?: boolean } | null>(null);
  const abortRef = useRef<AbortController | null>(null);
  const scrollRef = useRef<HTMLDivElement | null>(null);

  // Auto-scroll on new content
  useEffect(() => {
    if (scrollRef.current) {
      scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
    }
  }, [messages, streamingText]);

  async function sendQuestion(question: string) {
    if (streaming || !question.trim()) return;
    setError(null);

    const userMsg: QAMessage = {
      id: `tmp-u-${Date.now()}`,
      role: "user",
      content: question,
      createdAt: new Date().toISOString(),
    };
    setMessages((prev) => [...prev, userMsg]);
    setInput("");
    setStreaming(true);
    setStreamingText("");

    const ctrl = new AbortController();
    abortRef.current = ctrl;

    try {
      const res = await fetch(`/api/charts/${chartId}/qa`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ question, conversationId }),
        signal: ctrl.signal,
      });

      if (!res.ok) {
        const err = await res.json().catch(() => ({ error: "Lỗi máy chủ" }));
        setError({
          message: err.error ?? `HTTP ${res.status}`,
          upgrade: err.upgrade ?? res.status === 402,
        });
        // Remove optimistic user message on hard error
        setMessages((prev) => prev.filter((m) => m.id !== userMsg.id));
        setStreaming(false);
        return;
      }

      const reader = res.body?.getReader();
      if (!reader) {
        setError({ message: "Không nhận được stream từ server" });
        setStreaming(false);
        return;
      }

      const decoder = new TextDecoder();
      let buffer = "";
      let assembled = "";

      while (true) {
        const { value, done } = await reader.read();
        if (done) break;
        buffer += decoder.decode(value, { stream: true });

        // Parse SSE chunks
        const lines = buffer.split("\n\n");
        buffer = lines.pop() ?? "";
        for (const line of lines) {
          if (!line.startsWith("data:")) continue;
          const json = line.slice(5).trim();
          if (!json) continue;
          try {
            const event = JSON.parse(json);
            if (event.type === "meta") {
              if (event.conversationId) setConversationId(event.conversationId);
            } else if (event.type === "token") {
              assembled += event.content;
              setStreamingText(assembled);
            } else if (event.type === "done") {
              const aMsg: QAMessage = {
                id: `tmp-a-${Date.now()}`,
                role: "assistant",
                content: assembled,
                createdAt: new Date().toISOString(),
              };
              setMessages((prev) => [...prev, aMsg]);
              setStreamingText("");
            } else if (event.type === "error") {
              setError({ message: event.message ?? "Lỗi AI" });
            }
          } catch {
            // Ignore malformed SSE chunks
          }
        }
      }
    } catch (e) {
      if (e instanceof Error && e.name !== "AbortError") {
        setError({ message: e.message });
      }
    } finally {
      setStreaming(false);
      abortRef.current = null;
    }
  }

  function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    sendQuestion(input);
  }

  function abort() {
    abortRef.current?.abort();
    setStreaming(false);
    setStreamingText("");
  }

  return (
    <div className="border-stroke-default bg-bg-elevated/50 flex flex-col rounded-xl border p-4 lg:p-6">
      <div className="mb-3 flex items-center justify-between gap-3">
        <div className="flex items-center gap-2">
          <Sparkles className="text-brand-gold h-5 w-5" />
          <h3 className="font-display text-lg font-semibold lg:text-xl">
            Hỏi &ldquo;Thầy&rdquo; về lá số
          </h3>
        </div>
        <span
          className={cn(
            "rounded-full border px-2 py-0.5 text-[10px] font-medium tracking-wider uppercase",
            plan === "PREMIUM"
              ? "border-amber-400/40 bg-amber-500/10 text-amber-300"
              : "border-stroke-default text-ink-muted"
          )}
        >
          {plan === "PREMIUM" ? "Premium · không giới hạn" : "FREE · 20 tin/ngày"}
        </span>
      </div>

      {/* Message stream */}
      <div
        ref={scrollRef}
        className="border-stroke-subtle bg-bg-base/40 mb-3 max-h-[460px] min-h-[280px] flex-1 overflow-y-auto rounded-lg border p-3 lg:p-4"
      >
        {messages.length === 0 && !streamingText ? (
          <EmptyState onPick={(q) => sendQuestion(q)} disabled={streaming} />
        ) : (
          <div className="space-y-4">
            {messages.map((m) => (
              <Bubble key={m.id} message={m} />
            ))}
            {streamingText ? (
              <Bubble
                message={{
                  id: "streaming",
                  role: "assistant",
                  content: streamingText,
                  createdAt: new Date().toISOString(),
                }}
                streaming
              />
            ) : null}
          </div>
        )}
      </div>

      {error ? (
        <div
          className={cn(
            "mb-3 flex items-start gap-2 rounded-md border px-3 py-2 text-sm",
            error.upgrade
              ? "border-amber-400/40 bg-amber-500/10 text-amber-200"
              : "border-rose-400/40 bg-rose-500/10 text-rose-200"
          )}
        >
          {error.upgrade ? (
            <Crown className="mt-0.5 h-4 w-4 flex-shrink-0" />
          ) : (
            <AlertCircle className="mt-0.5 h-4 w-4 flex-shrink-0" />
          )}
          <div className="flex-1">
            <p>{error.message}</p>
            {error.upgrade ? (
              <Link
                href="/pricing"
                className="mt-1 inline-block underline underline-offset-2 hover:text-amber-100"
              >
                Xem gói Premium →
              </Link>
            ) : null}
          </div>
        </div>
      ) : null}

      <form onSubmit={handleSubmit} className="flex items-center gap-2">
        <input
          type="text"
          value={input}
          onChange={(e) => setInput(e.target.value)}
          placeholder={
            streaming ? "Đang trả lời..." : "Hỏi về sự nghiệp, tình duyên, sức khỏe, tài lộc..."
          }
          disabled={streaming}
          maxLength={500}
          className="border-stroke-default bg-bg-base focus:border-brand-gold/60 focus:ring-brand-gold/20 flex-1 rounded-md border px-3 py-2 text-sm focus:ring-2 focus:outline-none disabled:opacity-60"
        />
        {streaming ? (
          <button
            type="button"
            onClick={abort}
            className="rounded-md border border-rose-400/40 bg-rose-500/10 px-3 py-2 text-sm font-medium text-rose-200 hover:bg-rose-500/20"
          >
            Dừng
          </button>
        ) : (
          <button
            type="submit"
            disabled={!input.trim()}
            className="bg-brand-gold text-ink-on-gold hover:bg-brand-gold-soft inline-flex items-center gap-1.5 rounded-md px-3 py-2 text-sm font-medium disabled:cursor-not-allowed disabled:opacity-50"
          >
            <Send className="h-4 w-4" />
            Gửi
          </button>
        )}
      </form>

      <div className="text-ink-muted mt-2 flex items-center justify-between text-[10px] lg:text-xs">
        <span>Tối đa 500 ký tự · {input.length}/500</span>
        <span>Lịch sử hội thoại lưu tự động</span>
      </div>
    </div>
  );
}

function EmptyState({ onPick, disabled }: { onPick: (q: string) => void; disabled: boolean }) {
  return (
    <div className="flex flex-col items-center justify-center py-8 text-center">
      <div className="border-brand-gold/30 bg-brand-gold/10 mb-3 inline-flex h-12 w-12 items-center justify-center rounded-full border">
        <Sparkles className="text-brand-gold h-6 w-6" />
      </div>
      <p className="font-display text-ink-primary mb-1 text-base font-medium">
        Hỏi &ldquo;Thầy&rdquo; bất kỳ điều gì về lá số
      </p>
      <p className="text-ink-muted mb-4 max-w-md text-xs leading-relaxed lg:text-sm">
        &ldquo;Thầy&rdquo; luận giải dựa trên 12 cung, chính tinh, đại vận và các sao phù trợ trong
        lá số của bạn. Hội thoại được lưu — hỏi tiếp bất cứ lúc nào.
      </p>
      <div className="flex flex-wrap justify-center gap-1.5">
        {SUGGESTED_QUESTIONS.map((q) => (
          <button
            key={q}
            type="button"
            onClick={() => onPick(q)}
            disabled={disabled}
            className="border-stroke-default text-ink-secondary hover:border-brand-gold/40 hover:text-brand-gold rounded-full border px-3 py-1 text-xs disabled:opacity-50"
          >
            {q}
          </button>
        ))}
      </div>
    </div>
  );
}

function Bubble({ message, streaming }: { message: QAMessage; streaming?: boolean }) {
  const isUser = message.role === "user";
  return (
    <div className={cn("flex gap-2", isUser ? "justify-end" : "justify-start")}>
      <div
        className={cn(
          "max-w-[88%] rounded-lg px-3 py-2 text-sm leading-relaxed lg:px-4 lg:py-3",
          isUser
            ? "bg-brand-gold/15 border-brand-gold/30 text-ink-primary border"
            : "bg-bg-elevated/80 border-stroke-subtle text-ink-secondary border"
        )}
      >
        <div className="whitespace-pre-wrap">{message.content}</div>
        {streaming ? (
          <Loader2 className="text-brand-gold mt-1 inline-block h-3 w-3 animate-spin" />
        ) : null}
      </div>
    </div>
  );
}
