/* Self-serve mode — public-facing conversational flow at /roi.

   Single column layout. User types a description, we extract, we show a result.
   The original §3.1 structured form is repurposed as the collapsed "Tweak the
   inputs" panel below the result. Implements §2 of the addendum (v0.2). */

const { useState: useStateSS, useEffect: useEffectSS, useMemo: useMemoSS, useRef: useRefSS, useCallback: useCallbackSS } = React;


function MaturitySuggestionCard({ suggestion, onAdjust }) {
  if (!suggestion) return null;
  const { groupName, groupLabel, pitch, colour, evidence } = suggestion;
  const evidenceLine = evidence.length
    ? `Based on what you told us about ${evidence.slice(0, 3).join(", ")}, `
    : "";
  return (
    <div className="maturity-suggest-card" style={{ "--group-colour": colour }}>
      <div className="maturity-suggest-card__head">
        <div className="maturity-suggest-card__badge" style={{ background: colour }}>{groupName}</div>
        <div className="maturity-suggest-card__label">{groupLabel}</div>
      </div>
      <p className="maturity-suggest-card__pitch">
        {evidenceLine}{pitch}
      </p>
      <div className="maturity-suggest-card__foot">
        <span className="maturity-suggest-card__hint">
          This drives the maturity factor in your ROI — adjust the sliders below if it doesn't look right.
        </span>
        <button className="btn link" onClick={onAdjust}>Adjust tracking data ↓</button>
      </div>
    </div>
  );
}

function OpportunityCard({ transcript }) {
  if (!transcript || !transcript.length) return null;
  const opp = analyseOpportunity(transcript);
  if (!opp.signals.length) return null;
  return (
    <div className="opportunity-card">
      <div className="opportunity-card__head">
        <div>
          <div className="eyebrow">Based on what you told us</div>
          <h4 className="opportunity-card__title">Opportunity assessment</h4>
        </div>
        <span className="opportunity-card__level" style={{ color: opp.levelColor }}>{opp.level} opportunity</span>
      </div>
      <ul className="opportunity-card__signals">
        {opp.signals.map((s, i) => <li key={i}>{s}</li>)}
      </ul>
    </div>
  );
}

