/* === Reports — GR check-in generator ===
   Mirrors the Retirement Legal GR Check-in agenda: per-jurisdiction rows with
   the tracked bills + sponsors (Quorum-derived), the compliance LANE, and the
   running status narrative. Grouped "Updates" (recent activity) vs "Other
   (no updates since last check-in)".

   Lane derivation (per Andrew):
     - engagement TA            → "TA"
     - engagement lobbying      → "IRS + State lobbying" ("IRS lobbying only"
                                   for DC; "IRS + LDA" for a federal row)
     - GA firm present          → takes precedence: appended with contract
                                   status matched from CAPS by vendor name
   Meetings (Salesforce / lobbying-time log) will slot in as a section here
   once the Salesforce report format is known. */

function parseUsDate(s) {
  if (!s) return null;
  const d = new Date(s);
  return isNaN(d) ? null : d;
}

function gaFirmStatus(j) {
  const eng = j.engagement || [];
  if (!j.gaFirm && !eng.includes("lobbying-ga")) return null;
  const firm = j.gaFirm || "firm TBD";
  const c = j.gaFirm ? (window.CONTRACTS || []).find((c) =>
    c.vendor.toLowerCase().includes(j.gaFirm.toLowerCase()) ||
    j.gaFirm.toLowerCase().includes(c.vendor.toLowerCase())) : null;
  if (!c) return { firm, status: "no contract on file" };
  const exp = parseUsDate(c.expire), now = new Date();
  const status = !exp ? "contract dates unknown"
    : exp < now ? `contract expired ${c.expire}`
    : (exp - now < 90 * 864e5) ? `contract expires ${c.expire}`
    : "active contract";
  return { firm, status };
}

function grLane(abbr, j) {
  const eng = j.engagement || [];
  const parts = [];
  const lobbying = eng.includes("lobbying") || eng.includes("lobbying-ga") || j.gaFirm;
  if (lobbying) {
    parts.push(abbr === "DC" ? "IRS lobbying only" : abbr === "FED" ? "IRS + LDA" : "IRS + State lobbying");
  } else if (eng.includes("ta")) {
    parts.push("TA");
  } else if (eng.includes("events")) {
    parts.push("Events / other");
  }
  const ga = gaFirmStatus(j);
  if (ga) parts.push(`GA firm — ${ga.firm} (${ga.status})`);
  return parts.join(" · ") || "—";
}

const PROGRAM_LABEL_R = { live: "Active program (live)", enacted: "Enacted — implementing", none: "No program" };
const LEG_LABEL_R = { "enacted-session": "Enacted this session", active: "Active legislation", recent: "Recent legislation", none: "No legislation this session" };

function grRows() {
  const RECENT_BILL_DAYS = 45;
  const now = new Date();
  return Object.entries(window.JURISDICTIONS)
    .map(([abbr, j]) => {
      const bills = (window.BILLS || []).filter((b) => b.state === abbr);
      const engaged = (j.engagement || []).length || j.gaFirm || j.grNote || bills.length ||
        j.legActivity === "active" || j.legActivity === "enacted-session";
      const recentBill = bills.some((b) => {
        const d = parseUsDate(b.statusDate);
        return d && (now - d) / 864e5 <= RECENT_BILL_DAYS;
      });
      return { abbr, j, bills, engaged, recentBill };
    })
    .filter((r) => r.engaged)
    .sort((a, b) => {
      const order = (r) => (r.j.legActivity === "active" || r.j.legActivity === "enacted-session") ? 0 :
        (r.j.engagement || []).length ? 1 : 2;
      return order(a) - order(b) || a.abbr.localeCompare(b.abbr);
    });
}

function grMarkdown(updates, others, editsByState) {
  const today = new Date().toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" });
  const line = (r) => {
    const out = [`**${window.STATE_NAMES[r.abbr] || r.abbr}**${r.j.label ? ` (${r.j.label})` : ""}`];
    out.push(`  - Status: ${PROGRAM_LABEL_R[r.j.program]} · ${LEG_LABEL_R[r.j.legActivity]}`);
    out.push(`  - Lane: ${grLane(r.abbr, r.j)}`);
    for (const b of r.bills) out.push(`  - ${b.bill} (${b.sponsors || "sponsor n/a"}) — ${b.status}, ${b.statusDate || b.intro}`);
    if (r.j.grNote) out.push(`  - Note: ${r.j.grNote}`);
    const ev = editsByState[r.abbr];
    if (ev) out.push(`  - Last dashboard edit: ${fmtEventTs(ev.ts)} by ${ev.user_name}`);
    return out.join("\n");
  };
  return [
    `## Retirement Savings — GR check-in · generated ${today}`,
    ``, `### Updates`, ...updates.map(line),
    ``, `### Other (no recent activity)`, ...others.map(line),
  ].join("\n");
}

