/* global React, ReactDOM, RECIPE_DATA, OneCook */
const { useState, useEffect, useMemo, useRef } = React;
const { ConfidenceBadge, ConfidenceModal, SourceModal, tierFor, scaleQuantity } = window.OneCook;

const DATA = window.RECIPE_DATA;

// ───────────────────────────── App ─────────────────────────────

function App() {
  const [modal, setModal] = useState(null); // 'confidence' | 'source' | null
  const [servings, setServings] = useState(DATA.metadata.servings);
  const [cookMode, setCookMode] = useState(false);
  const [checked, setChecked] = useState(() => new Set());
  const [doneSteps, setDoneSteps] = useState(() => new Set());
  const [activeStep, setActiveStep] = useState(0);

  const factor = servings / DATA.metadata.servings;

  const toggleIng = (i) => {
    setChecked((s) => { const n = new Set(s); n.has(i) ? n.delete(i) : n.add(i); return n; });
  };
  const toggleStep = (i) => {
    setDoneSteps((s) => { const n = new Set(s); n.has(i) ? n.delete(i) : n.add(i); return n; });
  };

  return (
    <div className="min-h-screen">
      <TopBar onOpenSource={() => setModal("source")} onOpenConfidence={() => setModal("confidence")} />

      <main className="oc-container pt-10 md:pt-14">
        <Hero
          data={DATA}
          onOpenConfidence={() => setModal("confidence")}
          onOpenSource={() => setModal("source")}
          cookMode={cookMode}
          setCookMode={setCookMode}
        />

        <ProvenanceStrip data={DATA} onOpenSource={() => setModal("source")} />

        <div className="mt-14 grid gap-12 md:gap-16 lg:grid-cols-[340px_1fr]">
          <Ingredients
            data={DATA}
            servings={servings}
            setServings={setServings}
            factor={factor}
            checked={checked}
            toggleIng={toggleIng}
            cookMode={cookMode}
          />
          <Instructions
            data={DATA}
            doneSteps={doneSteps}
            toggleStep={toggleStep}
            activeStep={activeStep}
            setActiveStep={setActiveStep}
            cookMode={cookMode}
          />
        </div>

        <Notes data={DATA} onOpenSource={() => setModal("source")} onOpenConfidence={() => setModal("confidence")} />
        <Footer />
      </main>

      {modal === "confidence" && (
        <ConfidenceModal data={DATA} onClose={() => setModal(null)} onOpenSource={() => setModal("source")} />
      )}
      {modal === "source" && <SourceModal data={DATA} onClose={() => setModal(null)} />}
    </div>
  );
}

// ───────────────────────────── Top Bar ─────────────────────────────

function TopBar({ onOpenSource, onOpenConfidence }) {
  const [open, setOpen] = useState(false);
  return (
    <header className="oc-topbar">
      <div className="oc-container flex h-14 items-center justify-between gap-3">
        <div className="flex items-center gap-8 min-w-0">
          <a className="flex items-center gap-2.5" href="Landing.html">
            <Logo />
            <span className="font-display text-[20px] leading-none text-stone-900">OneCook</span>
            <span className="ml-1 oc-pill">AI</span>
          </a>
          <nav className="hidden gap-6 text-[13px] text-stone-600 md:flex">
            <a href="Library.html" className="hover:text-stone-900">Library</a>
            <a href="Recipe.html" className="text-stone-900 font-medium">Recipe</a>
          </nav>
        </div>
        <div className="flex items-center gap-2">
          <div className="oc-topbar-icons flex items-center gap-2">
            <button className="oc-icon-btn" onClick={() => window.print()} title="Print">
              <svg viewBox="0 0 16 16" className="size-4"><path d="M4 6V2h8v4M4 12H2V7h12v5h-2M5 10h6v4H5z" fill="none" stroke="currentColor" strokeWidth="1.4"/></svg>
            </button>
            <button className="oc-icon-btn" title="Save">
              <svg viewBox="0 0 16 16" className="size-4"><path d="M4 2v12l4-3 4 3V2z" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinejoin="round"/></svg>
            </button>
            <button className="oc-icon-btn" title="Share">
              <svg viewBox="0 0 16 16" className="size-4"><circle cx="12" cy="3.5" r="1.8" fill="none" stroke="currentColor" strokeWidth="1.4"/><circle cx="4" cy="8" r="1.8" fill="none" stroke="currentColor" strokeWidth="1.4"/><circle cx="12" cy="12.5" r="1.8" fill="none" stroke="currentColor" strokeWidth="1.4"/><path d="M10.5 4.5L5.5 7M5.5 9L10.5 11.5" stroke="currentColor" strokeWidth="1.4"/></svg>
            </button>
            <div className="mx-1 h-5 w-px bg-stone-200" />
          </div>
          <div className="oc-avatar">BR</div>
          <button onClick={() => setOpen(!open)} className="oc-menu-btn" aria-label="Toggle menu">
            {open ? (
              <svg viewBox="0 0 16 16"><path d="M3 3l10 10M13 3L3 13" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>
            ) : (
              <svg viewBox="0 0 16 16"><path d="M2 4h12M2 8h12M2 12h12" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>
            )}
          </button>
        </div>
      </div>
      {open && (
        <nav className="oc-mobile-panel">
          <a href="Library.html">Library</a>
          <a href="Recipe.html">This recipe</a>
          <a href="#" onClick={(e) => { e.preventDefault(); window.print(); setOpen(false); }}>Print</a>
          <a href="#" onClick={(e) => { e.preventDefault(); onOpenSource(); setOpen(false); }}>View source →</a>
        </nav>
      )}
    </header>
  );
}

