/* SkyOps — Dashboard widgets: Work orders (Operations) and Contracts & costs (Financial). */

function WoDashCard({ go, setActiveSite }) {
  const wos = window.useWOs ? window.useWOs() : (window.woStore?.list || []);
  const T = window.SKY_TODAY;
  const open = wos.filter(w => !["done", "verified"].includes(w.status));
  const overdue = open.filter(w => w.due && w.due < T);
  const p1 = open.filter(w => w.prio === "P1");
  const toVerify = wos.filter(w => w.status === "done");
  const rar = open.reduce((a, w) => a + (+w.rar || 0), 0);
  const by = ["open", "assigned", "in_progress", "done"].map(s => [s, wos.filter(w => w.status === s).length]);
  const tot = Math.max(1, by.reduce((a, [, n]) => a + n, 0));
  const urgent = [...open].sort((a, b) => (a.prio > b.prio ? 1 : a.prio < b.prio ? -1 : 0) || String(a.due).localeCompare(String(b.due))).slice(0, 5);
  const L = { open: "Open", assigned: "Assigned", in_progress: "In progress", done: "To verify" };
  const C = { open: "var(--fg-muted)", assigned: "var(--accent-primary)", in_progress: "var(--sev-medium)", done: "var(--sev-low)" };
  return <div className="card dw">
    <div className="card-hd">Work orders<span className="sub">{open.length} open · {window.skyFmt.money(rar, { compact: true })}/yr at risk</span><div className="actions"><button className="btn btn-ghost btn-xs" onClick={() => go("workorders")}>All<Icon name="arrow_right" size={11}/></button></div></div>
    <div className="dw-kpis">
      {[["Overdue", overdue.length, overdue.length ? "crit" : ""], ["P1 open", p1.length, p1.length ? "warn" : ""], ["To verify", toVerify.length, ""]].map(([l, n, t]) => <button key={l} className={`dw-k ${t}`} onClick={() => go("workorders")}><b>{n}</b><span>{l}</span></button>)}
    </div>
    <div className="dw-stack" title={by.map(([s, n]) => `${L[s]}: ${n}`).join(" · ")}>{by.map(([s, n]) => n ? <i key={s} style={{ width: n / tot * 100 + "%", background: C[s] }}/> : null)}</div>
    <div className="dw-lg">{by.map(([s, n]) => <span key={s}><i style={{ background: C[s] }}/>{L[s]} <b className="mono">{n}</b></span>)}</div>
    <div className="dw-list">{urgent.map(w => { const s = (window.SITES || []).find(x => x.id === w.siteId); const od = w.due && w.due < T; return (
      <button key={w.id} className="dw-row" onClick={() => { setActiveSite && setActiveSite(w.siteId); go("workorders"); }}>
        <span className={`dw-prio dw-prio-${w.prio}`}>{w.prio}</span>
        <span className="dw-row-m"><b>{w.title}</b><em>{w.id} · {s?.name} · {(w.assignee || "").split(" · ")[0].split(" (")[0]}</em></span>
        <span className={`dw-due ${od ? "crit" : ""}`}>{od ? "Overdue" : "Due"}<b>{window.skyFmt.date(w.due)}</b></span></button>); })}
      {!urgent.length && <div className="tbl-empty">No open work orders.</div>}</div>
  </div>;
}

