"use client";

/**
 * Generic AI insight panel — drop into any tool page that has structured
 * computed data. Calls POST /api/ai/insight with { topic, context, prompt? }
 * and streams the deep-dive response as SSE.
 *
 * Usage:
 *   <AiInsightPanel topic="dream" context={{ keyword, meaning }} />
 *   <AiInsightPanel topic="bat-tu" context={{ pillars, fiveElements }} title="Luận sâu Bát Tự" />
 *
 * The component is intentionally self-contained — no provider state shared
 * across instances, each one tracks its own stream.
 */
import { useRef, useState, useTransition } from "react";
import { Sparkles, Square } from "lucide-react";

type InsightTopic =
  | "dream"
  | "bat-tu"
  | "i-ching"
  | "horoscope"
  | "numerology"
  | "compat-method"
  | "naming";

type Props = {
  topic: InsightTopic;
  context: Record<string, unknown>;
  /** Override the default CTA label, e.g. "Hỏi AI về quẻ này". */
  cta?: string;
  /** Optional hint shown above the result while idle. */
  hint?: string;
  /** Optional fixed prompt — if omitted, server uses topic-specific default. */
  prompt?: string;
  /** Optional title shown on the panel header. Defaults to "Luận giải sâu bằng AI". */
  title?: string;
};

const DEFAULT_TITLE = 'Luận giải sâu bằng "Thầy"';
const DEFAULT_HINT =
  "Phần trên là kết quả tra cứu nhanh. Bấm bên dưới để AI phân tích chi tiết hơn.";

export function AiInsightPanel({ topic, context, cta, hint, prompt, title }: Props) {
  const [text, setText] = useState("");
  const [streaming, setStreaming] = useState(false);
  const [providerName, setProviderName] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [, startTransition] = useTransition();
  const abortRef = useRef<AbortController | null>(null);

  const ctaLabel = cta ?? 'Hỏi "Thầy"';
  const hintText = hint ?? DEFAULT_HINT;
  const headerTitle = title ?? DEFAULT_TITLE;

  async function run() {
    if (streaming) return;
    setError(null);
    setText("");

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

    try {
      const res = await fetch("/api/ai/insight", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ topic, context, prompt }),
        signal: ctrl.signal,
      });
      if (!res.ok || !res.body) {
        const msg = (await res.text().catch(() => "")) || `HTTP ${res.status}`;
        throw new Error(msg);
      }
      const reader = res.body.getReader();
      const decoder = new TextDecoder();
      let buf = "";
      while (true) {
        const { value, done } = await reader.read();
        if (done) break;
        buf += decoder.decode(value, { stream: true });
        const events = buf.split("\n\n");
        buf = events.pop() ?? "";
        for (const evt of events) {
          const trimmed = evt.trim();
          if (!trimmed.startsWith("data:")) continue;
          const payload = trimmed.slice(5).trim();
          try {
            const parsed = JSON.parse(payload) as {
              delta?: string;
              done?: boolean;
              provider?: string;
              error?: string;
            };
            if (parsed.error) throw new Error(parsed.error);
            if (parsed.provider) setProviderName(parsed.provider);
            if (parsed.delta) {
              startTransition(() => {
                setText((prev) => prev + parsed.delta);
              });
            }
          } catch (e) {
            if (e instanceof Error && e.message !== "Unexpected end of JSON input") {
              throw e;
            }
          }
        }
      }
    } catch (e) {
      const msg = e instanceof Error ? e.message : "Lỗi không xác định";
      if (msg !== "AbortError" && !msg.includes("aborted")) {
        setError(msg);
      }
    } finally {
      setStreaming(false);
      abortRef.current = null;
    }
  }

  function stop() {
    abortRef.current?.abort();
  }

  const hasOutput = text.length > 0;

  return (
    <section className="border-brand-gold/20 bg-bg-elevated/40 mt-6 rounded-xl border p-4 lg:p-5">
      <header className="mb-3 flex items-center justify-between gap-2">
        <div className="flex items-center gap-2">
          <Sparkles className="text-brand-gold h-4 w-4" aria-hidden="true" />
          <h2 className="font-display text-ink-primary text-base font-semibold lg:text-lg">
            {headerTitle}
          </h2>
        </div>
        {providerName === "mock" ? (
          <span className="border-stroke-default text-ink-muted rounded-md border px-2 py-0.5 text-[10px] tracking-wider uppercase">
            mock
          </span>
        ) : null}
      </header>

      {!hasOutput && !streaming ? (
        <p className="text-ink-secondary mb-3 text-sm">{hintText}</p>
      ) : null}

      {hasOutput || streaming ? (
        <div className="bg-bg-inset border-stroke-subtle text-ink-primary mb-3 min-h-[120px] rounded-md border px-4 py-3 text-sm leading-relaxed whitespace-pre-wrap">
          {text || "..."}
        </div>
      ) : null}

      {error ? (
        <div className="border-brand-red/40 bg-brand-red/10 text-brand-red-light mb-3 rounded-md border px-3 py-2 text-xs">
          {error}
        </div>
      ) : null}

      <div className="flex items-center gap-2">
        {streaming ? (
          <button
            type="button"
            onClick={stop}
            className="border-stroke-default text-ink-secondary hover:border-brand-red/50 hover:text-brand-red-light inline-flex items-center gap-1.5 rounded-md border px-3 py-2 text-sm"
          >
            <Square className="h-3.5 w-3.5" aria-hidden="true" />
            Dừng
          </button>
        ) : (
          <button
            type="button"
            onClick={() => void run()}
            className="from-brand-gold via-brand-gold-soft to-brand-gold text-bg-base inline-flex items-center gap-1.5 rounded-md bg-gradient-to-r px-4 py-2 text-sm font-semibold transition hover:brightness-105"
          >
            <Sparkles className="h-3.5 w-3.5" aria-hidden="true" />
            {hasOutput ? "Hỏi lại" : ctaLabel}
          </button>
        )}
        <p className="text-ink-muted text-[11px]">Nội dung chỉ mang tính tham khảo.</p>
      </div>
    </section>
  );
}