function Logo() {
  return (
    <svg viewBox="0 0 28 28" className="size-7 text-[var(--accent)]">
      <circle cx="14" cy="14" r="12.5" fill="none" stroke="currentColor" strokeWidth="1.4"/>
      <path d="M9 11c0-2.8 2.2-5 5-5s5 2.2 5 5v3H9z" fill="currentColor" opacity="0.18"/>
      <path d="M9 11c0-2.8 2.2-5 5-5s5 2.2 5 5v3H9z M11 14v6M14 14v6M17 14v6" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinejoin="round"/>
    </svg>
  );
}

// ───────────────────────────── Hero ─────────────────────────────

function Hero({ data, onOpenConfidence, onOpenSource, cookMode, setCookMode }) {
  const m = data.metadata;
  return (
    <section className="oc-hero">
      <div className="oc-hero-text">
        <div className="flex items-center gap-2 text-[12px] font-mono uppercase tracking-[0.14em] text-stone-500">
          <span>Mains</span><Dot /><span>Autumn</span><Dot /><span>One-pan</span>
        </div>
        <h1 className="oc-hero-title">{data.title}</h1>
        {data.instructions && data.instructions.length > 0 && (
          <p className="oc-hero-deck">
            {(() => {
              const first = data.instructions[0]?.text || "";
              return first.length > 180 ? first.slice(0, 177) + "…" : first;
            })()}
          </p>
        )}

        <div className="mt-7 flex flex-wrap items-center gap-2.5">
          <button onClick={() => setCookMode(!cookMode)} className={`oc-btn-primary ${cookMode ? "oc-btn-primary-on" : ""}`}>
            {cookMode ? "Exit cook mode" : "Start cook mode"}
            <svg viewBox="0 0 16 16" className="size-3.5"><path d="M5 3l6 5-6 5" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"/></svg>
          </button>
          <button onClick={onOpenSource} className="oc-btn-secondary">
            <svg viewBox="0 0 16 16" className="size-3.5"><path d="M2 4h12v9H2z M2 4l6 5 6-5" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinejoin="round"/></svg>
            View source
          </button>
        </div>

        <div className="mt-9 grid grid-cols-2 gap-x-7 gap-y-5 sm:grid-cols-4">
          <Stat label="Prep" v={m.prep_time} />
          <Stat label="Cook" v={m.cook_time} />
          <Stat label="Serves" v={m.servings} />
          <Stat label="Difficulty" v={m.difficulty} extra={<DifficultyPips n={1} />} />
        </div>
      </div>

      <aside className="oc-hero-side">
        <ConfidenceCard data={data} onOpenConfidence={onOpenConfidence} onOpenSource={onOpenSource} />
      </aside>
    </section>
  );
}

