/* Funding Hub · Grant Pipeline · Applications - the funding lifecycle.
   All grounded in window.OPS + window.DATA. Exports the three views.    */

/* ============================ FUNDING HUB ============================ */
function FundingHub({ onOpen }) {
  const D = window.DATA, O = window.OPS, fmt = D.fmtMoney;
  const outstanding = O.committed - O.paidOut;
  const available = O.reserves - outstanding;
  const upcoming = O.payments.filter((p) => p.status !== "Paid").sort((a, b) => new Date(a.due) - new Date(b.due));
  const grants = D.orgs.filter((o) => o.funded && o.funding).sort((a, b) => b.funding.awarded - a.funding.awarded);
  const paidFor = (oid) => O.payments.filter((p) => p.org === oid && p.status === "Paid").reduce((s, p) => s + p.amount, 0);
  const statusMeta = { "Paid": { c: "var(--good)", bg: "var(--good-bg)" }, "Due soon": { c: "var(--warn)", bg: "var(--warn-bg)" }, "Scheduled": { c: "var(--text-muted)", bg: "var(--surface-2)" } };

  return (
    <ModulePage icon="funding" eyebrow="Operations" title="Funding Hub"
      subtitle="Budgets, awards, payment schedules and reserves - every pound from commitment to disbursement."
      actions={<React.Fragment>
        <button className="btn"><Icon name="receipt" size={15} /> Export ledger</button>
        <button className="btn btn-primary"><Icon name="plus" size={15} /> New award</button>
      </React.Fragment>}>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 18, marginBottom: 20 }}>
        <StatTile icon="funding" label="Total committed" value={fmt(O.committed)} sub={`${grants.length} active grants`} accent />
        <StatTile icon="check" label="Paid to date" value={fmt(O.paidOut)} sub={`${O.payments.filter((p) => p.status === "Paid").length} tranches released`} color="var(--good)" />
        <StatTile icon="clock" label="Outstanding" value={fmt(outstanding)} sub="committed, not yet paid" color="var(--warn)" />
        <StatTile icon="layers" label="Reserves available" value={fmt(available)} sub={`of ${fmt(O.reserves)} fund`} />
      </div>

      <div style={{ marginBottom: 20 }}>
        <AINote title="Reserves outlook">
          At the current disbursement pace you'll hold <strong>{fmt(available)}</strong> uncommitted by Q3. NeuroAI suggests earmarking
          <strong> {fmt(Math.round(available * 0.4))}</strong> toward the {D.orgs.filter((o) => o.priority === "need").length} high-need prospects flagged in prioritisation.
        </AINote>
      </div>

      <div style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr", gap: 20, alignItems: "start" }}>
        <ModulePanel title="Grant ledger" icon="building" right={<span className="badge mono">{grants.length}</span>}>
          <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
            {grants.map((o) => {
              const paid = paidFor(o.id), total = o.funding.awarded, pct = Math.round((paid / total) * 100);
              return (
                <button key={o.id} className="focusable" onClick={() => onOpen(o.id)} style={{ display: "block", width: "100%", textAlign: "left", padding: "12px 13px", border: "1px solid var(--border)", borderRadius: 12, background: "var(--surface-2)", cursor: "pointer" }}>
                  <div style={{ display: "flex", alignItems: "center", gap: 9, marginBottom: 8 }}>
                    <span style={{ width: 8, height: 8, borderRadius: 999, background: domainColor(o.domain), flex: "none" }} />
                    <span style={{ fontSize: 13.5, fontWeight: 600, flex: 1, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{o.name}</span>
                    <span className="mono" style={{ fontSize: 12.5, color: "var(--text-muted)" }}>{fmt(paid)} / {fmt(total)}</span>
                  </div>
                  <div style={{ height: 7, borderRadius: 5, background: "var(--surface-3)", overflow: "hidden" }}>
                    <div style={{ width: pct + "%", height: "100%", background: domainColor(o.domain), borderRadius: 5 }} />
                  </div>
                </button>
              );
            })}
          </div>
        </ModulePanel>

        <ModulePanel title="Payment schedule" icon="calendar" right={<span className="badge mono">{upcoming.length} due</span>}>
          <div style={{ display: "flex", flexDirection: "column", gap: 9 }}>
            {upcoming.slice(0, 8).map((p) => {
              const sm = statusMeta[p.status] || statusMeta.Scheduled;
              return (
                <button key={p.id} className="focusable" onClick={() => onOpen(p.org)} style={{ display: "flex", alignItems: "center", gap: 11, padding: "10px 12px", border: "1px solid var(--border)", borderRadius: 10, background: "var(--surface-2)", cursor: "pointer", textAlign: "left" }}>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 13, fontWeight: 600, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{D.byId[p.org].name}</div>
                    <div style={{ fontSize: 11.5, color: "var(--text-muted)" }}>{p.label} · {relDay(p.due)}</div>
                  </div>
                  <span className="mono" style={{ fontSize: 13, fontWeight: 600 }}>{fmt(p.amount)}</span>
                  <span className="badge" style={{ flex: "none", background: sm.bg, color: sm.c, borderColor: "transparent" }}>{p.status}</span>
                </button>
              );
            })}
          </div>
        </ModulePanel>
      </div>
    </ModulePage>
  );
}

