/* global React */
const { useState, useEffect, useMemo, useRef } = React;

// ───────────────────────────── Utilities ─────────────────────────────

const tierFor = (score) => {
  if (score >= 9) return { label: "High", className: "tier-high", hex: "#3f7d3a" };
  if (score >= 7) return { label: "Medium", className: "tier-med", hex: "#a06b13" };
  return { label: "Low", className: "tier-low", hex: "#a8392b" };
};

// Parse mixed-number strings like "3/4", "1 1/2", "1-2" into a number (range → first value)
function parseQty(q) {
  if (!q) return null;
  const s = String(q).trim();
  if (s.includes("-")) {
    const [a] = s.split("-").map(parseQty);
    return a;
  }
  const parts = s.split(/\s+/);
  let total = 0;
  for (const p of parts) {
    if (p.includes("/")) {
      const [n, d] = p.split("/").map(Number);
      if (!isNaN(n) && !isNaN(d) && d) total += n / d;
    } else if (!isNaN(Number(p))) {
      total += Number(p);
    } else {
      return null; // non-numeric token → bail
    }
  }
  return total;
}

function formatQty(n) {
  if (n == null || isNaN(n)) return "";
  // Round to nearest 1/8
  const eighths = Math.round(n * 8);
  if (eighths === 0) return "0";
  const whole = Math.floor(eighths / 8);
  const rem = eighths % 8;
  const fracs = { 1: "⅛", 2: "¼", 3: "⅜", 4: "½", 5: "⅝", 6: "¾", 7: "⅞" };
  if (rem === 0) return String(whole);
  if (whole === 0) return fracs[rem];
  return `${whole} ${fracs[rem]}`;
}

function scaleQuantity(original, factor) {
  if (!original) return original;
  const s = String(original).trim();
  if (s.includes("-")) {
    const [a, b] = s.split("-");
    const na = parseQty(a);
    const nb = parseQty(b);
    if (na != null && nb != null) return `${formatQty(na * factor)}–${formatQty(nb * factor)}`;
  }
  const n = parseQty(s);
  if (n == null) return s;
  return formatQty(n * factor);
}

// ───────────────────────────── Confidence Badge ─────────────────────────────

function ConfidenceBadge({ score, onClick, size = "md" }) {
  const t = tierFor(score);
  const sizes = {
    sm: "h-7 text-[11px] px-2 gap-1.5",
    md: "h-9 text-[12px] px-3 gap-2",
    lg: "h-11 text-sm px-4 gap-2.5",
  };
  return (
    <button
      onClick={onClick}
      className={`oc-badge ${t.className} ${sizes[size]}`}
      title={`Extraction confidence — click for breakdown`}
    >
      <span className="oc-dot" />
      <span className="font-mono tabular-nums">{score.toFixed(2)}</span>
      <span className="oc-badge-sep" />
      <span className="uppercase tracking-[0.08em]">{t.label} confidence</span>
    </button>
  );
}

// ───────────────────────────── Confidence Modal ─────────────────────────────

function ConfidenceModal({ data, onClose, onOpenSource }) {
  const c = data.confidence_assessment;
  const t = tierFor(c.overall_score);
  const fields = Object.entries(c.field_scores);
  return (
    <Modal onClose={onClose} title="Extraction Confidence" subtitle="How sure OneCook is about what it read.">
      <div className="grid gap-8 md:grid-cols-[260px_1fr] p-7">
        <div className="space-y-5">
          <ConfidenceRing score={c.overall_score} tier={t} />
          <div className="space-y-1.5 font-mono text-[11px] text-stone-500">
            <KV k="Source" v={data.source_type} />
            <KV k="Iteration" v={`#${c.iteration}`} />
            <KV k="Quality gate" v={c.gated ? "Passed" : "Pending"} />
          </div>
          <button onClick={onOpenSource} className="oc-btn-secondary w-full">
            View source evidence →
          </button>
        </div>

        <div className="space-y-6">
          <div>
            <div className="oc-eyebrow mb-3">Per-field scores</div>
            <div className="space-y-3">
              {fields.map(([k, v]) => (
                <FieldScoreRow key={k} field={k} score={v} />
              ))}
            </div>
          </div>

          <div className="oc-divider" />

          <div>
            <div className="oc-eyebrow mb-3">Ambiguities flagged ({c.ambiguities.length})</div>
            <ul className="space-y-3">
              {c.ambiguities.map((a, i) => (
                <li key={i} className="flex gap-3 text-[13.5px] leading-relaxed text-stone-700">
                  <span className="mt-[3px] inline-block size-1.5 rounded-full bg-amber-500 shrink-0" />
                  <span>{a}</span>
                </li>
              ))}
            </ul>
          </div>
        </div>
      </div>
    </Modal>
  );
}