function SelfServe({ tweaks }) {
  // High-level phase: where in the conversational flow are we?
  // 'landing'    → conversational input only, no result
  // 'extracting' → loading state shown inside ConversationalInput
  // 'followup'   → branch-A inline follow-up question
  // 'result'     → branch-B (extraction succeeded) — full result revealed
  const initialPhase = tweaks.start === "result" ? "result" : "chat";

  const [phase, setPhase] = useStateSS(initialPhase);
  const [heroVisible, setHeroVisible] = useStateSS(true);
  const heroRef = useRefSS(null);
  const [extraction, setExtraction] = useStateSS(
    initialPhase === "result" ? mockExtract("We're a 20-machine subcontract CNC shop in Coventry. Mostly aerospace and motorsport. Two shifts five days, we're absolutely flat out and our lead times have crept up. Charge-out is around £60/hr. Thinking about a new 5-axis, probably £250k.") :
    null
  );
  const [transcript, setTranscript] = useStateSS([]);

  // Structured "tweak" state — populated from extraction once it lands
  const [scenario, setScenario] = useStateSS(tweaks.scenario || "conservative");
  const [refineOpen, setRefineOpen] = useStateSS(!!tweaks.refineOpen);
  const [bcOpen, setBcOpen] = useStateSS(false);
  const [understoodOpen, setUnderstoodOpen] = useStateSS(true);

  // Per-field overrides (the "Tweak the inputs" panel writes here)
  const [overrides, setOverrides] = useStateSS({});
  const refineRef = useRefSS(null);

  useEffectSS(() => { setScenario(tweaks.scenario || "conservative"); }, [tweaks.scenario]);

  // Pin net value in nav once the hero row scrolls out of view
  useEffectSS(() => {
    if (!heroRef.current) return;
    const obs = new IntersectionObserver(
      ([entry]) => setHeroVisible(entry.isIntersecting),
      { rootMargin: "0px 0px 0px 0px", threshold: 0 }
    );
    obs.observe(heroRef.current);
    return () => obs.disconnect();
  }, [phase]);

  // Reset overrides when a fresh extraction comes in (e.g. via "Tell us more")
  const onExtractionResult = (result, transcriptArr) => {
    setExtraction(result);
    setTranscript(transcriptArr || []);
    setOverrides({});
    setUnderstoodOpen(true);
    setPhase("result");
  };
  const onAddContext = (text) => {
    const newR = mockExtract(text, extraction);
    setExtraction(newR);
    setUnderstoodOpen(true);
  };

  // Build engine inputs from extraction + overrides
  const inputs = useMemoSS(() => {
    const x = extraction?.extracted || {};
    const o = overrides;
    const sector = o.sector || x.sector || "subcon_cnc";

    // Use machineHoursPerWeek directly
    const machineHoursPerWeek = o.machineHoursPerWeek != null
      ? o.machineHoursPerWeek
      : (x.machineHoursPerWeek ?? (x.shiftsPerDay && x.hoursPerShift && x.daysPerWeek
          ? x.shiftsPerDay * x.hoursPerShift * x.daysPerWeek
          : 80));  // default 2 shifts × 8h × 5 days

    const merged = {
      sector,
      machineCount: o.machineCount != null ? o.machineCount : (x.machineCount || 10),
      machineHoursPerWeek,
      weeksPerYear: o.weeksPerYear ?? x.weeksPerYear ?? 48,
      scenario,
      demandConstrained: o.demandConstrained != null ? o.demandConstrained : (x.demandConstrained ?? true),
    };
    const chargeOut = o.chargeOutRate != null ? o.chargeOutRate : x.chargeOutRate;
    if (chargeOut) merged.chargeOutRate = chargeOut;
    const capex = o.plannedCapex != null ? o.plannedCapex : x.plannedCapex;
    if (capex && capex.price) merged.plannedCapex = capex;
    const util = o.currentUtilisationPct != null ? o.currentUtilisationPct : x.currentUtilisationPct;
    if (util) merged.currentUtilisationPct = util;
    const rev = o.annualRevenue != null ? o.annualRevenue : x.annualRevenue;
    if (rev) merged.annualRevenue = rev;
    const mdh = o.manualDataHoursPerWeek != null ? o.manualDataHoursPerWeek : x.manualDataHoursPerWeek;
    if (mdh) merged.manualDataHoursPerWeek = mdh;
    const trackingMaturity = o.trackingMaturity ?? x.trackingMaturity ?? null;
    if (trackingMaturity) merged.trackingMaturity = trackingMaturity;
    return merged;
  }, [extraction, overrides, scenario]);

  const result = useMemoSS(() => {
    if (phase !== "result") return null;
    try { return window.FJ.calculateROI(inputs); } catch (e) { return null; }
  }, [inputs, phase]);

  const scrollToTweak = () => {
    setRefineOpen(true);
    setTimeout(() => {
      refineRef.current?.scrollIntoView?.({ behavior: "smooth", block: "start" });
    }, 50);
  };

  return (
    <div className={"roi-app" + (tweaks.dark ? " dark" : "")}>
      <div className="conv-shell">
        <div className="conv-nav">
          <div className="logo">
            <img src={tweaks.dark ? "assets/logo-primary-white.svg" : "assets/logo-primary.svg"} alt="FourJaw" />
          </div>
          <div className="conv-nav__crumb">ROI Calculator</div>
          <div className="conv-nav__spacer" />
          {phase === "result" && result && !heroVisible && (
            <div className="conv-nav__stickyval">
              <span className="conv-nav__stickyval__n">{fmtGbp(result.year1NetValue)}</span>
              <span className="conv-nav__stickyval__s">yr 1 net · {result.paybackMonths < 999 ? result.paybackMonths.toFixed(1) + " mo payback" : "—"}</span>
            </div>
          )}
          <div className="conv-nav__phase">
            {phase === "result"
              ? <><span className="dot dot--purple" /> Result based on what you told us</>
              : <><span className="dot dot--ink" /> Tell us about your factory</>}
          </div>
        </div>

        <div className="conv-main">
          {phase === "chat" && (
            <ChatConversation dark={tweaks.dark} onResult={onExtractionResult} />
          )}

          {/* Phase 4 — result revealed */}
          {phase === "result" && result && extraction && (
            <>
              {/* Compact, slimmed-down version of the original prompt */}
              <div className="conv__topbar">
                <div>
                  <div className="eyebrow">Your description</div>
                  <div className="conv__topbarText">
                    {(extraction.extracted.sector ? SECTOR_META[extraction.extracted.sector].name + " · " : "") +
                     (extraction.extracted.machineCount ? extraction.extracted.machineCount + " machines · " : "") +
                     (extraction.extracted.shiftsPerDay ? extraction.extracted.shiftsPerDay + "-shift" : "")}
                  </div>
                </div>
                <button className="btn ghost" onClick={() => setPhase("chat")}>Start over</button>
              </div>

              <UnderstoodPanel
                extraction={extraction}
                onTweakClick={scrollToTweak}
                defaultOpen={understoodOpen}
              />

              <OpportunityCard transcript={transcript} />

              <MaturitySuggestionCard
                suggestion={extraction?.maturitySuggestion}
                onAdjust={scrollToTweak}
              />

              {/* Hero + scenario toggle. Sentinel div marks the bottom of the headline number —
                  when it scrolls off, the sticky nav value appears. */}
              <div className="result-hero-row">
                <div className="result-hero-row__hero">
                  <ResultHeadline engineOutput={result} scenario={scenario} />
                  <div ref={heroRef} style={{ height: 0, overflow: "hidden" }} aria-hidden="true" />
                </div>
                <div className="result-hero-row__side">
                  <div className="eyebrow">Scenario</div>
                  <ScenarioToggle value={scenario} onChange={setScenario} />
                  <p className="result-hero-row__scenarioNote">
                    {scenario === "conservative" && "The defensible number — uplift assumptions below typical engaged customers."}
                    {scenario === "realistic"    && "The number we'd put in a forecast — broadly matches engaged customer outcomes."}
                    {scenario === "aspirational" && "The case-study ceiling — Armac Martin saw a 65% capacity boost on this lever."}
                  </p>
                </div>
              </div>

              {/* Drivers */}
              <section className="result-section">
                <div className="sec-head"><h3>Where the value comes from</h3><span className="sec-head__meta">Click any £ for the working</span></div>
                <DriverBreakdown engineOutput={result} />
              </section>

              {/* Operational metrics */}
              <section className="result-section">
                <div className="sec-head"><h3>What you'd see operationally</h3></div>
                <OperationalMetrics engineOutput={result} />
              </section>

              {/* Sensitivity — top 3 cards */}
              {result.sensitivity && result.sensitivity.length > 0 && (
                <section className="result-section">
                  <div className="sec-head">
                    <h3>How sensitive is this?</h3>
                    <span className="sec-head__meta">If the top driver was half what we've modelled…</span>
                  </div>
                  <SensitivityCallouts engineOutput={result} />
                </section>
              )}

              {/* Tweak the inputs — repurposed from the old §3.1 form */}
              <div ref={refineRef}>
                <TweakInputsPanel
                  open={refineOpen}
                  onToggle={setRefineOpen}
                  extraction={extraction}
                  overrides={overrides}
                  setOverrides={setOverrides}
                  inputs={inputs}
                  appliedDefaultsCount={result.appliedDefaults.length}
                />
              </div>

              {/* Tell us more — the conversational thread */}
              <TellUsMore onAddContext={onAddContext} />

              {/* Business case CTA */}
              <section className="result-section result-section--cta">
                <div className="sec-head"><h3>Get the full one-page business case</h3></div>
                <p className="result-cta__p">
                  A sober internal memo tailored to whoever's making the call —
                  Finance Director, MD, Operations Director or CI Manager. We email it as a PDF.
                </p>
                <button className="btn primary lg" onClick={() => setBcOpen(true)}>
                  <img src="assets/icons/page.svg" alt="" style={{ width: 16, height: 16, filter: "invert(1)" }} />
                  Get the business case
                </button>
              </section>
            </>
          )}
        </div>

        {bcOpen && result && (
          <BusinessCaseDialog
            engineOutput={result}
            onClose={() => setBcOpen(false)}
          />
        )}
      </div>
    </div>
  );
}