/* ============================ GRANT PIPELINE ============================ */
function GrantPipeline({ onOpen }) {
  const D = window.DATA, fmt = D.fmtMoney;
  const stageOf = (o) => {
    if (o.relationship === "Prospect") {
      const prop = D.projectsByOrg(o.id).some((p) => p.type === "Proposal" && p.status === "In review");
      return prop ? "In review" : "Prospect";
    }
    if (D.projectsByOrg(o.id).some((p) => p.status === "Approved")) return "Approved";
    if (o.funded) return "Active";
    return "Supporter";
  };
  const COLS = [
    { id: "Prospect", label: "Prospect", c: "var(--text-muted)" },
    { id: "In review", label: "In review", c: "var(--warn)" },
    { id: "Approved", label: "Approved", c: "var(--info)" },
    { id: "Active", label: "Active grant", c: "var(--good)" },
    { id: "Supporter", label: "Supporter", c: "var(--accent)" },
  ];
  const byStage = {}; COLS.forEach((c) => (byStage[c.id] = []));
  D.orgs.forEach((o) => byStage[stageOf(o)].push(o));
  const valueOf = (o) => (o.funding ? (o.funded ? o.funding.awarded : o.funding.ask) : 0);
  const conv = Math.round((byStage["Active"].length / (byStage["Prospect"].length + byStage["In review"].length + byStage["Approved"].length + byStage["Active"].length)) * 100);

  return (
    <ModulePage icon="pipeline" eyebrow="Operations" title="Grant Pipeline" maxWidth={1500}
      subtitle="Every opportunity from first contact to active grant. Click a card to open the record."
      actions={<button className="btn btn-primary"><Icon name="plus" size={15} /> Add opportunity</button>}>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 18, marginBottom: 20 }}>
        <StatTile icon="pipeline" label="In pipeline" value={byStage["Prospect"].length + byStage["In review"].length + byStage["Approved"].length} sub="opportunities being worked" accent />
        <StatTile icon="target" label="Conversion to active" value={conv + "%"} sub="prospect → funded" color="var(--good)" />
        <StatTile icon="funding" label="Pipeline value" value={fmt(D.orgs.filter((o) => stageOf(o) === "Prospect" || stageOf(o) === "In review").reduce((s, o) => s + valueOf(o), 0))} sub="open asks" color="var(--warn)" />
      </div>

      <div style={{ marginBottom: 20 }}>
        <AINote title="Where things stall" onAction={() => onOpen(byStage["In review"][0] && byStage["In review"][0].id)} actionLabel="Open top prospect">
          {byStage["In review"].length} opportunities are stuck in review. {byStage["In review"][0] ? byStage["In review"][0].name : "Your top prospect"} has the strongest fit score - moving it to panel this cycle would lift conversion.
        </AINote>
      </div>

      <div style={{ display: "grid", gridTemplateColumns: "repeat(5, minmax(0,1fr))", gap: 14, alignItems: "start" }}>
        {COLS.map((col) => (
          <div key={col.id} style={{ background: "var(--surface-2)", border: "1px solid var(--border)", borderRadius: 14, padding: 12, minHeight: 200 }}>
            <div style={{ display: "flex", alignItems: "center", gap: 7, marginBottom: 12, padding: "0 2px" }}>
              <span style={{ width: 8, height: 8, borderRadius: 999, background: col.c, flex: "none" }} />
              <span style={{ fontSize: 12.5, fontWeight: 650 }}>{col.label}</span>
              <span className="badge mono" style={{ marginLeft: "auto" }}>{byStage[col.id].length}</span>
            </div>
            <div style={{ display: "flex", flexDirection: "column", gap: 9 }}>
              {byStage[col.id].map((o) => (
                <button key={o.id} className="focusable" onClick={() => onOpen(o.id)} style={{ display: "block", width: "100%", textAlign: "left", background: "var(--surface)", border: "1px solid var(--border)", borderTop: `2px solid ${col.c}`, borderRadius: 10, padding: "10px 11px", cursor: "pointer", boxShadow: "var(--shadow-sm)" }}>
                  <div style={{ fontSize: 12.5, fontWeight: 600, lineHeight: 1.25, marginBottom: 6 }}>{o.name}</div>
                  <div style={{ display: "flex", alignItems: "center", gap: 6, marginBottom: 8 }}>
                    <span style={{ width: 6, height: 6, borderRadius: 999, background: domainColor(o.domain) }} />
                    <span style={{ fontSize: 10.5, color: "var(--text-muted)" }}>{(D.domains.find((d) => d.id === o.domain) || {}).label}</span>
                  </div>
                  <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
                    <span className="mono" style={{ fontSize: 11.5, color: "var(--text-muted)" }}>{valueOf(o) ? fmt(valueOf(o)) : "-"}</span>
                    {o.account && <Avatar name={D.byId[o.account].name} size={20} accent />}
                  </div>
                </button>
              ))}
              {byStage[col.id].length === 0 && <div style={{ fontSize: 12, color: "var(--text-faint)", textAlign: "center", padding: "12px 0" }}>Empty</div>}
            </div>
          </div>
        ))}
      </div>
    </ModulePage>
  );
}