function ConfidenceRing({ score, tier }) {
  const pct = (score / 10) * 100;
  const C = 2 * Math.PI * 54;
  return (
    <div className="relative aspect-square w-full">
      <svg viewBox="0 0 120 120" className="size-full -rotate-90">
        <circle cx="60" cy="60" r="54" fill="none" stroke="rgba(0,0,0,0.06)" strokeWidth="6" />
        <circle
          cx="60" cy="60" r="54" fill="none"
          stroke={tier.hex} strokeWidth="6" strokeLinecap="round"
          strokeDasharray={C} strokeDashoffset={C - (pct / 100) * C}
        />
      </svg>
      <div className="absolute inset-0 grid place-items-center">
        <div className="text-center">
          <div className="font-display text-[44px] leading-none tabular-nums" style={{ color: tier.hex }}>
            {score.toFixed(2)}
          </div>
          <div className="mt-2 font-mono text-[10px] uppercase tracking-[0.14em] text-stone-500">
            / 10.00 · {tier.label}
          </div>
        </div>
      </div>
    </div>
  );
}

function FieldScoreRow({ field, score }) {
  const t = tierFor(score);
  const pct = (score / 10) * 100;
  return (
    <div>
      <div className="mb-1 flex items-baseline justify-between">
        <span className="text-[13px] font-medium capitalize text-stone-800">{field}</span>
        <span className="font-mono text-[11px] tabular-nums text-stone-600">{score.toFixed(2)}</span>
      </div>
      <div className="h-1.5 w-full overflow-hidden rounded-full bg-stone-200/70">
        <div
          className="h-full rounded-full transition-all"
          style={{ width: `${pct}%`, background: t.hex }}
        />
      </div>
    </div>
  );
}

function KV({ k, v }) {
  return (
    <div className="flex items-center justify-between gap-3">
      <span className="uppercase tracking-[0.1em]">{k}</span>
      <span className="text-stone-700">{v}</span>
    </div>
  );
}

// ───────────────────────────── Source Modal ─────────────────────────────

function SourceModal({ data, onClose }) {
  const [tab, setTab] = useState("scan");
  return (
    <Modal onClose={onClose} title="Source evidence" subtitle={`Extracted from a ${data.source_type} note · ${data.confidence_assessment.overall_score.toFixed(2)} / 10 confidence`}>
      <div className="border-b border-stone-200/80 px-7">
        <div className="flex gap-6">
          {[
            ["scan", "Original scan"],
            ["transcript", "Raw transcription"],
            ["json", "Extracted JSON"],
          ].map(([id, label]) => (
            <button
              key={id}
              onClick={() => setTab(id)}
              className={`oc-tab ${tab === id ? "oc-tab-active" : ""}`}
            >
              {label}
            </button>
          ))}
        </div>
      </div>

      <div className="p-7">
        {tab === "scan" && <ScanView data={data} />}
        {tab === "transcript" && (
          <pre className="oc-mono-block">{data.raw_transcription}</pre>
        )}
        {tab === "json" && (
          <pre className="oc-mono-block">{JSON.stringify(
            { title: data.title, ingredients: data.ingredients, instructions: data.instructions, metadata: data.metadata },
            null, 2
          )}</pre>
        )}
      </div>
    </Modal>
  );
}

