/**
 * InlineCitation — renders a [[doc/p007#c0042]] citation as a clickable mini-card
 * with bbox thumbnail, page, type, classification, and snippet. Fetches chunk
 * data lazily from /api/chunk on first render.
 *
 * Used by:
 *   - <MarkdownBody> to upgrade chunk-anchor wiki-links (in chat assistant messages
 *     and in any markdown body that cites chunks)
 */
"use client";
import { useEffect, useState } from "react";
import Link from "next/link";

interface ChunkData {
  chunk_id: string;
  doc_id: string;
  page: number;
  type: string;
  bbox: { x: number; y: number; w: number; h: number } | null;
  classification: string | null;
  content_en: string | null;
  content_pt: string | null;
}

const cache = new Map<string, ChunkData | "not_found">();

export function InlineCitation({
  docId,
  chunkId,
  label,
  lang = "pt",
}: {
  docId: string;
  chunkId: string;
  label?: string;
  lang?: "pt" | "en";
}) {
  const key = `${docId}/${chunkId}`;
  const cached = cache.get(key);
  const [data, setData] = useState<ChunkData | null>(
    cached && cached !== "not_found" ? cached : null,
  );
  const [missing, setMissing] = useState<boolean>(cached === "not_found");
  const [open, setOpen] = useState(false);

  useEffect(() => {
    if (cached) return;
    let cancelled = false;
    (async () => {
      try {
        const res = await fetch(
          `/api/chunk?doc=${encodeURIComponent(docId)}&chunk=${encodeURIComponent(chunkId)}`,
        );
        if (!res.ok) {
          cache.set(key, "not_found");
          if (!cancelled) setMissing(true);
          return;
        }
        const payload = (await res.json()) as ChunkData;
        cache.set(key, payload);
        if (!cancelled) setData(payload);
      } catch {
        cache.set(key, "not_found");
        if (!cancelled) setMissing(true);
      }
    })();
    return () => {
      cancelled = true;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [docId, chunkId]);

  const href = `/d/${docId}#${chunkId}`;

  if (missing) {
    return (
      <Link href={href} className="wiki-link wiki-link--doc" title={`${docId}/${chunkId}`}>
        {label ?? chunkId}
      </Link>
    );
  }

  if (!data) {
    return (
      <span className="inline-flex items-center gap-1 px-1.5 py-0.5 rounded bg-[rgba(127,219,255,0.08)] border border-[rgba(127,219,255,0.20)] font-mono text-[10px] text-[#7fdbff] align-baseline">
        <span className="animate-pulse">·</span>
        {label ?? chunkId}
      </span>
    );
  }

  const text = lang === "en" ? data.content_en || data.content_pt : data.content_pt || data.content_en;
  const cropUrl = data.bbox
    ? `/api/crop?doc=${encodeURIComponent(docId)}&page=${data.page}` +
      `&x=${data.bbox.x}&y=${data.bbox.y}&w=${data.bbox.w}&h=${data.bbox.h}&w_px=320`
    : null;

  return (
    <span className="relative inline-block align-baseline">
      <button
        type="button"
        onClick={() => setOpen(!open)}
        className="inline-flex items-center gap-1 px-1.5 py-0.5 rounded bg-[rgba(0,255,156,0.08)] border border-[rgba(0,255,156,0.32)] font-mono text-[10px] text-[#00ff9c] hover:bg-[rgba(0,255,156,0.18)] cursor-pointer"
        title={text?.slice(0, 200)}
      >
        📎 {label ?? chunkId} <span className="text-[#5a6678]">p{data.page}</span>
      </button>
      {open && (
        <span className="absolute left-0 top-full mt-1 z-30 w-80 max-w-[min(90vw,500px)] bg-[#0a121e] border border-[#00ff9c] rounded shadow-xl p-3 block">
          <span className="flex items-center gap-2 text-[10px] font-mono mb-2">
            <span className="text-[#00ff9c]">{data.chunk_id}</span>
            <span className="text-[#5a6678]">p{data.page}</span>
            <span className="text-[#5a6678]">{data.type}</span>
            {data.classification && (
              <span className="text-[#ff6b6b]">{data.classification}</span>
            )}
            <button
              type="button"
              onClick={(e) => {
                e.stopPropagation();
                setOpen(false);
              }}
              className="ml-auto text-[#5a6678] hover:text-[#00ff9c]"
              aria-label="close"
            >
              ✕
            </button>
          </span>
          {cropUrl && (
            <span className="block mb-2 border border-[rgba(0,255,156,0.20)] rounded overflow-hidden bg-black">
              {/* eslint-disable-next-line @next/next/no-img-element */}
              <img
                src={cropUrl}
                alt=""
                className="block w-full h-auto max-h-48 object-contain"
                loading="lazy"
              />
            </span>
          )}
          {text && (
            <span className="block text-[11px] text-[#c8d4e6] leading-snug whitespace-pre-line line-clamp-6">
              {text}
            </span>
          )}
          <Link
            href={href}
            className="mt-2 block text-center font-mono text-[10px] text-[#7fdbff] hover:text-[#00ff9c] underline"
          >
            abrir página inteira →
          </Link>
        </span>
      )}
    </span>
  );
}