function CostDashCard({ go }) {
  const v = window.useCM ? window.useCM() : null;
  if (!v) return null;
  const type = window.tnCur ? window.tnCur().type : "owner";
  const T = window.SKY_TODAY, Y = window.cmRange("year");
  if (type === "provider") {
    const jobs = window.cmJobs(v);
    const inv = jobs.filter(j => j.invoice && window.cmIn(j.issued, Y));
    const rev = inv.reduce((a, j) => a + j.net, 0), cost = inv.reduce((a, j) => a + j.cost, 0);
    const ar = jobs.filter(j => j.invoice && j.status !== "paid").reduce((a, j) => a + j.net, 0);
    const arr = v.contracts.filter(c => ["active", "signed"].includes(c.status) && c.end >= T).reduce((a, c) => a + c.price * c.cycles, 0);
    return <div className="card dw dw-cost">
      <div className="card-hd">Commercial · year to date<div className="actions"><button className="btn btn-ghost btn-xs" onClick={() => go("commercial")}>Open<Icon name="arrow_right" size={11}/></button></div></div>
      <div className="dw-cost-g">{[["Invoiced", window.cmEur(rev)], ["Gross margin", rev ? ((rev - cost) / rev * 100).toFixed(1) + "%" : "—"], ["Receivables", window.cmEur(ar)], ["Contracted / yr", window.cmEur(arr)]].map(([l, x]) => <div key={l}><span>{l}</span><b>{x}</b></div>)}</div>
    </div>;
  }
  const actY = window.cmActuals(v, Y);
  const sites = window.SITES || [];
  const spend = Object.values(actY).reduce((a, c) => a + Object.values(c).reduce((b, x) => b + x, 0), 0);
  const budget = sites.reduce((a, s) => a + Object.values(v.budget[s.id] || {}).reduce((b, x) => b + x, 0), 0);
  const [y, m, d] = T.split("-").map(Number); const elapsed = ((m - 1) + d / 30) / 12;
  const byCat = Object.keys(window.CM_CATS).map(k => [k, Object.values(actY).reduce((a, c) => a + (c[k] || 0), 0), sites.reduce((a, s) => a + ((v.budget[s.id] || {})[k] || 0), 0)]);
  const pend = v.pos.filter(p => p.status === "pending").length + v.sInv.filter(x => x.status === "pending").length;
  const disputed = v.sInv.filter(x => x.status === "disputed").length;
  const committed = v.pos.filter(p => ["approved", "received"].includes(p.status)).reduce((a, p) => a + p.amount, 0);
  const pen = v.sInv.filter(x => ["approved", "paid"].includes(x.status) && window.cmIn(x.date, Y)).reduce((a, x) => a + (x.amount - window.cmSInvNet(v, x).net), 0);
  const pct = budget ? spend / budget * 100 : 0, ahead = pct > elapsed * 110;
  return <div className="card dw dw-cost">
    <div className="card-hd">Contracts & costs · {y}<span className="sub">O&M and inspection spend vs budget</span><div className="actions">{pend > 0 && <span className="pill warn"><span className="dot"/>{pend} to approve</span>}<button className="btn btn-ghost btn-xs" onClick={() => go("commercial")}>Open<Icon name="arrow_right" size={11}/></button></div></div>
    <div className="dw-cost-wrap">
      <div className="dw-cost-main">
        <div className="dw-cost-big"><b>{window.cmEur(spend)}</b><span>spent of {window.cmEur(budget)} · <b className={ahead ? "cm-warn-t" : "cm-ok-t"}>{pct.toFixed(0)}%</b></span></div>
        <div className="dw-bud"><i style={{ width: Math.max(1, Math.min(100, pct)) + "%", background: ahead ? "var(--sev-critical)" : "var(--accent-primary)" }}/><em style={{ left: elapsed * 100 + "%" }}><span>{`${Math.round(elapsed * 100)}% of year`}</span></em></div>
        <div className="dw-cats">{byCat.map(([k, a, b]) => { const p = b ? a / b * 100 : 0; return <div key={k}><div className="dw-cat-h"><span>{window.CM_CATS[k]}</span><em>{b ? Math.round(p) + "%" : "—"}</em></div><b>{window.cmEur(a)}</b><div className="dw-mini"><i style={{ width: Math.min(100, p) + "%", background: p > elapsed * 110 ? "var(--sev-critical)" : "var(--accent-primary)" }}/></div><em className="dw-of">of {b ? window.cmEur(b) : "no budget"}</em></div>; })}</div>
      </div>
      <div className="dw-cost-side">{[["Committed POs", window.cmEur(committed), ""], ["Penalties recovered", window.cmEur(pen), ""], ["Pending approvals", pend, pend ? "warn" : ""], ["Disputed invoices", disputed, disputed ? "crit" : ""]].map(([l, x, t]) => <div key={l} className={t}><span>{l}</span><b>{x}</b></div>)}</div>
    </div>
  </div>;
}

Object.assign(window, { WoDashCard, CostDashCard });
