/* Subscriptions — auto-detected recurring expenses */

const SubChargesModal = ({ sub, onClose }) => {
  if (!sub) return null;
  const baseCurM = window.CB_DATA?.profile?.baseCurrency || "USD";
  const fcM = (n, opts) => CB.fmtCur(CB.convert(n, "USD", baseCurM), baseCurM, opts || {});
  const txs = [...sub.transactions].sort((a, b) => b.date.localeCompare(a.date));
  const min = Math.min(...txs.map(t => CB.txToUSD(t)));
  const max = Math.max(...txs.map(t => CB.txToUSD(t)));
  const range = max - min;
  return (
    <Modal open={!!sub} onClose={onClose}
      title={`${sub.vendor} — charge history`}
      subtitle={`${txs.length} charge${txs.length !== 1 ? "s" : ""} · ${sub.cadence}`}
      maxWidth={520}
      footer={<button className="btn" onClick={onClose}>Close</button>}>
      <div style={{ display: "flex", flexDirection: "column", gap: 0, border: "1px solid var(--hairline)", borderRadius: 10, overflow: "hidden" }}>
        {txs.map((t, i) => {
          const tUSD = CB.txToUSD(t);
          const pct = range > 0 ? ((tUSD - min) / range) * 100 : 50;
          const isFirst = i === txs.length - 1;
          const isLatest = i === 0;
          const prevAmt = i < txs.length - 1 ? CB.txToUSD(txs[i + 1]) : null;
          const delta = prevAmt != null ? tUSD - prevAmt : null;
          return (
            <div key={t.id || t.date + t.amount} style={{
              display: "grid", gridTemplateColumns: "110px 1fr auto",
              alignItems: "center", gap: 12, padding: "11px 14px",
              borderBottom: i < txs.length - 1 ? "1px solid var(--hairline)" : "none",
              background: isLatest ? "var(--surface-2)" : undefined,
            }}>
              <div style={{ fontSize: 12.5, color: "var(--ink-soft)", fontFamily: "var(--font-mono)" }}>
                {new Date(t.date).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })}
                {isLatest && <span style={{ marginLeft: 6, fontSize: 10, background: "var(--primary)", color: "white", borderRadius: 4, padding: "1px 5px" }}>latest</span>}
                {isFirst && !isLatest && <span style={{ marginLeft: 6, fontSize: 10, background: "var(--surface-3,var(--hairline))", color: "var(--muted)", borderRadius: 4, padding: "1px 5px" }}>first</span>}
              </div>
              <div style={{ position: "relative", height: 6, background: "var(--hairline)", borderRadius: 3, overflow: "hidden" }}>
                <div style={{ position: "absolute", left: 0, top: 0, height: "100%", width: pct + "%", background: "var(--primary)", borderRadius: 3 }} />
              </div>
              <div style={{ textAlign: "right", fontFamily: "var(--font-mono)", fontSize: 13, fontWeight: 500, minWidth: 80 }}>
                {fcM(tUSD)}
                {delta != null && Math.abs(delta) > 0.01 && (
                  <div style={{ fontSize: 10.5, color: delta > 0 ? "var(--expense-text-strong)" : "var(--income-text-strong)", fontWeight: 400 }}>
                    {delta > 0 ? "+" : "−"}{fcM(Math.abs(delta))}
                  </div>
                )}
              </div>
            </div>
          );
        })}
      </div>
      <div style={{ marginTop: 12, display: "flex", justifyContent: "space-between", fontSize: 12, color: "var(--muted)" }}>
        <span>First charge: {new Date(sub.transactions[0].date).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })}</span>
        <span>Total paid: {fcM(txs.reduce((s, t) => s + CB.txToUSD(t), 0))}</span>
      </div>
    </Modal>
  );
};

