/* stage2/Stage2Wizard.jsx — the underwriting wizard shell.
   Loads the application by id, drives the 8 STAGE2_STEPS, saves every
   field as you type (debounced), persists child arrays on blur/step-change,
   and submits at the end. DEMO MODE when window.portalSupabase is null.
   Globals: React, Portal, Icon, CenterLoad, STAGE2_STEPS + the Step* comps. */
/* eslint-disable */
const { useState: useW2, useEffect: useWE2, useRef: useWR2 } = React;

/* ---------- demo seed (no Supabase) ---------- */
function s2DemoApplication(applicationId) {
  return {
    id: applicationId || "demo-application",
    status: "stage2_in_progress",
    applicant_full_name: "Sample Applicant",
    entity_legal_name: "",
    entity_structure: "",
    entity_state: Portal.property.state || "CO",
    certify_accuracy: false,
  };
}
function s2SeedReferences() {
  return [
    { ref_kind: "landlord", company: "", contact_name: "", phone: "", email: "", notes: "" },
    { ref_kind: "vendor", company: "", contact_name: "", phone: "", email: "", notes: "" },
    { ref_kind: "bank", company: "", contact_name: "", phone: "", email: "", notes: "" },
  ];
}

/* fields we own on the applications row (everything we may upsert) */
const S2_APP_FIELDS = [
  "entity_legal_name", "entity_dba", "entity_structure", "entity_state", "ein",
  "year_founded", "naics_code", "fiscal_year_end", "years_in_business",
  "years_at_address", "ft_employees", "pt_employees",
  "has_changed_names", "name_change_explain",
  "annual_revenue_range", "annual_revenue_proj_range", "gross_margin_range",
  "cash_reserves_range", "monthly_rent_budget_range", "buildout_cost_range",
  "buildout_finance_method", "hours_of_operation", "business_plan_summary",
  "disclosure_bankruptcy_y", "disclosure_bankruptcy_explain",
  "disclosure_foreclosure_y", "disclosure_foreclosure_explain",
  "disclosure_eviction_y", "disclosure_eviction_explain",
  "disclosure_assignment_y", "disclosure_assignment_explain",
  "certify_accuracy",
];
/* int columns — coerce before persisting */
const S2_INT_FIELDS = ["year_founded", "years_in_business", "years_at_address", "ft_employees", "pt_employees", "naics_code"];

function s2CoerceForDb(data) {
  var out = {};
  S2_APP_FIELDS.forEach(function (k) {
    var v = data[k];
    if (v === undefined) return;
    if (S2_INT_FIELDS.indexOf(k) !== -1) {
      if (v === "" || v == null) { out[k] = null; return; }
      var n = parseInt(String(v).replace(/\D/g, ""), 10);
      out[k] = isNaN(n) ? null : n;
    } else if (v === "") {
      out[k] = null;
    } else {
      out[k] = v;
    }
  });
  return out;
}