function Stat({ label, v, extra }) {
  return (
    <div>
      <div className="oc-eyebrow">{label}</div>
      <div className="mt-1.5 flex items-baseline gap-2">
        <span className="font-display text-[22px] text-stone-900">{v}</span>
        {extra}
      </div>
    </div>
  );
}

function DifficultyPips({ n }) {
  return (
    <span className="flex items-center gap-[3px]">
      {Array.from({ length: 5 }).map((_, i) => (
        <span key={i} className={`size-1.5 rounded-full ${i < n ? "bg-stone-900" : "bg-stone-300"}`} />
      ))}
    </span>
  );
}

function Dot() { return <span className="size-1 rounded-full bg-stone-400" />; }

// ───────────────────────────── Confidence Card ─────────────────────────────

function ConfidenceCard({ data, onOpenConfidence, onOpenSource }) {
  const c = data.confidence_assessment;
  const t = tierFor(c.overall_score);
  return (
    <div className="oc-confidence-card">
      <div className="flex items-start justify-between gap-3">
        <div>
          <div className="oc-eyebrow">Extraction Confidence</div>
          <div className="mt-1 flex items-baseline gap-2">
            <span className="font-display text-[40px] leading-none tabular-nums" style={{ color: t.hex }}>
              {c.overall_score.toFixed(2)}
            </span>
            <span className="font-mono text-[11px] text-stone-500">/ 10.00</span>
          </div>
        </div>
        <span className={`oc-tier-chip ${t.className}`}>
          <span className="oc-dot" /> {t.label}
        </span>
      </div>

      <div className="mt-5 space-y-2.5">
        {Object.entries(c.field_scores).map(([k, v]) => {
          const ft = tierFor(v);
          return (
            <div key={k}>
              <div className="mb-1 flex items-baseline justify-between">
                <span className="text-[12px] capitalize text-stone-700">{k}</span>
                <span className="font-mono text-[11px] tabular-nums text-stone-500">{v.toFixed(2)}</span>
              </div>
              <div className="h-[3px] w-full overflow-hidden rounded-full bg-stone-200/70">
                <div className="h-full" style={{ width: `${(v / 10) * 100}%`, background: ft.hex }} />
              </div>
            </div>
          );
        })}
      </div>

      <div className="mt-5 flex items-center justify-between gap-2 border-t border-stone-200/80 pt-4">
        <div className="font-mono text-[11px] uppercase tracking-[0.1em] text-stone-500">
          {data.source_type} · iter #{c.iteration}
        </div>
        <button onClick={onOpenConfidence} className="oc-link">Breakdown →</button>
      </div>

      <div className="mt-3 flex items-center gap-2 rounded-md bg-amber-50/70 px-3 py-2 text-[11.5px] leading-snug text-amber-900 ring-1 ring-amber-200/60">
        <svg viewBox="0 0 16 16" className="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>
        <span>{c.ambiguities.length} ambiguities flagged. <button onClick={onOpenSource} className="underline underline-offset-2">Review →</button></span>
      </div>
    </div>
  );
}

// ───────────────────────────── Provenance Strip ─────────────────────────────

function ProvenanceStrip({ data, onOpenSource }) {
  return (
    <div className="oc-provenance">
      <div className="flex items-center gap-3">
        <span className="oc-prov-icon">
          <svg viewBox="0 0 16 16" className="size-3.5"><path d="M3 13l3-1L13 5l-2-2-7 7-1 3z" fill="none" stroke="currentColor" strokeWidth="1.3" strokeLinejoin="round"/></svg>
        </span>
        <div className="text-[13px] text-stone-700">
          Extracted from a <span className="font-medium text-stone-900">{data.source_type === 'handwritten' ? 'handwritten note' : data.source_type + ' source'}</span>
          <span className="mx-2 text-stone-400">·</span>
          OneCook Vision v3
          <span className="mx-2 text-stone-400">·</span>
          1 source artifact
        </div>
      </div>
      <button onClick={onOpenSource} className="oc-link">View original →</button>
    </div>
  );
}

// ───────────────────────────── Ingredients ─────────────────────────────