function ScanView({ data }) {
  const slug = window.CURRENT_SLUG || "sausage-stuffed-squash";
  const scanSrc = `assets/sources/${slug}/scan-1.jpg`;
  const ingCount = data.ingredients?.length ?? 0;
  const stepCount = data.instructions?.length ?? 0;
  const m = data.metadata || {};
  const headerBits = [];
  if (m.difficulty) headerBits.push("difficulty");
  if (m.prep_time) headerBits.push("prep time");
  if (m.servings != null && m.servings !== "") headerBits.push("serves");
  return (
    <div className="grid gap-7 md:grid-cols-[1.2fr_1fr]">
      <ScanImage src={scanSrc} title={data.title} />
      <div className="space-y-5">
        <div>
          <div className="oc-eyebrow mb-2">Provenance</div>
          <div className="oc-info-grid">
            <KV k="Source type" v={data.source_type} />
            <KV k="Method" v="OneCook Vision v3" />
            <KV k="Iteration" v={`#${data.confidence_assessment.iteration}`} />
            <KV k="Gate" v={data.confidence_assessment.gated ? "Passed" : "Pending review"} />
          </div>
        </div>
        <div>
          <div className="oc-eyebrow mb-2">What the model saw</div>
          <ul className="space-y-2.5 text-[13.5px] leading-relaxed text-stone-700">
            <li className="flex gap-3"><Check /> {ingCount} ingredient line{ingCount === 1 ? "" : "s"} parsed.</li>
            <li className="flex gap-3"><Check /> {stepCount} direction step{stepCount === 1 ? "" : "s"}.</li>
            {headerBits.length > 0 && (
              <li className="flex gap-3"><Check /> Header block: {headerBits.join(", ")}.</li>
            )}
            {(data.confidence_assessment.ambiguities || []).slice(0, 2).map((a, i) => (
              <li key={i} className="flex gap-3"><Warn /> {a}</li>
            ))}
          </ul>
        </div>
        <button onClick={() => {
          const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json" });
          const a = document.createElement("a");
          a.href = URL.createObjectURL(blob);
          a.download = `${data.title.replace(/\s+/g, "-").toLowerCase()}.json`;
          a.click();
        }} className="oc-btn-secondary w-full">Download extracted JSON</button>
      </div>
    </div>
  );
}

function ScanImage({ src, title }) {
  const [zoom, setZoom] = useState(false);
  return (
    <div className={`oc-scan-photo ${zoom ? 'is-zoomed' : ''}`} onClick={() => setZoom(z => !z)}>
      <img src={src} alt={`Source scan for ${title}`} loading="lazy" />
      <div className="oc-scan-photo-hint">
        <svg viewBox="0 0 16 16" className="size-3"><circle cx="7" cy="7" r="5" fill="none" stroke="currentColor" strokeWidth="1.4"/><path d="M11 11l3 3 M5 7h4 M7 5v4" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round"/></svg>
        {zoom ? 'Click to fit' : 'Click to zoom'}
      </div>
    </div>
  );
}

function Check() {
  return <svg viewBox="0 0 16 16" className="mt-[3px] size-3.5 shrink-0 text-emerald-700"><path d="M3 8.5l3 3 7-7" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/></svg>;
}
function Warn() {
  return <svg viewBox="0 0 16 16" className="mt-[3px] size-3.5 shrink-0 text-amber-600"><path d="M8 2L1.5 13.5h13L8 2z" fill="none" stroke="currentColor" strokeWidth="1.6"/><path d="M8 6.5v3.5M8 11.5v.5" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"/></svg>;
}

// ───────────────────────────── Modal Shell ─────────────────────────────

function Modal({ children, onClose, title, subtitle, wide = true }) {
  useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    return () => { window.removeEventListener("keydown", onKey); document.body.style.overflow = ""; };
  }, [onClose]);
  return (
    <div className="oc-modal-scrim" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className={`oc-modal ${wide ? "oc-modal-wide" : ""}`} onMouseDown={(e) => e.stopPropagation()}>
        <div className="flex items-start justify-between gap-6 border-b border-stone-200/80 px-7 pb-5 pt-6">
          <div>
            <div className="oc-eyebrow mb-1">OneCook AI</div>
            <h2 className="font-display text-[26px] leading-tight text-stone-900">{title}</h2>
            {subtitle && <p className="mt-1.5 text-[13px] text-stone-500">{subtitle}</p>}
          </div>
          <button onClick={onClose} className="oc-icon-btn" aria-label="Close">
            <svg viewBox="0 0 16 16" className="size-4"><path d="M3 3l10 10M13 3L3 13" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>
          </button>
        </div>
        {children}
      </div>
    </div>
  );
}

window.OneCook = window.OneCook || {};
Object.assign(window.OneCook, {
  ConfidenceBadge, ConfidenceModal, SourceModal, Modal,
  tierFor, parseQty, formatQty, scaleQuantity,
});