/* ============================ APPLICATIONS ============================ */
function ApplicationsView({ onOpen }) {
  const D = window.DATA, O = window.OPS, fmt = D.fmtMoney;
  const [stage, setStage] = React.useState("all");
  const apps = O.applications.filter((a) => stage === "all" || a.stage === stage).sort((a, b) => b.score - a.score);
  const stageMeta = { "New": "var(--text-muted)", "Screening": "var(--warn)", "Panel review": "var(--info)", "Shortlisted": "var(--accent)", "Decision": "var(--good)" };
  const top = [...O.applications].sort((a, b) => b.score - a.score)[0];

  return (
    <ModulePage icon="inbox" eyebrow="Operations" title="Applications" maxWidth={1280}
      subtitle="Branded intake feeds straight into the ecosystem - score, shortlist and route every submission."
      actions={<React.Fragment>
        <button className="btn"><Icon name="external" size={15} /> View public form</button>
        <button className="btn btn-primary"><Icon name="plus" size={15} /> New round</button>
      </React.Fragment>}>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 18, marginBottom: 20 }}>
        <StatTile icon="inbox" label="Open applications" value={O.applications.length} sub="this funding round" accent />
        <StatTile icon="target" label="Strong fit" value={O.applications.filter((a) => a.fit === "Strong").length} sub="score ≥ 75" color="var(--good)" />
        <StatTile icon="funding" label="Requested total" value={fmt(O.applications.reduce((s, a) => s + a.ask, 0))} sub="across all applicants" />
        <StatTile icon="users" label="Awaiting panel" value={O.applications.filter((a) => a.stage === "Panel review" || a.stage === "Screening").length} sub="need a decision" color="var(--warn)" />
      </div>

      <div style={{ marginBottom: 20 }}>
        <AINote title="Shortlist suggestion" onAction={() => top && onOpen(top.org)} actionLabel={top ? `Open ${D.byId[top.org].name}` : "Review"}>
          {top ? <span><strong>{D.byId[top.org].name}</strong> scores {top.score}/100 on fit and sits in an under-funded domain - a strong candidate to fast-track to panel.</span> : "No applications to assess."}
        </AINote>
      </div>

      <div style={{ display: "flex", gap: 6, marginBottom: 14, flexWrap: "wrap" }}>
        {["all", ...O.STAGE].map((s) => {
          const on = stage === s;
          return <button key={s} className="tap focusable" onClick={() => setStage(s)}
            style={{ font: "inherit", fontSize: 12, fontWeight: 550, cursor: "pointer", padding: "5px 11px", borderRadius: 999, border: "1px solid " + (on ? "transparent" : "var(--border)"), background: on ? "var(--accent)" : "var(--surface-2)", color: on ? "var(--accent-contrast)" : "var(--text-muted)" }}>{s === "all" ? "All stages" : s}</button>;
        })}
      </div>

      <div className="card" style={{ overflow: "hidden", padding: 0 }}>
        {apps.map((a, i) => {
          const o = D.byId[a.org];
          return (
            <button key={a.id} className="focusable" onClick={() => onOpen(a.org)} style={{ display: "flex", alignItems: "center", gap: 14, width: "100%", textAlign: "left", padding: "14px 18px", border: "none", borderBottom: i < apps.length - 1 ? "1px solid var(--border)" : "none", background: "none", cursor: "pointer" }}>
              <div style={{ width: 44, flex: "none", textAlign: "center" }}>
                <div className="mono" style={{ fontSize: 18, fontWeight: 700, color: a.score >= 75 ? "var(--good)" : a.score >= 60 ? "var(--accent)" : "var(--text-muted)" }}>{a.score}</div>
                <div style={{ fontSize: 9.5, color: "var(--text-faint)" }}>fit</div>
              </div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 14, fontWeight: 600 }}>{o.name}</div>
                <div style={{ fontSize: 12, color: "var(--text-muted)", marginTop: 2 }}>
                  <span style={{ display: "inline-flex", alignItems: "center", gap: 5 }}><span style={{ width: 6, height: 6, borderRadius: 999, background: domainColor(o.domain) }} />{(D.domains.find((d) => d.id === o.domain) || {}).label}</span>
                  {" · "}received {relDay(a.received)}{a.contact ? " · " + D.byId[a.contact].name : ""}
                </div>
              </div>
              <span className="mono" style={{ fontSize: 13.5, fontWeight: 600 }}>{fmt(a.ask)}</span>
              <span className="badge" style={{ flex: "none", width: 92, justifyContent: "center", background: "var(--surface-2)", color: stageMeta[a.stage], borderColor: "transparent", fontWeight: 600 }}>{a.stage}</span>
              <Icon name="chevronRight" size={16} style={{ color: "var(--text-faint)", flex: "none" }} />
            </button>
          );
        })}
        {apps.length === 0 && <div style={{ padding: 28, textAlign: "center", fontSize: 13.5, color: "var(--text-faint)" }}>No applications in this stage.</div>}
      </div>
    </ModulePage>
  );
}

window.FundingHub = FundingHub;
window.GrantPipeline = GrantPipeline;
window.ApplicationsView = ApplicationsView;