/* ============================================================
   TweakInputsPanel — the structured form, now repurposed as
   "Tweak the inputs" (collapsed by default, pre-filled from extraction)
   ============================================================ */
function TweakInputsPanel({ open, onToggle, extraction, overrides, setOverrides, inputs, appliedDefaultsCount }) {
  const setO = (patch) => setOverrides({ ...overrides, ...patch });
  const x = extraction?.extracted || {};

  const sector = inputs.sector;
  const machineCount = inputs.machineCount;
  const chargeOutRate = inputs.chargeOutRate || null;
  const plannedCapex = inputs.plannedCapex || null;
  const utilisation = inputs.currentUtilisationPct || null;
  const demandConstrained = inputs.demandConstrained;
  const annualRevenue = inputs.annualRevenue || "";

  const isStated = (f) => (extraction?.stated || []).includes(f);
  const isInferred = (f) => (extraction?.inferred || []).some((i) => i.field.split(".")[0] === f);
  const sourceBadge = (f) => {
    if (overrides[f] != null) return <span className="src-badge src-badge--user">edited</span>;
    if (isStated(f))   return <span className="src-badge src-badge--stated">from your text</span>;
    if (isInferred(f)) return <span className="src-badge src-badge--inferred">inferred</span>;
    return <span className="src-badge src-badge--default">sector default</span>;
  };

  return (
    <details className="refine refine--tweak" open={open} onToggle={(e) => onToggle(e.target.open)}>
      <summary>
        <div className="ico"><img src="assets/icons/cogs.svg" alt="" /></div>
        <div className="lbl">
          <h4>Tweak the inputs</h4>
          <p>
            Every field below is pre-populated from your description — we've marked which came from your text, which we inferred, and which fell back to sector defaults
            ({appliedDefaultsCount} fields). Change anything and the result recomputes.
          </p>
        </div>
        <span className="chev" />
      </summary>
      <div className="refine-body refine-body--tweak">

        <label className="field full">
          <div className="field__label">Sector {sourceBadge("sector")}</div>
          <select value={sector} onChange={(e) => setO({ sector: e.target.value })}>
            {Object.entries(SECTOR_META).map(([k, m]) => (
              <option key={k} value={k}>{m.name}</option>
            ))}
          </select>
        </label>

        <label className="field">
          <div className="field__label">Machine count {sourceBadge("machineCount")}</div>
          <input
            type="number"
            min={1} max={500}
            value={machineCount}
            onChange={(e) => setO({ machineCount: Math.max(1, Math.min(500, Number(e.target.value) || 1)) })}
          />
        </label>

        <label className="field">
          <div className="field__label">Machine hours / week {sourceBadge("machineHoursPerWeek")}</div>
          <input
            type="number"
            min={8} max={168}
            value={inputs.machineHoursPerWeek || 80}
            onChange={(e) => setO({ machineHoursPerWeek: Math.max(8, Math.min(168, Number(e.target.value) || 80)) })}
          />
          <span className="hint">Total hours machines run per week (e.g. 40 = 1 shift × 8h × 5 days, 80 = 2 shifts, 120 = 3 shifts)</span>
        </label>

        <label className="field">
          <div className="field__label">Weeks / year {sourceBadge("weeksPerYear")}</div>
          <input
            type="number"
            min={30} max={52}
            value={inputs.weeksPerYear || 48}
            onChange={(e) => setO({ weeksPerYear: Math.max(30, Math.min(52, Number(e.target.value) || 48)) })}
          />
        </label>

        <label className="field">
          <div className="field__label">Charge-out rate (£/hr) {sourceBadge("chargeOutRate")}</div>
          <input
            type="number"
            placeholder={`Sector default ≈ £${Math.round(window.FJ.SECTOR_DEFAULTS[sector].marginPerHour / (window.FJ.CHARGE_OUT_HAIRCUTS[sector] || 0.4))}`}
            value={chargeOutRate || ""}
            onChange={(e) => setO({ chargeOutRate: e.target.value ? Number(e.target.value) : null })}
          />
          <span className="hint">
            We apply a {Math.round((window.FJ.CHARGE_OUT_HAIRCUTS[sector] || 0.4) * 100)}% sector haircut to get contribution margin.
          </span>
        </label>

        <label className="field">
          <div className="field__label">Measured utilisation (%) {sourceBadge("currentUtilisationPct")}</div>
          <input
            type="number"
            min={10} max={85}
            placeholder={`Sector avg: ${window.FJ.SECTOR_DEFAULTS[sector].utilisationPct}%`}
            value={utilisation || ""}
            onChange={(e) => setO({ currentUtilisationPct: e.target.value ? Number(e.target.value) : null })}
          />
          <span className="hint">If you've measured it. Otherwise we use the sector average.</span>
        </label>

        <label className="field">
          <div className="field__label">Annual revenue (£) {sourceBadge("annualRevenue")}</div>
          <input
            type="number"
            placeholder="Optional — unlocks the quality lever"
            value={annualRevenue}
            onChange={(e) => setO({ annualRevenue: e.target.value ? Number(e.target.value) : null })}
          />
        </label>

        <div className="field full">
          <div className="field__label">Planned capex {sourceBadge("plannedCapex")}</div>
          <div className="capex-row">
            <button
              type="button"
              className={"toggle-switch" + (plannedCapex ? " on" : "")}
              onClick={() => setO({ plannedCapex: plannedCapex ? null : { price: 150000, deferralYears: 2 } })}
              aria-pressed={!!plannedCapex}
            />
            <span className="capex-row__lbl">{plannedCapex ? "Considering a new machine" : "No planned capex"}</span>
            {plannedCapex && (
              <>
                <span className="capex-row__sep">·</span>
                <span className="capex-row__lbl">Price</span>
                <input
                  type="number"
                  className="capex-row__price"
                  value={plannedCapex.price}
                  onChange={(e) => setO({ plannedCapex: { ...plannedCapex, price: Number(e.target.value) || 0 } })}
                />
                <span className="capex-row__lbl">defer</span>
                <select
                  className="capex-row__defer"
                  value={plannedCapex.deferralYears}
                  onChange={(e) => setO({ plannedCapex: { ...plannedCapex, deferralYears: Number(e.target.value) } })}
                >
                  <option value={1}>1 yr</option>
                  <option value={2}>2 yrs</option>
                  <option value={3}>3 yrs</option>
                </select>
              </>
            )}
          </div>
        </div>

        <label className="field full">
          <div className="toggle-pair">
            <span className="lbl">Could you sell the extra hours if you had them? {sourceBadge("demandConstrained")}</span>
            <button
              type="button"
              className={"toggle-switch" + (demandConstrained ? " on" : "")}
              onClick={() => setO({ demandConstrained: !demandConstrained })}
              aria-pressed={!!demandConstrained}
            />
          </div>
          <span className="hint">
            {demandConstrained
              ? "Yes — full capacity value applied."
              : "No — capacity value halved to reflect unsold hours."}
          </span>
        </label>

        <div className="field full">
          <div className="field__label">How well do you currently track? {sourceBadge("trackingMaturity")}</div>
          <MaturityPicker
            value={inputs.trackingMaturity}
            onChange={(v) => setO({ trackingMaturity: v })}
          />
        </div>

      </div>
    </details>
  );
}

