/* ============================================================
   B4IOU — main app / step machine
   ============================================================ */

const STEP_META = {
  landing: { n: 0, label: "" },
  input:   { n: 1, label: "01 / Schools" },
  aid:     { n: 2, label: "02 / Aid" },
  loading: { n: 3, label: "03 / Report" },
  report:  { n: 3, label: "03 / Report" },
  paywall: { n: 4, label: "Unlock" },
  post:    { n: 5, label: "Done" },
};
const TOTAL = 5;

function App() {
  const [step, setStep] = useState("landing");
  const [schools, setSchools] = useState([
    { name: "", program: "" },
    { name: "", program: "" },
    { name: "", program: "" },
  ]);
  const [usState, setUsState] = useState("");
  const [aid, setAid] = useState({ mode: null, answers: {}, saiFile: null });
  const [report, setReport] = useState(null);
  const [tier, setTier] = useState(null);
  const [err, setErr] = useState(null);
  const [toastMsg, setToastMsg] = useState("");
  const [previewHTML, setPreviewHTML] = useState(null);
  const toastTimer = useRef(null);

  useEffect(() => {
    function onPreview(e) { setPreviewHTML(e.detail && e.detail.html); }
    window.addEventListener("b4iou:preview", onPreview);
    return () => window.removeEventListener("b4iou:preview", onPreview);
  }, []);

  // returning from Stripe Checkout: ?paid=<session_id>&tier=<tier> → verify + unlock
  useEffect(() => {
    const cfg = window.B4IOU_CONFIG || {};
    const params = new URLSearchParams(window.location.search);
    const paid = params.get("paid");
    if (!paid) return;
    (async () => {
      let ok = true;
      if (cfg.BACKEND) {
        try {
          const r = await fetch("/api/verify-session?id=" + encodeURIComponent(paid));
          const d = await r.json();
          ok = !!d.paid;
        } catch (e) { ok = false; }
      }
      if (ok) {
        try {
          const saved = JSON.parse(localStorage.getItem("b4iou_pending") || "null");
          if (saved && saved.report) {
            setReport(saved.report);
            const s = (saved.schools || []).slice(0, 3);
            while (s.length < 3) s.push({ name: "", program: "" });
            setSchools(s);
            setTier(saved.tier || params.get("tier"));
            setStep("post");
          }
        } catch (e) {}
        try { localStorage.removeItem("b4iou_pending"); } catch (e) {}
      }
      window.history.replaceState({}, "", window.location.pathname);
    })();
  }, []);

  const scrollRef = useRef(null);
  useEffect(() => { if (scrollRef.current) scrollRef.current.scrollTop = 0; window.scrollTo(0, 0); }, [step]);

  function toast(msg) {
    setToastMsg(msg);
    clearTimeout(toastTimer.current);
    toastTimer.current = setTimeout(() => setToastMsg(""), 2200);
  }

  function buildInput(includeThird) {
    const active = schools.filter((s, i) => s.name.trim() && (includeThird || i < 2)).slice(0, includeThird ? 3 : 2);
    return {
      schools: active,
      state: usState,
      answers: aid.mode === "questions" ? aid.answers : null,
      sai: aid.mode === "sai" ? (report && report.sai) || estimateSAI(aid.answers || {}) : null,
    };
  }

  async function runReport(includeThird = false) {
    setErr(null);
    setStep("loading");
    const input = buildInput(includeThird);
    if (window.captureLead) window.captureLead({
      lead_type: "funnel",
      home_state: input.state,
      schools: input.schools.map((s) => ({ name: s.name, program: s.program })),
      aid_range: aid.mode === "questions" ? ((aid.answers && aid.answers.income) || null) : "sai-upload",
      sai_estimate: input.sai,
      source_step: "report-run",
    });
    // guarantee a minimum loader beat so it doesn't flash
    const started = Date.now();
    let result;
    try {
      result = await generateReport(input);
    } catch (e) {
      result = fallbackReport(input);
    }
    const wait = Math.max(0, 2600 - (Date.now() - started));
    setTimeout(() => { setReport(result); setStep("report"); }, wait);
  }

  // produce the final {report, schools} for a tier (regenerating for the 3rd school)
  async function finalizeForTier(chosenTier) {
    if (chosenTier === "full3" && schools[2] && schools[2].name.trim()) {
      const input = buildInput(true);
      let res;
      try { res = await generateReport(input); } catch (e) { res = fallbackReport(input); }
      return { report: res || fallbackReport(input), schools: schools.slice(0, 3) };
    }
    return { report, schools: schools.slice(0, 2) };
  }

  function onPay(chosenTier) {
    setTier(chosenTier);
    if (window.captureLead) window.captureLead({
      lead_type: "purchase",
      tier: chosenTier,
      amount: Number((TIERS[chosenTier] || {}).price || 0),
      home_state: usState,
      schools: schools.filter((s) => s.name).map((s) => ({ name: s.name, program: s.program })),
      source_step: "paywall",
    });
    const cfg = window.B4IOU_CONFIG || {};
    const needRegen = chosenTier === "full3" && schools[2] && schools[2].name.trim();

    // ---- production: real Stripe Checkout (redirect round-trip) ----
    if (cfg.BACKEND) {
      (async () => {
        if (needRegen) setStep("loading");
        const fin = await finalizeForTier(chosenTier);
        try { localStorage.setItem("b4iou_pending", JSON.stringify({ tier: chosenTier, report: fin.report, schools: fin.schools })); } catch (e) {}
        try {
          const r = await fetch("/api/create-checkout-session", {
            method: "POST", headers: { "content-type": "application/json" },
            body: JSON.stringify({ tier: chosenTier }),
          });
          const d = await r.json();
          if (d && d.url) { window.location.href = d.url; return; }
          throw new Error(d && d.error ? d.error : "no checkout url");
        } catch (e) {
          setStep("paywall");
          toast("Checkout error: " + e.message);
        }
      })();
      return;
    }

    // ---- demo: simulate a successful unlock (no real charge) ----
    if (chosenTier === "quick") { setStep("post"); return; }
    if (needRegen) {
      setStep("loading");
      const input = buildInput(true);
      const started = Date.now();
      generateReport(input).catch(() => fallbackReport(input)).then((res) => {
        const wait = Math.max(0, 2200 - (Date.now() - started));
        setTimeout(() => { setReport(res || fallbackReport(input)); setStep("post"); }, wait);
      });
    } else {
      setStep("post");
    }
  }

  function goHome() { setStep("landing"); }

  const meta = STEP_META[step];
  const showBar = step !== "landing";

  return (
    <div className="shell" ref={scrollRef}>
      {showBar && <TopBar step={meta.n} totalSteps={TOTAL} label={meta.label} onHome={goHome} />}

      {step === "landing" && <Landing onStart={() => setStep("input")} />}

      {step === "input" && (
        <SchoolInput
          schools={schools} setSchools={setSchools}
          usState={usState} setUsState={setUsState}
          allowThird={false}
          onNext={() => setStep("aid")}
          onBack={goHome}
        />
      )}

      {step === "aid" && (
        <AidEligibility
          aid={aid} setAid={setAid}
          onNext={() => runReport(false)}
          onBack={() => setStep("input")}
        />
      )}

      {step === "loading" && <Loader />}

      {step === "report" && report && (
        <FreeReport
          report={report} schools={schools}
          onUpgrade={() => setStep("paywall")}
          onBack={() => setStep("input")}
        />
      )}

      {step === "paywall" && (
        <Paywall
          schools={schools} setSchools={setSchools}
          onPay={onPay}
          onBack={() => setStep("report")}
        />
      )}

      {step === "post" && report && (
        <PostPayment
          report={report} schools={schools} tier={tier}
          onDownload={() => downloadPDF(report, schools, tier)}
          onUpgrade={() => setStep("paywall")}
          toast={toast}
        />
      )}

      <Toast msg={toastMsg} />
      {previewHTML && <ReportPreview html={previewHTML} onClose={() => setPreviewHTML(null)} toast={toast} />}
    </div>
  );
}

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