function GRReport() {
  const [events, setEvents] = React.useState([]);
  const [copied, setCopied] = React.useState(false);
  React.useEffect(() => {
    window.Store.history({ type: "jurisdiction" }).then(setEvents).catch(() => setEvents([]));
  }, []);

  // Latest edit event per state (already newest-first from the store).
  const editsByState = {};
  for (const e of events) if (!editsByState[e.entityId]) editsByState[e.entityId] = e;

  const RECENT_EDIT_DAYS = 30;
  const now = new Date();
  const isRecentEdit = (abbr) => {
    const e = editsByState[abbr];
    if (!e) return false;
    const iso = e.ts.includes("T") ? e.ts : e.ts.replace(" ", "T") + "Z";
    const d = new Date(iso);
    return !isNaN(d) && (now - d) / 864e5 <= RECENT_EDIT_DAYS;
  };

  const rows = grRows();
  const updates = rows.filter((r) => r.recentBill || isRecentEdit(r.abbr));
  const others = rows.filter((r) => !updates.includes(r));

  async function copy() {
    try {
      await navigator.clipboard.writeText(grMarkdown(updates, others, editsByState));
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    } catch (e) { /* clipboard denied — ignore */ }
  }

  return (
    <div>
      <div className="section-head report-controls">
        <div>
          <div className="section-title">GR check-in report</div>
          <div className="section-sub">
            Jurisdiction · lane · tracked bills with sponsors (Quorum) · status note.
            "Updates" = a bill action in the last 45 days or a dashboard edit in the last 30.
          </div>
        </div>
        <div className="row">
          <button className="btn" onClick={copy}>{copied ? "Copied ✓" : "Copy as Markdown"}</button>
          <button className="btn btn--primary" onClick={() => window.print()}>Print / PDF</button>
        </div>
      </div>

      <GRSection title="Updates" rows={updates} editsByState={editsByState} />
      <GRSection title="Other (no recent activity)" rows={others} editsByState={editsByState} dim />

      <div className="mono faint" style={{ fontSize: 10, marginTop: 18, lineHeight: 1.6 }}>
        MEETINGS: not yet tracked — will populate from the Salesforce lobbying-time report once its format is confirmed.
        Set each state's lane inputs (engagement type, GA firm) and the status note in the jurisdiction panel.
      </div>
    </div>
  );
}

function GRSection({ title, rows, editsByState, dim }) {
  return (
    <div style={{ marginBottom: 26, opacity: dim ? 0.9 : 1 }}>
      <div style={{ display: "flex", alignItems: "baseline", gap: 8, margin: "14px 0 8px" }}>
        <span className="eyebrow" style={{ fontSize: 11 }}>{title}</span>
        <span style={{ flex: 1, height: 1, background: "var(--rule)" }}></span>
        <span className="mono faint" style={{ fontSize: 11 }}>{rows.length}</span>
      </div>
      {rows.length === 0 ? (
        <div className="muted" style={{ fontSize: 12 }}>Nothing in this bucket.</div>
      ) : (
        <div className="card">
          {rows.map((r) => {
            const ev = editsByState[r.abbr];
            return (
              <div key={r.abbr} className="list-row" style={{ gridTemplateColumns: "150px 1.2fr 1.6fr", alignItems: "start" }}>
                <div>
                  <div style={{ fontWeight: 600, fontSize: 14, fontFamily: "var(--serif)" }}>{window.STATE_NAMES[r.abbr] || r.abbr}</div>
                  <div className="muted" style={{ fontSize: 11, marginTop: 2 }}>{r.j.label || "—"}</div>
                  <div style={{ marginTop: 6, display: "flex", flexDirection: "column", gap: 3, fontSize: 11, color: "var(--ink-2)" }}>
                    <span>{PROGRAM_LABEL_R[r.j.program]}</span>
                    <span style={{ color: r.j.legActivity === "active" || r.j.legActivity === "enacted-session" ? "var(--accent)" : "var(--ink-mute)" }}>
                      {LEG_LABEL_R[r.j.legActivity]}
                    </span>
                  </div>
                </div>
                <div>
                  <div className="eyebrow" style={{ marginBottom: 4 }}>Lane</div>
                  <div style={{ fontSize: 12, fontWeight: 600, color: "var(--ink)" }}>{grLane(r.abbr, r.j)}</div>
                  <div style={{ marginTop: 8 }}>
                    <EngagementChips list={r.j.engagement} small />
                  </div>
                  {ev ? (
                    <div className="mono faint" style={{ fontSize: 10, marginTop: 8 }}>
                      last edit {fmtEventTs(ev.ts)} · {ev.user_name}
                    </div>
                  ) : null}
                </div>
                <div>
                  {r.bills.length ? (
                    <div style={{ marginBottom: r.j.grNote ? 8 : 0 }}>
                      {r.bills.map((b) => (
                        <div key={b.id} style={{ padding: "4px 0", fontSize: 12 }}>
                          <span className="mono" style={{ fontWeight: 600 }}>{b.bill}</span>
                          <span className="muted"> ({b.sponsors || "sponsor n/a"})</span>
                          <span> — {b.status}</span>
                          <span className="mono faint" style={{ fontSize: 10 }}> · {b.statusDate || ("intro " + b.intro)}</span>
                        </div>
                      ))}
                    </div>
                  ) : (
                    <div className="muted" style={{ fontSize: 12, marginBottom: r.j.grNote ? 8 : 0 }}>No tracked bills.</div>
                  )}
                  {r.j.grNote ? (
                    <div style={{ padding: "8px 10px", borderLeft: "2px solid var(--accent)", background: "var(--surface-2)", fontSize: 12, fontStyle: "italic", lineHeight: 1.5, borderRadius: "0 3px 3px 0" }}>
                      {r.j.grNote}
                    </div>
                  ) : null}
                </div>
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}

Object.assign(window, { GRReport, grLane });