const Subscriptions = ({ goTo, txState, profile }) => {
  const subs = React.useMemo(() => window.CB_INTEL.detectSubscriptions(txState), [txState]);
  const [muted, setMuted] = React.useState(() => {
    try { return JSON.parse(localStorage.getItem("cb_subs_muted") || "{}"); } catch { return {}; }
  });
  const [cancelled, setCancelled] = React.useState(() => {
    try { return JSON.parse(localStorage.getItem("cb_subs_cancelled") || "{}"); } catch { return {}; }
  });
  const [viewChargesSub, setViewChargesSub] = React.useState(null);
  const [filter, setFilter] = React.useState("all"); // all | monthly | yearly | flagged | cancelled

  React.useEffect(() => { localStorage.setItem("cb_subs_muted", JSON.stringify(muted)); }, [muted]);
  React.useEffect(() => { localStorage.setItem("cb_subs_cancelled", JSON.stringify(cancelled)); }, [cancelled]);

  const baseCur = profile?.baseCurrency || window.CB_DATA?.profile?.baseCurrency || "USD";
  const fc = (n, opts) => CB.fmtCur(CB.convert(n, "USD", baseCur), baseCur, opts || {});

  const markCancelled = (id) => setCancelled(c => ({ ...c, [id]: new Date().toISOString().slice(0, 10) }));
  const restore = (id) => setCancelled(c => { const n = { ...c }; delete n[id]; return n; });

  const activeSubs = subs.filter(s => !muted[s.id]);

  const liveSubs = activeSubs.filter(s => !cancelled[s.id]);
  const cancelledCount = activeSubs.filter(s => cancelled[s.id]).length;

  const monthlyBurn = liveSubs.reduce((sum, s) =>
    sum + (s.cadence === "monthly" ? s.amount : s.cadence === "yearly" ? s.amount / 12 : s.amount / 3), 0);
  const annualBurn = liveSubs.reduce((sum, s) => sum + s.annualizedCost, 0);
  const flaggedCount = liveSubs.filter(s => s.priceChanged).length;

  const visible = activeSubs.filter(s => {
    if (filter === "monthly") return s.cadence === "monthly" && !cancelled[s.id];
    if (filter === "yearly") return s.cadence === "yearly" && !cancelled[s.id];
    if (filter === "flagged") return s.priceChanged && !cancelled[s.id];
    if (filter === "cancelled") return !!cancelled[s.id];
    return true;
  });

  const totalSavings = activeSubs.filter(s => s.priceChanged && s.priceChangePct > 0)
    .reduce((sum, s) => sum + (s.latestAmount - s.firstAmount) * (s.cadence === "monthly" ? 12 : 1), 0);

  return (
    <div className="page-fade">
      <div className="page-head">
        <div>
          <h1 className="page-title">Subscriptions</h1>
          <div className="page-sub">
            {activeSubs.length} recurring · auto-detected from your transactions
          </div>
        </div>
        <div className="page-actions">
          <button className="btn"><Icon name="refresh" size={14} /> Re-scan</button>
          <button className="btn"><Icon name="download" size={14} /> Export</button>
        </div>
      </div>

      {/* KPI strip */}
      <div className="kpi-grid" style={{ gridTemplateColumns: "repeat(4, 1fr)" }}>
        <div className="kpi">
          <div className="kpi-label">Monthly burn</div>
          <div className="bignum-sm" style={{ color: "var(--expense)" }}>
            {fc(monthlyBurn, { cents: false })}
          </div>
          <div style={{ fontSize: 11, color: "var(--muted)" }}>
            across {activeSubs.length} subscriptions
          </div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Annual cost</div>
          <div className="bignum-sm">{fc(annualBurn, { cents: false })}</div>
          <div style={{ fontSize: 11, color: "var(--muted)" }}>
            if nothing changes
          </div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Price changes</div>
          <div className="bignum-sm" style={{ color: flaggedCount > 0 ? "var(--expense)" : "var(--ink)" }}>{flaggedCount}</div>
          <div style={{ fontSize: 11, color: "var(--muted)" }}>
            since first charge
          </div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Extra spent / year</div>
          <div className="bignum-sm">{fc(totalSavings, { cents: false })}</div>
          <div style={{ fontSize: 11, color: "var(--muted)" }}>
            from price increases
          </div>
        </div>
      </div>

      {/* Filter */}
      <div className="filters" style={{ marginTop: 22 }}>
        <div className="segmented">
          <button className={filter === "all" ? "on" : ""} onClick={() => setFilter("all")}>All</button>
          <button className={filter === "monthly" ? "on" : ""} onClick={() => setFilter("monthly")}>Monthly</button>
          <button className={filter === "yearly" ? "on" : ""} onClick={() => setFilter("yearly")}>Yearly</button>
          <button className={filter === "flagged" ? "on" : ""} onClick={() => setFilter("flagged")}>
            Flagged
            {flaggedCount > 0 && <span style={{ marginLeft: 4, padding: "0 6px", background: "var(--expense)", color: "white", borderRadius: 8, fontSize: 10 }}>{flaggedCount}</span>}
          </button>
          <button className={filter === "cancelled" ? "on" : ""} onClick={() => setFilter("cancelled")}>
            Cancelled
            {cancelledCount > 0 && <span style={{ marginLeft: 4, padding: "0 6px", background: "var(--surface-3,var(--hairline-strong))", color: "var(--ink-soft)", borderRadius: 8, fontSize: 10 }}>{cancelledCount}</span>}
          </button>
        </div>
        <span style={{ marginLeft: "auto", fontSize: 12, color: "var(--muted)" }}>
          Muted: {Object.values(muted).filter(Boolean).length}
        </span>
        {Object.values(muted).some(Boolean) && (
          <button className="btn btn-ghost btn-sm" onClick={() => setMuted({})}>Clear muted</button>
        )}
      </div>

      {/* Subscription cards */}
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
        {subs.length === 0 && (
          <div style={{ gridColumn: "1 / -1" }}>
            <EmptyState
              icon="refresh"
              title="No recurring charges detected yet"
              subtitle="Once you have a couple months of transaction history, CreatorBoard will spot recurring vendors and surface them here automatically."
              action={{ label: "Add transaction", icon: "plus", onClick: () => goTo("ledger", { addTx: true }) }}
              secondary={{ label: "Import statement", icon: "upload", onClick: () => goTo("ledger") }}
            />
          </div>
        )}
        {subs.length > 0 && visible.map(s => {
          const cat = CB.catById(s.category);
          const acc = CB.accountById(s.account);
          const daysUntil = Math.round((new Date(s.nextExpected) - window.CB_DATA.today) / 86400000);
          const isCancelled = !!cancelled[s.id];
          return (
            <div key={s.id} className="card" style={{ padding: 18, opacity: isCancelled ? 0.6 : 1 }}>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "start" }}>
                <div style={{ flex: 1 }}>
                  <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                    <div style={{
                      width: 38, height: 38, borderRadius: 10,
                      background: isCancelled ? "var(--surface-3,var(--hairline-strong))" : (cat?.color || "var(--surface-2)"),
                      display: "grid", placeItems: "center", color: isCancelled ? "var(--muted)" : "white",
                      fontFamily: "var(--font-display)", fontSize: 18,
                    }}>{s.vendor[0]}</div>
                    <div>
                      <div style={{ fontWeight: 500, fontSize: 15, display: "flex", alignItems: "center", gap: 8 }}>
                        {s.vendor}
                        {isCancelled && (
                          <span style={{ fontSize: 10, padding: "2px 7px", background: "var(--surface-2)", color: "var(--muted)", border: "1px solid var(--hairline-strong)", borderRadius: 6 }}>
                            Cancelled {cancelled[s.id]}
                          </span>
                        )}
                      </div>
                      <div style={{ fontSize: 11.5, color: "var(--muted)" }}>
                        <span className="cat-swatch" style={{ background: cat?.color, marginRight: 6 }} />
                        {cat?.name} · {s.occurrences} charge{s.occurrences > 1 ? "s" : ""}
                      </div>
                    </div>
                  </div>
                </div>
                <div style={{ textAlign: "right" }}>
                  <div style={{ fontFamily: "var(--font-display)", fontSize: 22 }}>
                    {fc(s.amount, { cents: s.amount < 100 })}
                  </div>
                  <div style={{ fontSize: 11, color: "var(--muted)", textTransform: "capitalize" }}>{s.cadence}</div>
                </div>
              </div>

              {s.priceChanged && (
                <div style={{
                  marginTop: 12, padding: "8px 12px", borderRadius: 8,
                  background: s.priceChangePct > 0 ? "var(--expense-soft)" : "var(--income-soft)",
                  fontSize: 12,
                  color: s.priceChangePct > 0 ? "var(--expense-text-strong)" : "var(--income-text-strong)",
                  display: "flex", alignItems: "center", gap: 8,
                }}>
                  <Icon name={s.priceChangePct > 0 ? "arrowUp" : "arrowDown"} size={12} />
                  Price changed {s.priceChangePct > 0 ? "+" : ""}{s.priceChangePct.toFixed(1)}%
                  <span style={{ opacity: 0.7 }}>
                    ({fc(s.firstAmount, { cents: s.firstAmount < 100 })} → {fc(s.latestAmount, { cents: s.latestAmount < 100 })})
                  </span>
                </div>
              )}

              <div style={{ marginTop: 12, display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10, fontSize: 12 }}>
                <div>
                  <div style={{ color: "var(--muted)" }}>Last charge</div>
                  <div style={{ fontWeight: 500, marginTop: 2 }}>{new Date(s.lastCharge).toLocaleDateString("en-US", { month: "short", day: "numeric" })}</div>
                </div>
                <div>
                  <div style={{ color: "var(--muted)" }}>Next expected</div>
                  <div style={{ fontWeight: 500, marginTop: 2 }}>
                    {new Date(s.nextExpected).toLocaleDateString("en-US", { month: "short", day: "numeric" })}
                    <span style={{ color: "var(--muted)", fontWeight: 400, marginLeft: 4 }}>
                      ({daysUntil > 0 ? `in ${daysUntil}d` : daysUntil === 0 ? "today" : `${-daysUntil}d ago`})
                    </span>
                  </div>
                </div>
                <div>
                  <div style={{ color: "var(--muted)" }}>Account</div>
                  <div style={{ fontWeight: 500, marginTop: 2 }}>{acc?.name?.split(" ")[0]}{acc?.last4 && acc.last4 !== "—" ? ` ··${acc.last4}` : ""}</div>
                </div>
                <div>
                  <div style={{ color: "var(--muted)" }}>Annual</div>
                  <div style={{ fontWeight: 500, marginTop: 2 }}>{fc(s.annualizedCost, { cents: false })}</div>
                </div>
              </div>

              <div style={{ marginTop: 14, display: "flex", gap: 6 }}>
                {isCancelled ? (
                  <button className="btn btn-sm" onClick={() => restore(s.id)}>
                    <Icon name="refresh" size={11} /> Restore
                  </button>
                ) : (
                  <button className="btn btn-sm" onClick={() => markCancelled(s.id)}>
                    <Icon name="close" size={11} /> Mark cancelled
                  </button>
                )}
                <button className="btn btn-sm btn-ghost" onClick={() => setViewChargesSub(s)}>
                  View charges
                </button>
                <button className="btn btn-sm btn-ghost" style={{ marginLeft: "auto" }} onClick={() => setMuted({ ...muted, [s.id]: true })}>
                  Mute
                </button>
              </div>
            </div>
          );
        })}
        {visible.length === 0 && (
          <div className="card empty" style={{ gridColumn: "1 / -1" }}>
            No subscriptions match this filter.
          </div>
        )}
      </div>

      <div className="card-quiet" style={{ marginTop: 16, padding: 14, display: "flex", gap: 12, alignItems: "start" }}>
        <Icon name="sparkles" size={16} />
        <div style={{ fontSize: 12.5, color: "var(--ink-soft)" }}>
          <b style={{ color: "var(--ink)" }}>How we detect subscriptions:</b> recurring vendor, stable amount (within 15%),
          and a consistent monthly, quarterly, or yearly cadence between charges.
          Hit "Mute" if a charge is recurring but shouldn't be treated as a subscription.
          Hit "Mark cancelled" to stop including it in your burn totals — it stays visible under the Cancelled filter.
        </div>
      </div>

      <SubChargesModal sub={viewChargesSub} onClose={() => setViewChargesSub(null)} />
    </div>
  );
};

window.Subscriptions = Subscriptions;