function Stage2Wizard({ applicationId }) {
  const sb = window.portalSupabase;
  const demo = !sb;

  const [loading, setLoading] = useW2(true);
  const [loadError, setLoadError] = useW2(null);
  const [stepIndex, setStepIndex] = useW2(0);
  const [data, setData] = useW2({});
  const [owners, setOwners] = useW2([]);
  const [locations, setLocations] = useW2([]);
  const [references, setReferences] = useW2(s2SeedReferences());
  const [touched, setTouched] = useW2({});
  const [errors, setErrors] = useW2({});
  const [saveState, setSaveState] = useW2("idle"); // idle | saving | saved
  const [toast, setToast] = useW2(null);
  const [submitting, setSubmitting] = useW2(false);
  const [submitted, setSubmitted] = useW2(false);

  const saveTimer = useWR2(null);
  const mounted = useWR2(true);

  /* ---------- load ---------- */
  useWE2(function () {
    mounted.current = true;
    (async function () {
      if (demo) {
        const a = s2DemoApplication(applicationId);
        setData(a);
        setOwners([]);
        setLocations([]);
        setReferences(s2SeedReferences());
        window.__portalAppId = a.id;
        console.warn("[portal] Stage 2 DEMO MODE — no Supabase; state held in React.");
        setLoading(false);
        return;
      }
      try {
        const sess = await sb.auth.getSession();
        if (!sess || !sess.data || !sess.data.session) {
          setLoadError("expired");
          setLoading(false);
          return;
        }
        const { data: app, error } = await sb
          .from("applications").select("*").eq("id", applicationId).maybeSingle();
        if (error) throw error;
        if (!app) { setLoadError("expired"); setLoading(false); return; }

        window.__portalAppId = app.id;
        window.__portalUserId = app.applicant_id;

        // pull a friendly first name for the welcome line
        try {
          const { data: appl } = await sb.from("applicants").select("full_name")
            .eq("id", app.applicant_id).maybeSingle();
          if (appl && appl.full_name) app.applicant_full_name = appl.full_name;
        } catch (e) {}

        setData(app);

        const [ow, lo, re] = await Promise.all([
          sb.from("application_owners").select("*").eq("application_id", applicationId).order("sort"),
          sb.from("application_locations").select("*").eq("application_id", applicationId).order("sort"),
          sb.from("application_references").select("*").eq("application_id", applicationId).order("sort"),
        ]);
        setOwners((ow.data || []));
        setLocations((lo.data || []));
        setReferences((re.data && re.data.length) ? re.data : s2SeedReferences());

        // advance status to in-progress if still earlier in the funnel
        const earlier = ["lead", "qualified"].indexOf(app.status) !== -1;
        if (earlier || !app.stage2_started_at) {
          const patch = { status: "stage2_in_progress" };
          if (!app.stage2_started_at) patch.stage2_started_at = new Date().toISOString();
          sb.from("applications").update(patch).eq("id", applicationId).then(function () {});
        }

        // resume at the saved step if present
        if (app.current_step) {
          const idx = STAGE2_STEPS.findIndex(function (s) { return s.key === app.current_step; });
          if (idx > 0) setStepIndex(idx);
        }
        setLoading(false);
      } catch (err) {
        console.error("[portal] Stage 2 load failed", err);
        setLoadError("expired");
        setLoading(false);
      }
    })();
    return function () { mounted.current = false; };
  }, [applicationId]);

  /* step_view analytics */
  useWE2(function () {
    if (loading || loadError || submitted) return;
    const key = STAGE2_STEPS[stepIndex] && STAGE2_STEPS[stepIndex].key;
    window.portalAnalytics && window.portalAnalytics.log("step_view", { step: key, application_id: applicationId });
  }, [stepIndex, loading, loadError, submitted]);

  /* ---------- debounced field save ---------- */
  useWE2(function () {
    if (loading || loadError || submitted) return;
    if (saveTimer.current) clearTimeout(saveTimer.current);
    setSaveState("saving");
    saveTimer.current = setTimeout(function () { flushSave(); }, 700);
    return function () { if (saveTimer.current) clearTimeout(saveTimer.current); };
  }, [data]);

  function flushSave() {
    const key = STAGE2_STEPS[stepIndex] && STAGE2_STEPS[stepIndex].key;
    if (demo || !sb) {
      window.portalAnalytics && window.portalAnalytics.log("field_save", { step: key, application_id: applicationId, metadata: { demo: true } });
      setSaveState("saved");
      return;
    }
    const patch = s2CoerceForDb(data);
    patch.last_field_saved_at = new Date().toISOString();
    patch.current_step = key;
    patch.wizard_state = { data: data, owners: owners, locations: locations, references: references, stepIndex: stepIndex };
    sb.from("applications").update(patch).eq("id", applicationId).then(function (r) {
      if (!mounted.current) return;
      if (r.error) { console.warn("[portal] field save error", r.error.message); setSaveState("idle"); }
      else setSaveState("saved");
    });
  }

  /* ---------- persist child arrays (delete + reinsert) ---------- */
  async function persistChildren() {
    if (demo || !sb) return;
    try {
      // owners
      await sb.from("application_owners").delete().eq("application_id", applicationId);
      const orows = (owners || [])
        .filter(function (o) { return (o.full_name || "").trim(); })
        .map(function (o, i) {
          return {
            application_id: applicationId, full_name: o.full_name, title: o.title || null,
            ownership_pct: o.ownership_pct === "" || o.ownership_pct == null ? null : Number(String(o.ownership_pct).replace(/[^\d.]/g, "")) || null,
            email: o.email || null, phone: (o.phone || "").replace(/\D/g, "") || null,
            dob: o.dob || null, personal_guaranty: !!o.personal_guaranty, sort: i,
          };
        });
      if (orows.length) await sb.from("application_owners").insert(orows);

      // locations
      await sb.from("application_locations").delete().eq("application_id", applicationId);
      const lrows = (locations || [])
        .filter(function (l) { return (l.address || "").trim(); })
        .map(function (l, i) {
          return {
            application_id: applicationId, address: l.address,
            sf: l.sf === "" || l.sf == null ? null : (parseInt(String(l.sf).replace(/\D/g, ""), 10) || null),
            year_opened: l.year_opened === "" || l.year_opened == null ? null : (parseInt(String(l.year_opened).replace(/\D/g, ""), 10) || null),
            current_rent: l.current_rent || null, lease_type: l.lease_type || null,
            lease_expiration: l.lease_expiration || null, annual_sales_range: l.annual_sales_range || null, sort: i,
          };
        });
      if (lrows.length) await sb.from("application_locations").insert(lrows);

      // references
      await sb.from("application_references").delete().eq("application_id", applicationId);
      const rrows = (references || [])
        .filter(function (r) { return (r.company || "").trim() || (r.contact_name || "").trim(); })
        .map(function (r, i) {
          return {
            application_id: applicationId, ref_kind: r.ref_kind,
            company: r.company || null, contact_name: r.contact_name || null,
            phone: (r.phone || "").replace(/\D/g, "") || null, email: r.email || null,
            notes: r.notes || null, sort: i,
          };
        });
      if (rrows.length) await sb.from("application_references").insert(rrows);
    } catch (e) {
      console.warn("[portal] child persist error", e.message);
    }
  }

  /* ---------- field handlers ---------- */
  function setField(name, val) {
    setData(function (d) { return Object.assign({}, d, { [name]: val }); });
  }
  function onBlur(name) {
    setTouched(function (t) { return Object.assign({}, t, { [name]: true }); });
    window.portalAnalytics && window.portalAnalytics.log("field_blur", { step: STAGE2_STEPS[stepIndex].key, field: name, application_id: applicationId });
  }

  /* ---------- validation ---------- */
  function validateStep(i) {
    const step = STAGE2_STEPS[i];
    const ne = {}; let first = null;
    (step.fields || []).forEach(function (f) {
      let err = null;
      if (f === "ein") err = Portal.validators.ein(data[f]);
      else err = Portal.validators.required(data[f]);
      if (err) { ne[f] = err; first = first || f; }
    });
    // Step C: at least one owner, and every owner row needs the required
    // fields (everything except Title).
    if (step.key === "C") {
      const list = owners || [];
      if (!list.some(function (o) { return (o.full_name || "").trim(); })) {
        ne.__owners = "Add at least one owner."; first = first || "owner_full_name_0";
      } else {
        const reqCols = [
          ["full_name", "owner_full_name_"], ["ownership_pct", "owner_pct_"],
          ["email", "owner_email_"], ["phone", "owner_phone_"], ["dob", "owner_dob_"],
        ];
        for (let oi = 0; oi < list.length && !first; oi++) {
          for (let c = 0; c < reqCols.length; c++) {
            const v = list[oi][reqCols[c][0]];
            if (String(v == null ? "" : v).trim() === "") { first = reqCols[c][1] + oi; break; }
          }
        }
      }
    }
    // Step H: certify gate is handled at submit; still mark explains optional.
    setErrors(function (e) { return Object.assign({}, e, ne); });
    const t = {}; (step.fields || []).forEach(function (f) { t[f] = true; });
    setTouched(function (p) { return Object.assign({}, p, t); });
    return { ok: !first, first: first };
  }

  function scrollToError(name) {
    setTimeout(function () {
      const el = document.querySelector('[name="' + name + '"]');
      if (el && el.scrollIntoView) { el.scrollIntoView({ behavior: "smooth", block: "center" }); if (el.focus) el.focus(); }
      else window.scrollTo({ top: 0, behavior: "smooth" });
    }, 30);
  }

  const lastStep = stepIndex === STAGE2_STEPS.length - 1;

  function goBack() {
    persistChildren();
    setStepIndex(function (i) { return Math.max(0, i - 1); });
    window.scrollTo({ top: 0, behavior: "smooth" });
  }

  async function goNext() {
    const { ok, first } = validateStep(stepIndex);
    if (!ok) {
      window.portalAnalytics && window.portalAnalytics.log("step_error", { step: STAGE2_STEPS[stepIndex].key, field: first, application_id: applicationId });
      scrollToError(first);
      return;
    }
    await persistChildren();
    flushSave();
    window.portalAnalytics && window.portalAnalytics.log("step_complete", { step: STAGE2_STEPS[stepIndex].key, application_id: applicationId });

    if (lastStep) { handleSubmit(); return; }
    setStepIndex(function (i) { return Math.min(STAGE2_STEPS.length - 1, i + 1); });
    window.scrollTo({ top: 0, behavior: "smooth" });
  }

  function onSigned() {
    setField("__signed", true);
    window.portalAnalytics && window.portalAnalytics.log("docusign_signed", { step: "H", application_id: applicationId });
  }

  async function handleSubmit() {
    if (!data.certify_accuracy) {
      setTouched(function (t) { return Object.assign({}, t, { certify_accuracy: true }); });
      scrollToError("certify_accuracy");
      return;
    }
    setSubmitting(true);
    try {
      if (!demo && sb) {
        await persistChildren();
        await sb.from("applications").update({
          status: "submitted",
          stage2_submitted_at: new Date().toISOString(),
          current_step: "H",
        }).eq("id", applicationId);
        try { await sb.functions.invoke("send-stage2-confirmation", { body: { application_id: applicationId } }); }
        catch (e) { console.warn("[portal] stage2 confirmation edge fn:", e.message); }
      } else {
        await new Promise(function (r) { setTimeout(r, 600); });
        console.warn("[portal] DEMO — Stage 2 submit simulated", { data: data, owners: owners, locations: locations, references: references });
      }
      window.portalAnalytics && window.portalAnalytics.log("submission", { step: "H", application_id: applicationId });
      setSubmitted(true);
      window.scrollTo({ top: 0, behavior: "smooth" });
    } catch (err) {
      console.error("[portal] Stage 2 submit failed", err);
      setToast("Something went wrong submitting. Your work is saved — try again, or call " + ((Portal.brand.contact && Portal.brand.contact.phone) || "us") + ".");
    } finally {
      setSubmitting(false);
    }
  }

  function saveAndLater() {
    flushSave();
    persistChildren();
    setToast(Portal.c("stage2.saveResume", "Saved") + " — we emailed you the link.");
    setTimeout(function () { if (mounted.current) setToast(null); }, 4000);
  }

  /* ---------- render: loading / error / success ---------- */
  if (loading) return <CenterLoad label="Loading your application…" />;

  if (loadError) {
    return (
      <div className="success-stage">
        <div className="wrap-narrow">
          <div className="success-mark"><Icon name="clock" size={28} /></div>
          <h1>This link has expired.</h1>
          <p className="s-body">
            For your security, application links don't stay active forever. Reply to your
            email and we'll send you a fresh one — your saved answers will be right where
            you left them.
          </p>
          <p className="s-sign">— {Portal.brand.contact && Portal.brand.contact.name}, {Portal.brand.legalName || Portal.brand.name}</p>
        </div>
      </div>
    );
  }

  if (submitted) {
    const fn = (data.applicant_full_name || "").trim().split(/\s+/)[0] || "there";
    return (
      <div className="success-stage">
        <div className="wrap-narrow">
          <div className="success-mark"><Icon name="check" size={30} /></div>
          <h1>Thank you, {fn}.</h1>
          <p className="s-body">
            Your application is in our hands. We'll review the details and get back to you
            within two business days. If we need anything else, we'll reach out — but you're
            done for now.
          </p>
          <p className="s-sign">— {Portal.brand.contact && Portal.brand.contact.name}, {Portal.brand.legalName || Portal.brand.name}</p>
          <div style={{ marginTop: 40 }}>
            <a className="btn ghost sm" href={Portal.brand.propertyUrl || "#/"}>
              Back to {Portal.brand.name}
            </a>
          </div>
        </div>
      </div>
    );
  }

  /* ---------- render: the wizard ---------- */
  const step = STAGE2_STEPS[stepIndex];
  const StepComp = step.Comp;
  const pct = Math.round(((stepIndex + 1) / STAGE2_STEPS.length) * 100);

  return (
    <div className="wizard">
      <div className="progress-rail">
        <div className="pr-inner">
          <div className="pr-meta">
            <span>Step {stepIndex + 1} of {STAGE2_STEPS.length} — {pct}% complete</span>
            <button type="button" className={Portal.cx("pr-save", saveState === "saved" && "saved")}
              onClick={saveAndLater}>
              {saveState === "saving" ? "Saving…" : saveState === "saved" ? "Saved" : Portal.c("stage2.saveResume", "Save & continue later")}
            </button>
          </div>
          <div className="pr-bar"><div className="pr-fill" style={{ width: pct + "%" }} /></div>
        </div>
      </div>

      <StepComp
        data={data}
        setField={setField}
        errors={errors}
        touched={touched}
        onBlur={onBlur}
        owners={owners}
        setOwners={setOwners}
        locations={locations}
        setLocations={setLocations}
        references={references}
        setReferences={setReferences}
        applicationId={applicationId}
        application={data}
        onSigned={onSigned}
      />

      {toast && <div className="why-note" style={{ margin: "0 auto", maxWidth: 640 }}>{toast}</div>}

      <div className="step-nav">
        <div className="sn-inner">
          <button type="button" className="btn ghost"
            onClick={goBack} disabled={stepIndex === 0 || submitting}>
            <span className="arr" style={{ transform: "rotate(180deg)" }}><Icon name="arrow" size={15} /></span>
            Back
          </button>
          <button type="button" className="btn"
            onClick={goNext}
            disabled={submitting || (lastStep && !data.certify_accuracy)}>
            {submitting ? "Submitting…" : lastStep ? Portal.c("stage2.submit", "Submit application") : "Continue"}
            {!submitting && <span className="arr"><Icon name="arrow" size={15} /></span>}
          </button>
        </div>
      </div>
    </div>
  );
}
