/* Alerts dropdown + ToastContainer — JSX components */

const ToastContainer = () => {
  const [items, setItems] = React.useState([]);
  React.useEffect(() => window.toast.subscribe(setItems), []);

  const colors = {
    success: { bg: "var(--income-soft)", color: "var(--income-text-strong)", icon: "check" },
    info:    { bg: "var(--primary-soft)", color: "var(--primary-ink)",       icon: "sparkles" },
    error:   { bg: "var(--expense-soft)", color: "var(--expense-text-strong)", icon: "bell" },
  };

  return (
    <div style={{
      position: "fixed", bottom: 22, right: 22, zIndex: 9999,
      display: "flex", flexDirection: "column", gap: 8, pointerEvents: "none",
      maxWidth: 380,
    }}>
      {items.map(t => {
        const c = colors[t.type] || colors.info;
        return (
          <div key={t.id} style={{
            background: "var(--surface)",
            border: "1px solid var(--hairline)",
            borderLeft: "3px solid " + c.color,
            borderRadius: 12,
            padding: "12px 14px",
            display: "flex", alignItems: "center", gap: 12,
            boxShadow: "var(--shadow-2)",
            pointerEvents: "auto",
            animation: "toast-in 0.22s cubic-bezier(0.2, 0.8, 0.2, 1)",
            minWidth: 240,
          }}>
            <div style={{
              width: 28, height: 28, borderRadius: 8,
              background: c.bg, color: c.color,
              display: "grid", placeItems: "center", flexShrink: 0,
            }}>
              <Icon name={c.icon} size={14} />
            </div>
            <div style={{ flex: 1, fontSize: 13.5, color: "var(--ink)", lineHeight: 1.35 }}>
              {t.message}
            </div>
            {t.action && (
              <button className="btn btn-ghost btn-sm" onClick={() => { t.action.onClick(); window.toast.dismiss(t.id); }}>
                {t.action.label}
              </button>
            )}
            <button className="btn btn-ghost btn-sm" onClick={() => window.toast.dismiss(t.id)}
              style={{ padding: 4 }} aria-label="Dismiss">
              <Icon name="close" size={12} />
            </button>
          </div>
        );
      })}
    </div>
  );
};

const computeAlerts = (state) => {
  const txState = state.txState;
  const invoiceState = state.invoiceState;
  const accounts = state.accounts;

  const today = window.CB_DATA.today;
  const todayStr = today.toISOString().slice(0, 10);
  const alerts = [];

  // 1. Overdue invoices
  invoiceState
    .filter(i => (i.status === "sent" || i.status === "overdue") && i.dueAt < todayStr)
    .forEach(i => {
      const days = Math.floor((today - new Date(i.dueAt)) / 86400000);
      alerts.push({
        id: "alert_inv_" + i.id,
        severity: days > 30 ? "high" : "medium",
        title: "Invoice " + i.number + " is " + days + "d overdue",
        sub: i.client.name + " · " + CB.fmt(window.invoiceTotal(i), { cents: false }),
        action: { label: "Send reminder", target: "invoices" },
        ts: i.dueAt,
      });
    });

  // 2. Cash buffer
  const totalCash = accounts.filter(a => a.balance && a.balance > 0).reduce((s, a) => s + a.balance, 0);
  const monthAgo = new Date(today.getFullYear(), today.getMonth() - 1, 1).toISOString().slice(0, 10);
  const monthlyExp = txState
    .filter(t => t.type === "expense" && t.date >= monthAgo)
    .reduce((s, t) => s + CB.txToUSD(t), 0);
  if (monthlyExp > 0 && totalCash < monthlyExp * 2) {
    alerts.push({
      id: "alert_cash_low",
      severity: totalCash < monthlyExp ? "high" : "medium",
      title: "Cash buffer running thin",
      sub: CB.fmt(totalCash, { cents: false }) + " on hand · " + (totalCash / monthlyExp).toFixed(1) + "x monthly burn",
      action: { label: "View forecast", target: "forecast" },
      ts: todayStr,
    });
  }

  // 3. Tax due
  const taxDates = ["2026-06-15", "2026-09-15", "2027-01-15"];
  for (const d of taxDates) {
    if (d < todayStr) continue;
    const daysUntil = Math.ceil((new Date(d) - today) / 86400000);
    if (daysUntil > 30) break;
    alerts.push({
      id: "alert_tax_" + d,
      severity: daysUntil < 7 ? "high" : "medium",
      title: "Quarterly tax due in " + daysUntil + "d",
      sub: "Estimated payment by " + new Date(d).toLocaleDateString("en-US", { month: "short", day: "numeric" }),
      action: { label: "Tax setup", target: "settings" },
      ts: d,
    });
    break;
  }

  // 4. Review queue
  const queueLen = txState.filter(t => t.needsReview || !t.category).length;
  if (queueLen > 0) {
    alerts.push({
      id: "alert_review",
      severity: "low",
      title: queueLen + " transaction" + (queueLen === 1 ? "" : "s") + " need review",
      sub: "Confirm AI suggestions or pick a category",
      action: { label: "Open review", target: "review" },
      ts: todayStr,
    });
  }

  // 5. Subscription price changes
  const subs = (window.CB_INTEL && window.CB_INTEL.detectSubscriptions(txState)) || [];
  const changed = subs.filter(s => s.priceChanged && s.priceChangePct > 0);
  if (changed.length > 0) {
    const top = changed[0];
    alerts.push({
      id: "alert_sub_price",
      severity: "low",
      title: top.vendor + " raised its price " + top.priceChangePct.toFixed(0) + "%",
      sub: CB.fmt(top.firstAmount) + " to " + CB.fmt(top.latestAmount),
      action: { label: "Subscriptions", target: "subscriptions" },
      ts: top.lastCharge,
    });
  }

  const sev = { high: 0, medium: 1, low: 2 };
  return alerts.sort((a, b) => sev[a.severity] - sev[b.severity]);
};