/* ============================================================
   MaturityPicker — 5 independent 1-5 sliders, one per FourJaw dimension.
   Free-text scores pre-position each slider; user can adjust any of them.
   engine value per dimension: 0–2 (fractional ok, engine just sums them).
   slider 1→0, 2→0.5, 3→1, 4→1.5, 5→2
   ============================================================ */

const MATURITY_DIMS = [
  { key: "utilisation", label: "Machine runtime / utilisation" },
  { key: "downtime",    label: "Stoppages and downtime" },
  { key: "jobs",        label: "Jobs, batches or work orders" },
  { key: "energy",      label: "Energy consumption" },
  { key: "partCount",   label: "Output / part count" },
];

const MATURITY_TICK_LABELS = ["", "Not tracked", "By eye", "Manual logs", "Some system", "Covered"];

function dimToSlider(v) { return Math.min(5, Math.max(1, Math.round(v * 2 + 1))); }
function sliderToDim(s) { return (s - 1) / 2; }

function MaturityPicker({ value, onChange }) {
  const v = value ?? { utilisation: 1, downtime: 1, jobs: 1, energy: 1, partCount: 1 };
  const [local, setLocal] = useStateSS(null);
  const current = local ?? v;

  const handleInput  = (key, s) => setLocal(prev => ({ ...(prev ?? current), [key]: sliderToDim(s) }));
  const handleCommit = (key, s) => { const next = { ...(local ?? v), [key]: sliderToDim(s) }; setLocal(null); onChange(next); };

  return (
    <div className="maturity-dims">
      <div className="maturity-dims__legend">
        <span>1 — Not tracked</span>
        <span>5 — Got it covered</span>
      </div>
      {MATURITY_DIMS.map(({ key, label }) => {
        const s = dimToSlider(current[key] ?? 1);
        return (
          <div key={key} className="maturity-dim-row">
            <span className="maturity-dim-row__label">{label}</span>
            <div className="maturity-dim-row__slider">
              <input
                type="range" min={1} max={5} step={1} value={s}
                className="maturity-slider"
                style={{ "--v": s }}
                onChange={e => handleInput(key, Number(e.target.value))}
                onPointerUp={e => handleCommit(key, Number(e.target.value))}
                onMouseUp={e => handleCommit(key, Number(e.target.value))}
              />
              <div className="maturity-dim-row__ticks">
                {[1,2,3,4,5].map(n => (
                  <span key={n} className={"maturity-tick" + (n === s ? " active" : "")}>{n}</span>
                ))}
              </div>
            </div>
            <span className="maturity-dim-row__val">{MATURITY_TICK_LABELS[s]}</span>
          </div>
        );
      })}
    </div>
  );
}

Object.assign(window, { SelfServe, TweakInputsPanel, MaturityPicker });