function Ingredients({ data, servings, setServings, factor, checked, toggleIng, cookMode }) {
  const baseServings = data.metadata.servings;
  return (
    <aside className="oc-ing">
      <div className="oc-ing-sticky">
        <div className="flex items-baseline justify-between">
          <h2 className="font-display text-[28px] text-stone-900">Ingredients</h2>
          <span className="font-mono text-[11px] uppercase tracking-[0.1em] text-stone-500">
            {data.ingredients.length} items
          </span>
        </div>

        <div className="mt-5 flex items-center justify-between rounded-lg border border-stone-200/90 bg-white/50 px-3 py-2.5">
          <div>
            <div className="oc-eyebrow">Serves</div>
            <div className="mt-0.5 font-display text-[20px] tabular-nums text-stone-900">{servings}</div>
          </div>
          <div className="flex items-center gap-1">
            <button onClick={() => setServings(Math.max(1, servings - 1))} className="oc-stepper">−</button>
            <button onClick={() => setServings(servings + 1)} className="oc-stepper">+</button>
            {servings !== baseServings && (
              <button onClick={() => setServings(baseServings)} className="ml-2 text-[11px] font-mono uppercase tracking-[0.1em] text-stone-500 hover:text-stone-900">reset</button>
            )}
          </div>
        </div>

        <ul className="mt-6 space-y-1">
          {data.ingredients.map((ing, i) => (
            <IngRow key={i} ing={ing} factor={factor} checked={checked.has(i)} onToggle={() => toggleIng(i)} cookMode={cookMode} />
          ))}
        </ul>
      </div>
    </aside>
  );
}