const AlertsButton = ({ alerts, onJump, onMarkAllRead, onDismiss, dismissed }) => {
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);
  React.useEffect(() => {
    const handler = (e) => {
      if (ref.current && !ref.current.contains(e.target)) setOpen(false);
    };
    document.addEventListener("mousedown", handler);
    return () => document.removeEventListener("mousedown", handler);
  }, []);

  const visible = alerts.filter(a => !dismissed.has(a.id));
  const count = visible.length;
  const high = visible.filter(a => a.severity === "high").length;
  const sevColor = (s) =>
    s === "high"   ? "var(--expense)" :
    s === "medium" ? "var(--primary)" :
                     "var(--ink-soft)";

  return (
    <div ref={ref} style={{ position: "relative" }}>
      <button className="btn" onClick={() => setOpen(o => !o)}
        style={{ position: "relative", padding: 9 }}
        aria-label="Notifications">
        <Icon name="bell" size={16} />
        {count > 0 && (
          <span style={{
            position: "absolute", top: -4, right: -4,
            background: high > 0 ? "var(--expense)" : "var(--primary)",
            color: "white", fontSize: 10, fontWeight: 700,
            padding: "1px 6px", borderRadius: 10, minWidth: 18, textAlign: "center",
            boxShadow: "0 0 0 2px var(--bg)",
          }}>{count}</span>
        )}
      </button>

      {open && (
        <div style={{
          position: "absolute", top: "calc(100% + 8px)", right: 0,
          width: 360, maxWidth: "92vw",
          background: "var(--surface)",
          border: "1px solid var(--hairline)",
          borderRadius: 14,
          boxShadow: "var(--shadow-pop)",
          zIndex: 200, overflow: "hidden",
          maxHeight: "70vh", display: "flex", flexDirection: "column",
        }}>
          <div style={{
            padding: "14px 16px", borderBottom: "1px solid var(--hairline)",
            display: "flex", justifyContent: "space-between", alignItems: "center", gap: 10,
          }}>
            <div>
              <div style={{ fontFamily: "var(--font-display)", fontSize: 18 }}>Notifications</div>
              <div style={{ fontSize: 11.5, color: "var(--muted)", marginTop: 2 }}>
                {count === 0
                  ? "All clear"
                  : count + " alert" + (count === 1 ? "" : "s") + (high > 0 ? " · " + high + " need attention" : "")}
              </div>
            </div>
            {count > 0 && (
              <button className="btn btn-sm btn-ghost"
                onClick={() => onMarkAllRead(alerts.map(a => a.id))}
                style={{ flexShrink: 0, fontSize: 11.5 }}>
                <Icon name="check" size={11} /> Mark all read
              </button>
            )}
          </div>

          <div style={{ flex: 1, overflowY: "auto" }}>
            {visible.length === 0 ? (
              <div style={{ padding: 40, textAlign: "center", color: "var(--muted)", fontSize: 13 }}>
                <Icon name="check" size={24} />
                <div style={{ marginTop: 8 }}>Nothing needs your attention right now.</div>
              </div>
            ) : visible.map(a => (
              <div key={a.id} style={{
                display: "flex", alignItems: "stretch",
                borderBottom: "1px solid var(--hairline)",
              }}>
                {/* Main clickable area */}
                <button
                  onClick={() => { if (a.action) onJump(a.action.target); setOpen(false); }}
                  style={{
                    display: "flex", gap: 12, flex: 1, textAlign: "left",
                    padding: "14px 16px", border: 0,
                    background: "transparent", cursor: "pointer", minWidth: 0,
                  }}>
                  <div style={{
                    width: 8, height: 8, borderRadius: "50%",
                    background: sevColor(a.severity), flexShrink: 0, marginTop: 5,
                  }} />
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 13, fontWeight: 500 }}>{a.title}</div>
                    <div style={{ fontSize: 11.5, color: "var(--muted)", marginTop: 2 }}>{a.sub}</div>
                    {a.action && (
                      <div style={{ fontSize: 11, color: "var(--primary-ink)", marginTop: 6, fontWeight: 500 }}>
                        {a.action.label}
                      </div>
                    )}
                  </div>
                </button>
                {/* Per-row dismiss */}
                <button
                  onClick={() => onDismiss(a.id)}
                  title="Mark as read"
                  style={{
                    border: 0, background: "transparent", cursor: "pointer",
                    padding: "0 14px", color: "var(--muted)", flexShrink: 0,
                    display: "flex", alignItems: "center",
                  }}
                  onMouseEnter={e => e.currentTarget.style.color = "var(--ink)"}
                  onMouseLeave={e => e.currentTarget.style.color = "var(--muted)"}
                  aria-label="Mark as read">
                  <Icon name="close" size={13} />
                </button>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
};

window.ToastContainer = ToastContainer;
window.AlertsButton = AlertsButton;
window.computeAlerts = computeAlerts;