function IngRow({ ing, factor, checked, onToggle, cookMode }) {
  const scaled = scaleQuantity(ing.quantity, factor);
  const scaledChanged = scaled !== ing.quantity && ing.quantity;
  return (
    <li className={`oc-ing-row ${checked ? "is-checked" : ""}`}>
      <button onClick={onToggle} className="oc-checkbox" aria-pressed={checked}>
        {checked && <svg viewBox="0 0 16 16" className="size-3"><path d="M3 8.5l3 3 7-7" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"/></svg>}
      </button>
      <div className="flex-1">
        <div className="flex items-baseline gap-2">
          {ing.quantity && (
            <span className="oc-qty">
              {scaled}
              {scaledChanged && <span className="oc-qty-orig"> · was {ing.quantity}</span>}
            </span>
          )}
          {ing.unit && <span className="oc-unit">{ing.unit}</span>}
          <span className="oc-item">{ing.item}</span>
        </div>
        {ing.preparation && <div className="oc-prep">{ing.preparation}</div>}
      </div>
    </li>
  );
}

// ───────────────────────────── Instructions ─────────────────────────────

function Instructions({ data, doneSteps, toggleStep, activeStep, setActiveStep, cookMode }) {
  // Lightweight phase grouping: thirds of the step list (or none if <6 steps)
  const phases = useMemo(() => {
    const n = data.instructions.length;
    if (n < 6) return [{ title: null, range: [1, n] }];
    const a = Math.ceil(n / 3);
    const b = Math.ceil((n * 2) / 3);
    return [
      { title: "Prep", range: [1, a] },
      { title: "Cook", range: [a + 1, b] },
      { title: "Finish", range: [b + 1, n] },
    ];
  }, [data.instructions.length]);

  return (
    <section className="oc-instr">
      <div className="flex items-baseline justify-between">
        <h2 className="font-display text-[28px] text-stone-900">Method</h2>
        <span className="font-mono text-[11px] uppercase tracking-[0.1em] text-stone-500">
          {data.instructions.length} steps · {doneSteps.size}/{data.instructions.length} done
        </span>
      </div>

      <div className="oc-progress mt-4">
        <div className="oc-progress-fill" style={{ width: `${(doneSteps.size / data.instructions.length) * 100}%` }} />
      </div>

      <div className="mt-10 space-y-12">
        {phases.map((phase, pi) => (
          <div key={pi}>
            <div className="mb-5 flex items-center gap-3">
              <span className="font-mono text-[11px] uppercase tracking-[0.16em] text-stone-500">
                Phase {pi + 1}
              </span>
              <span className="h-px flex-1 bg-stone-200" />
              <h3 className="font-display text-[18px] text-stone-800">{phase.title}</h3>
            </div>
            <ol className="space-y-3">
              {data.instructions
                .filter((s) => s.step_number >= phase.range[0] && s.step_number <= phase.range[1])
                .map((step) => (
                  <StepRow
                    key={step.step_number}
                    step={step}
                    done={doneSteps.has(step.step_number)}
                    onToggle={() => toggleStep(step.step_number)}
                    isAmbiguous={false}
                  />
                ))}
            </ol>
          </div>
        ))}
      </div>
    </section>
  );
}

function StepRow({ step, done, onToggle, isAmbiguous }) {
  return (
    <li className={`oc-step ${done ? "is-done" : ""} ${isAmbiguous ? "is-ambiguous" : ""}`}>
      <button onClick={onToggle} className="oc-step-num" aria-pressed={done}>
        {done ? (
          <svg viewBox="0 0 16 16" className="size-3.5"><path d="M3 8.5l3 3 7-7" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"/></svg>
        ) : (
          <span className="font-mono tabular-nums">{String(step.step_number).padStart(2, "0")}</span>
        )}
      </button>
      <div className="flex-1">
        <p className="oc-step-text">{step.text}</p>
        <div className="mt-2 flex flex-wrap items-center gap-1.5">
          {(step.temperature_c != null || step.temperature != null) && (() => {
            const c = step.temperature_c != null ? step.temperature_c : (typeof step.temperature === 'number' ? step.temperature : null);
            if (c == null) return null;
            return <Chip icon="thermo">{(c * 9 / 5 + 32).toFixed(0)}°F · {c}°C</Chip>;
          })()}
          {step.time_duration && <Chip icon="clock">{step.time_duration}</Chip>}
          {isAmbiguous && (
            <span className="oc-ambig-chip">
              <svg viewBox="0 0 16 16" className="size-3"><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>
              Flagged · review against source
            </span>
          )}
        </div>
      </div>
    </li>
  );
}

function Chip({ icon, children }) {
  const icons = {
    thermo: <path d="M8 2v9 M6 11a2 2 0 104 0 M6 11V4a2 2 0 014 0v7" fill="none" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round"/>,
    clock: <><circle cx="8" cy="8" r="6" fill="none" stroke="currentColor" strokeWidth="1.3"/><path d="M8 4.5V8l2.5 1.5" fill="none" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round"/></>,
  };
  return (
    <span className="oc-chip">
      <svg viewBox="0 0 16 16" className="size-3">{icons[icon]}</svg>
      {children}
    </span>
  );
}

// ───────────────────────────── Notes ─────────────────────────────

function Notes({ data, onOpenSource, onOpenConfidence }) {
  const ambig = data.confidence_assessment?.ambiguities || [];
  if (ambig.length === 0) return null;
  return (
    <section className="mt-20">
      <div className="oc-note oc-note-warn">
        <div className="flex items-center justify-between">
          <div className="oc-eyebrow mb-2">Source ambiguities</div>
          <button onClick={onOpenConfidence} className="oc-link">View all →</button>
        </div>
        <ul className="space-y-3 text-[14px] leading-relaxed text-stone-700">
          {ambig.map((a, i) => (
            <li key={i} className="flex gap-3">
              <span className="mt-[6px] inline-block size-1.5 shrink-0 rounded-full bg-amber-500" />
              <span>{a}</span>
            </li>
          ))}
        </ul>
        <button onClick={onOpenSource} className="oc-btn-secondary mt-5">
          Compare with original →
        </button>
      </div>
    </section>
  );
}

function Footer() {
  return (
    <footer className="oc-footer">
      <div className="flex items-center gap-2">
        <Logo /> <span className="font-display text-[15px] text-stone-700">OneCook</span>
        <span className="font-mono text-[11px] uppercase tracking-[0.1em] text-stone-400">
          · Recipes you've actually cooked
        </span>
      </div>
      <div className="font-mono text-[11px] uppercase tracking-[0.1em] text-stone-400">
        v3.2.1 · build a7f9d2
      </div>
    </footer>
  );
}

// ───────────────────────────── Mount ─────────────────────────────

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
