// Parseia datas "YYYY-MM-DD" como hora local (evita off-by-one de UTC)
const parseDate = (d) => /^\d{4}-\d{2}-\d{2}$/.test(d || "") ? new Date(d + "T00:00:00") : new Date(d || NaN);

// Dashboard bifurcado: business vs personal
function Dashboard(props) {
  return props.ws.type === "personal"
    ? <DashboardPersonal {...props} />
    : <DashboardBusiness {...props} />;
}

// ---------- Hook compartilhado de período ----------
function usePeriod(currentMonth, rangeMode, customRange) {
  return React.useMemo(() => {
    if (rangeMode === "MES") return {
      from: new Date(currentMonth.year, currentMonth.month, 1),
      to: new Date(currentMonth.year, currentMonth.month + 1, 0, 23, 59, 59),
      label: new Date(currentMonth.year, currentMonth.month, 1)
        .toLocaleDateString("pt-BR", { month: "long", year: "numeric" }),
    };
    if (rangeMode === "TRIMESTRE") return {
      from: new Date(currentMonth.year, currentMonth.month - 2, 1),
      to: new Date(currentMonth.year, currentMonth.month + 1, 0, 23, 59, 59),
      label: "Últimos 3 meses",
    };
    if (rangeMode === "ANO") return {
      from: new Date(currentMonth.year, 0, 1),
      to: new Date(currentMonth.year, 11, 31, 23, 59, 59),
      label: `Ano ${currentMonth.year}`,
    };
    if (rangeMode === "TUDO") return {
      from: new Date(1900, 0, 1),
      to: new Date(2100, 11, 31, 23, 59, 59),
      label: "Tudo (sem filtro de data)",
    };
    // PERSONALIZADO — valida que tem from/to e que from <= to
    const safeFrom = customRange?.from ? new Date(customRange.from) : new Date(1900, 0, 1);
    const safeTo = customRange?.to ? new Date(customRange.to + "T23:59:59") : new Date(2100, 11, 31);
    return {
      from: safeFrom,
      to: safeTo,
      label: `${safeFrom.toLocaleDateString("pt-BR")} → ${safeTo.toLocaleDateString("pt-BR")}`,
    };
  }, [rangeMode, customRange, currentMonth]);
}

function useData(ws, currentMonth, period) {
  const txns = ws.transactions || [];
  const recs = ws.receitas || [];
  const inPeriod = (d) => { const dt = parseDate(d); return dt >= period.from && dt <= period.to; };
  const monthTxns = txns.filter(t => inPeriod(t.date));
  const monthRecs = recs.filter(r => inPeriod(r.date));
  const totalOut = monthTxns.reduce((s, t) => s + (Number(t.value) || 0), 0);
  const totalIn  = monthRecs.reduce((s, r) => s + (Number(r.value) || 0), 0);
  const balance  = totalIn - totalOut;
  const pending  = txns.filter(t => t.status === "PENDENTE" || t.status === "AGENDADO");
  const pendingTotal = pending.reduce((s, t) => s + (Number(t.value) || 0), 0);

  const months = [];
  for (let i = 5; i >= 0; i--) {
    const d = new Date(currentMonth.year, currentMonth.month - i, 1);
    const y = d.getFullYear(), m = d.getMonth();
    const mIn  = recs.filter(r => { const dd = parseDate(r.date); return dd.getFullYear()===y && dd.getMonth()===m; }).reduce((s,r) => s+(Number(r.value)||0), 0);
    const mOut = txns.filter(t => { const dd = parseDate(t.date); return dd.getFullYear()===y && dd.getMonth()===m; }).reduce((s,t) => s+(Number(t.value)||0), 0);
    months.push({ label: monthLabel(m), in: mIn, out: mOut });
  }

  return { txns, recs, monthTxns, monthRecs, totalOut, totalIn, balance, pending, pendingTotal, months };
}

// ---------- Barra de período ----------
function PeriodBar({ rangeMode, setRangeMode, customRange, setCustomRange, period, children }) {
  return (
    <div className="card" style={{ padding: 14, display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap" }}>
      <span style={{ fontSize: 11.5, color: "var(--fg-3)", textTransform: "uppercase", letterSpacing: 0.6, fontWeight: 500 }}>Período:</span>
      <div style={{ display: "flex", gap: 4, padding: 3, background: "var(--surface-2)", borderRadius: 8, flexWrap: "wrap" }}>
        {[
          { k:"MES",l:"Mês" },
          { k:"TRIMESTRE",l:"Trimestre" },
          { k:"ANO",l:"Ano" },
          { k:"TUDO",l:"Tudo" },
          { k:"PERSONALIZADO",l:"Personalizado" },
        ].map(o => (
          <button key={o.k} onClick={() => setRangeMode(o.k)} style={{
            padding: "5px 11px", border: "none", cursor: "pointer", borderRadius: 6,
            fontFamily: "inherit", fontSize: 12.5,
            background: rangeMode===o.k ? "var(--surface-1)" : "transparent",
            color: rangeMode===o.k ? "var(--fg-1)" : "var(--fg-2)",
            fontWeight: rangeMode===o.k ? 500 : 400,
            boxShadow: rangeMode===o.k ? "var(--shadow-sm)" : "none",
          }}>{o.l}</button>
        ))}
      </div>
      {rangeMode === "PERSONALIZADO" && (
        <div style={{ display: "flex", alignItems: "center", gap: 8, padding: "6px 10px", background: "color-mix(in oklab, var(--green) 6%, var(--surface-2))", border: "1px solid color-mix(in oklab, var(--green) 25%, var(--border))", borderRadius: 8 }}>
          <span style={{ fontSize: 11, color: "var(--fg-3)" }}>De</span>
          <input type="date" className="input small" value={customRange.from || ""} onChange={e => setCustomRange(r => ({ ...r, from: e.target.value }))} style={{ minWidth: 130 }} />
          <span style={{ fontSize: 11, color: "var(--fg-3)" }}>até</span>
          <input type="date" className="input small" value={customRange.to || ""} onChange={e => setCustomRange(r => ({ ...r, to: e.target.value }))} style={{ minWidth: 130 }} />
        </div>
      )}
      <span style={{ fontSize: 12.5, color: "var(--fg-2)", textTransform: "capitalize" }}>{period.label}</span>
      <div style={{ flex: 1 }} />
      {children}
    </div>
  );
}

// ---------- KPI card ----------
function KPI({ title, value, icon, tone, sub }) {
  const toneColor = { pos:"var(--success)", neg:"var(--danger)", warn:"var(--warn)", neutral:"var(--fg-1)" }[tone] || "var(--fg-1)";
  return (
    <div className="card" style={{ padding: 16 }}>
      <div style={{ display:"flex", justifyContent:"space-between", alignItems:"flex-start", marginBottom: 12 }}>
        <span style={{ fontSize: 11.5, color:"var(--fg-3)", textTransform:"uppercase", letterSpacing: 0.6, fontWeight: 500 }}>{title}</span>
        <span style={{ width:28, height:28, borderRadius:8, background:`color-mix(in oklab, ${toneColor} 12%, transparent)`, color:toneColor, display:"flex", alignItems:"center", justifyContent:"center" }}>
          <Icon name={icon} size={15} />
        </span>
      </div>
      <div style={{ fontSize: 22, fontWeight: 600, color:"var(--fg-1)", fontVariantNumeric:"tabular-nums", letterSpacing:-0.3, overflow:"hidden", textOverflow:"ellipsis", whiteSpace:"nowrap" }}>{value}</div>
      <div style={{ fontSize: 11.5, color:"var(--fg-3)", marginTop: 4 }}>{sub}</div>
    </div>
  );
}

function Empty() {
  return <div style={{ padding:24, textAlign:"center", color:"var(--fg-3)", fontSize:13 }}>Sem dados neste período</div>;
}

// ---------- Resumo do mês (linguagem simples) ----------
function DREGerencial({ totalIn, totalOut, balance, monthTxns }) {
  const byCat = {};
  monthTxns.forEach(t => {
    const key = t.category || t.enquadramento || "Outros";
    byCat[key] = (byCat[key] || 0) + (Number(t.value) || 0);
  });
  const catEntries = Object.entries(byCat).sort((a, b) => b[1] - a[1]);
  const top4 = catEntries.slice(0, 4);
  const othersTotal = catEntries.slice(4).reduce((s, [, v]) => s + v, 0);
  const margem = totalIn > 0 ? Math.round((balance / totalIn) * 100) : 0;

  if (monthTxns.length === 0 && totalIn === 0) return <Empty />;

  const Line = ({ label, value, color, bold }) => (
    <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", padding: "8px 0" }}>
      <span style={{ fontSize: 13, color: "var(--fg-2)", fontWeight: bold ? 600 : 400 }}>{label}</span>
      <span style={{ fontSize: 14, fontVariantNumeric: "tabular-nums", fontWeight: bold ? 700 : 500, color: color || "var(--fg-1)" }}>
        {fmtBRL(value)}
      </span>
    </div>
  );

  return (
    <div>
      {/* Conta simples */}
      <div style={{ background: "var(--surface-2)", borderRadius: 10, padding: "4px 14px", marginBottom: 14 }}>
        <Line label="O que entrou" value={totalIn} color="var(--success)" bold />
        <div style={{ borderTop: "1px solid var(--border)" }} />
        <Line label="O que saiu" value={-totalOut} color="var(--danger)" bold />
        <div style={{ borderTop: "2px solid var(--border)" }} />
        <Line label="Sobrou" value={balance} color={balance >= 0 ? "var(--success)" : "var(--danger)"} bold />
      </div>

      {/* Margem */}
      {totalIn > 0 && (
        <div style={{ padding: "10px 12px", background: `color-mix(in oklab, ${margem >= 0 ? "var(--success)" : "var(--danger)"} 8%, var(--surface-1))`, borderRadius: 8, marginBottom: 14 }}>
          <div style={{ fontSize: 12.5, color: "var(--fg-2)", lineHeight: 1.5 }}>
            {margem >= 0
              ? <>Você ficou com <strong style={{ color: "var(--success)", fontSize: 14 }}>{margem}%</strong> do que faturou neste período.</>
              : <>Você gastou <strong style={{ color: "var(--danger)", fontSize: 14 }}>{Math.abs(margem)}%</strong> a mais do que recebeu.</>
            }
          </div>
        </div>
      )}

      {/* Onde foi o dinheiro */}
      {catEntries.length > 0 && (
        <div>
          <div style={{ fontSize: 11.5, color: "var(--fg-3)", textTransform: "uppercase", letterSpacing: 0.6, fontWeight: 500, marginBottom: 8 }}>
            Para onde foi o dinheiro
          </div>
          <div>
            {top4.map(([cat, val]) => {
              const pct = Math.round((val / totalOut) * 100);
              return (
                <div key={cat} style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", padding: "6px 0", borderBottom: "1px solid var(--border)" }}>
                  <span style={{ fontSize: 12.5, color: "var(--fg-2)" }}>{cat} <span style={{ color: "var(--fg-3)" }}>· {pct}%</span></span>
                  <span style={{ fontSize: 12.5, color: "var(--fg-1)", fontVariantNumeric: "tabular-nums" }}>{fmtBRL(val)}</span>
                </div>
              );
            })}
            {othersTotal > 0 && (
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", padding: "6px 0" }}>
                <span style={{ fontSize: 12.5, color: "var(--fg-3)" }}>Outros</span>
                <span style={{ fontSize: 12.5, color: "var(--fg-2)", fontVariantNumeric: "tabular-nums" }}>{fmtBRL(othersTotal)}</span>
              </div>
            )}
          </div>
        </div>
      )}
    </div>
  );
}

// ---------- Painel de Inadimplência ----------
function Inadimplencia({ recs }) {
  const today = new Date(); today.setHours(0, 0, 0, 0);
  const overdue = recs.filter(r => {
    const d = parseDate(r.date);
    return (r.status === "A RECEBER" || r.status === "PENDENTE") && d < today;
  });

  if (overdue.length === 0) {
    return (
      <div style={{ display:"flex", flexDirection:"column", alignItems:"center", justifyContent:"center", padding:"28px 0", gap:10 }}>
        <div style={{ width:44, height:44, borderRadius:12, background:"color-mix(in oklab, var(--success) 10%, transparent)", color:"var(--success)", display:"flex", alignItems:"center", justifyContent:"center" }}>
          <Icon name="check" size={22} />
        </div>
        <div style={{ fontSize:13, color:"var(--fg-3)", textAlign:"center" }}>Nenhum recebível em atraso</div>
      </div>
    );
  }

  const totalOverdue = overdue.reduce((s, r) => s + (Number(r.value) || 0), 0);
  const buckets = [
    { label: "1–30 dias",  color: "#f59e0b", min: 1,  max: 30 },
    { label: "31–60 dias", color: "#ef4444", min: 31, max: 60 },
    { label: "> 60 dias",  color: "#7f1d1d", min: 61, max: Infinity },
  ].map(b => {
    const items = overdue.filter(r => {
      const diff = Math.floor((today - parseDate(r.date)) / 86400000);
      return diff >= b.min && diff <= b.max;
    });
    return { ...b, count: items.length, total: items.reduce((s, r) => s + (Number(r.value) || 0), 0) };
  }).filter(b => b.count > 0);

  return (
    <div>
      <div style={{ marginBottom: 14 }}>
        <div style={{ fontSize: 11, color: "var(--fg-3)", textTransform: "uppercase", letterSpacing: 0.6, marginBottom: 2 }}>Total em atraso</div>
        <div style={{ fontSize: 22, fontWeight: 700, color: "var(--danger)", fontVariantNumeric: "tabular-nums" }}>{fmtBRL(totalOverdue)}</div>
        <div style={{ fontSize: 11.5, color: "var(--fg-3)" }}>{overdue.length} cliente{overdue.length > 1 ? "s" : ""} ainda não pagaram</div>
      </div>
      <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
        {buckets.map(b => (
          <div key={b.label} style={{ display:"flex", justifyContent:"space-between", alignItems:"center", padding:"8px 10px", borderRadius:8, borderLeft:`3px solid ${b.color}`, background:`color-mix(in oklab, ${b.color} 8%, var(--surface-1))` }}>
            <div>
              <div style={{ fontSize: 12, fontWeight: 600, color: b.color }}>{b.label}</div>
              <div style={{ fontSize: 11, color: "var(--fg-3)" }}>{b.count} item{b.count > 1 ? "s" : ""}</div>
            </div>
            <div style={{ fontSize: 13.5, fontWeight: 600, color: "var(--fg-1)", fontVariantNumeric: "tabular-nums" }}>{fmtBRL(b.total)}</div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ---------- O que vem por aí (Fluxo Projetado) ----------
function FluxoProjetado({ txns, recs }) {
  const today = new Date(); today.setHours(0, 0, 0, 0);

  const safeTxns = txns || [];
  const safeRecs = recs || [];
  const bucket = (days) => {
    const to = new Date(today); to.setDate(to.getDate() + days); to.setHours(23, 59, 59);
    const out = safeTxns.filter(t => {
      const d = parseDate(t.date);
      return (t.status === "PENDENTE" || t.status === "AGENDADO") && d >= today && d <= to;
    }).reduce((s, t) => s + (Number(t.value) || 0), 0);
    const inp = safeRecs.filter(r => {
      const d = parseDate(r.date);
      return (r.status === "A RECEBER" || r.status === "PENDENTE" || r.status === "AGENDADO") && d >= today && d <= to;
    }).reduce((s, r) => s + (Number(r.value) || 0), 0);
    return { out, inp, net: inp - out };
  };

  const buckets = [
    { label: "30 dias", b: bucket(30) },
    { label: "60 dias", b: bucket(60) },
    { label: "90 dias", b: bucket(90) },
  ];

  if (buckets.every(x => x.b.inp === 0 && x.b.out === 0)) return <Empty />;

  const b30 = buckets[0].b;

  return (
    <div>
      {/* Frase de contexto baseada nos próximos 30 dias */}
      {(b30.inp > 0 || b30.out > 0) && (
        <div style={{ padding: "10px 12px", background: "var(--surface-2)", borderRadius: 8, marginBottom: 12, fontSize: 12.5, color: "var(--fg-2)", lineHeight: 1.5 }}>
          Nas próximas semanas você deve receber <strong style={{ color: "var(--success)" }}>{fmtBRL(b30.inp)}</strong> e
          pagar <strong style={{ color: "var(--danger)" }}>{fmtBRL(b30.out)}</strong>.
        </div>
      )}
      <div style={{ display: "flex", flexDirection: "column", gap: 2 }}>
        {buckets.map(({ label, b }, i) => (
          <div key={label} style={{ padding: "10px 0", borderBottom: i < 2 ? "1px solid var(--border)" : "none" }}>
            <div style={{ fontSize: 11.5, fontWeight: 600, color: "var(--fg-3)", textTransform: "uppercase", letterSpacing: 0.5, marginBottom: 8 }}>
              Próximos {label}
            </div>
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 8 }}>
              <div>
                <div style={{ fontSize: 10.5, color: "var(--fg-3)", marginBottom: 2 }}>A receber</div>
                <div style={{ fontSize: 13, fontWeight: 600, color: "var(--success)", fontVariantNumeric: "tabular-nums" }}>{fmtBRL(b.inp)}</div>
              </div>
              <div>
                <div style={{ fontSize: 10.5, color: "var(--fg-3)", marginBottom: 2 }}>A pagar</div>
                <div style={{ fontSize: 13, fontWeight: 600, color: "var(--danger)", fontVariantNumeric: "tabular-nums" }}>{fmtBRL(b.out)}</div>
              </div>
              <div>
                <div style={{ fontSize: 10.5, color: "var(--fg-3)", marginBottom: 2 }}>Sobra</div>
                <div style={{ fontSize: 13, fontWeight: 600, fontVariantNumeric: "tabular-nums", color: b.net >= 0 ? "var(--success)" : "var(--danger)" }}>{fmtBRL(b.net)}</div>
              </div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ---------- Avisos de Vencimento (Personal) ----------
function AvisosVencimento({ txns }) {
  const today = new Date(); today.setHours(0, 0, 0, 0);
  const in7 = new Date(today); in7.setDate(in7.getDate() + 7); in7.setHours(23, 59, 59);

  const upcoming = (txns || []).filter(t => {
    const d = parseDate(t.date);
    return (t.status === "PENDENTE" || t.status === "AGENDADO") && d >= today && d <= in7;
  }).sort((a, b) => parseDate(a.date) - parseDate(b.date));

  if (upcoming.length === 0) return null;

  return (
    <div className="card" style={{ padding: 18, borderColor: "var(--warn)" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 14 }}>
        <span style={{ width:28, height:28, borderRadius:8, background:"color-mix(in oklab, var(--warn) 12%, transparent)", color:"var(--warn)", display:"flex", alignItems:"center", justifyContent:"center", flexShrink:0 }}>
          <Icon name="alert" size={14} />
        </span>
        <h3 style={{ margin: 0, fontSize: 14, fontWeight: 600 }}>Vencimentos nos próximos 7 dias</h3>
        <span style={{ marginLeft:"auto", fontSize:11, background:"color-mix(in oklab, var(--warn) 15%, transparent)", color:"var(--warn)", padding:"2px 8px", borderRadius:99, fontWeight:600 }}>
          {upcoming.length}
        </span>
      </div>
      <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
        {upcoming.map(t => {
          const d = parseDate(t.date);
          const diff = Math.floor((d - today) / 86400000);
          const urgColor = diff === 0 ? "var(--danger)" : diff <= 2 ? "var(--warn)" : "var(--fg-3)";
          const dayLabel = diff === 0 ? "Vence hoje" : diff === 1 ? "Vence amanhã" : `Vence em ${diff} dias`;
          return (
            <div key={t.id} style={{ display:"flex", alignItems:"center", gap:10, padding:"8px 10px", background:"var(--surface-1)", borderRadius:8, borderLeft:`3px solid ${urgColor}` }}>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize:13, fontWeight:500, color:"var(--fg-1)", overflow:"hidden", textOverflow:"ellipsis", whiteSpace:"nowrap" }}>{t.desc}</div>
                <div style={{ fontSize: 11, color: urgColor }}>{dayLabel} · {new Date(t.date).toLocaleDateString("pt-BR")}</div>
              </div>
              <div style={{ fontSize:13.5, fontWeight:600, color:"var(--fg-1)", fontVariantNumeric:"tabular-nums", flexShrink:0 }}>{fmtBRL(t.value)}</div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ---------- Contas fixas vs. extras (Personal) ----------
// Fixo = mesmo nome aparecendo em 2+ meses (mais robusto que apenas mês anterior)
function FixasVariaveis({ monthTxns, allTxns }) {
  const norm = (s) => (s || "").toLowerCase().trim();

  // Conta em quantos meses distintos cada nome de lançamento aparece (no histórico inteiro)
  const monthsByDesc = {};
  (allTxns || []).forEach(t => {
    const k = norm(t.desc);
    if (!k) return;
    const d = parseDate(t.date);
    const ym = `${d.getFullYear()}-${d.getMonth()}`;
    if (!monthsByDesc[k]) monthsByDesc[k] = new Set();
    monthsByDesc[k].add(ym);
  });

  const isFixo = (t) => (monthsByDesc[norm(t.desc)] || new Set()).size >= 2;

  const fixas = monthTxns.filter(isFixo);
  const variaveis = monthTxns.filter(t => !isFixo(t));
  const totalFixas = fixas.reduce((s, t) => s + (Number(t.value) || 0), 0);
  const totalVar = variaveis.reduce((s, t) => s + (Number(t.value) || 0), 0);
  const total = totalFixas + totalVar || 1;
  const pctF = Math.round((totalFixas / total) * 100);

  if (monthTxns.length === 0) return <Empty />;

  return (
    <div>
      <div style={{ display: "flex", gap: 10, marginBottom: 12 }}>
        <div style={{ flex:1, padding:"10px 12px", background:"color-mix(in oklab, #7c3aed 8%, var(--surface-1))", borderRadius:8 }}>
          <div style={{ fontSize: 11, color: "var(--fg-3)", marginBottom: 4 }}>Contas fixas</div>
          <div style={{ fontSize: 17, fontWeight: 700, color: "#7c3aed", fontVariantNumeric: "tabular-nums" }}>{fmtBRL(totalFixas)}</div>
          <div style={{ fontSize: 11, color: "var(--fg-3)" }}>{fixas.length} itens · {pctF}%</div>
        </div>
        <div style={{ flex:1, padding:"10px 12px", background:"color-mix(in oklab, var(--info) 8%, var(--surface-1))", borderRadius:8 }}>
          <div style={{ fontSize: 11, color: "var(--fg-3)", marginBottom: 4 }}>Gastos extras</div>
          <div style={{ fontSize: 17, fontWeight: 700, color: "var(--info)", fontVariantNumeric: "tabular-nums" }}>{fmtBRL(totalVar)}</div>
          <div style={{ fontSize: 11, color: "var(--fg-3)" }}>{variaveis.length} itens · {100 - pctF}%</div>
        </div>
      </div>
      <div style={{ height: 8, display: "flex", borderRadius: 999, overflow: "hidden" }}>
        {pctF > 0 && <div style={{ width:`${pctF}%`, background:"#7c3aed", transition:"width .8s" }} />}
        <div style={{ flex: 1, background: "var(--info)" }} />
      </div>
      <div style={{ fontSize: 11.5, color: "var(--fg-2)", marginTop: 8, lineHeight: 1.4 }}>
        Suas contas fixas somam <strong style={{ color: "var(--fg-1)" }}>{fmtBRL(totalFixas)}</strong> no mês.
        <span style={{ color: "var(--fg-3)" }}> Conta fixa = aparece todo mês (em 2 ou mais meses).</span>
      </div>
    </div>
  );
}

// ---------- BUSINESS dashboard ----------
function DashboardBusiness({ ws, setWs, accent, currentMonth, rangeMode, setRangeMode, customRange, setCustomRange }) {
  const period = usePeriod(currentMonth, rangeMode, customRange);
  const { txns, recs, monthTxns, monthRecs, totalOut, totalIn, balance, months } = useData(ws, currentMonth, period);

  const prevOut  = months[months.length - 2]?.out || 0;
  const deltaPct = prevOut ? ((totalOut - prevOut) / prevOut) * 100 : 0;

  // Inadimplência (receitas vencidas)
  const today = new Date(); today.setHours(0, 0, 0, 0);
  const overdueRecs = recs.filter(r => {
    const d = parseDate(r.date);
    return (r.status === "A RECEBER" || r.status === "PENDENTE") && d < today;
  });
  const totalOverdue = overdueRecs.reduce((s, r) => s + (Number(r.value) || 0), 0);

  // Custos por categoria (donut)
  const byCat = {};
  monthTxns.forEach(t => { byCat[t.category || "Outros"] = (byCat[t.category || "Outros"] || 0) + (Number(t.value) || 0); });
  const catData = Object.entries(byCat).map(([label, value]) => ({ label, value })).sort((a, b) => b.value - a.value);

  // Maiores gastos (top 5)
  const top5 = [...monthTxns].sort((a, b) => b.value - a.value).slice(0, 5).map(t => ({ label: t.desc, value: t.value }));

  const replicateLastMonth = () => {
    const prev = new Date(currentMonth.year, currentMonth.month - 1, 1);
    const prevY = prev.getFullYear(), prevM = prev.getMonth();
    const prevTxns = txns.filter(t => { const d = new Date(t.date); return d.getFullYear() === prevY && d.getMonth() === prevM; });
    if (!prevTxns.length) { alert("Nenhum lançamento no mês anterior."); return; }
    if (!confirm(`Replicar ${prevTxns.length} lançamentos de ${prev.toLocaleDateString("pt-BR", { month: "long" })}?`)) return;
    const lastDay = new Date(currentMonth.year, currentMonth.month + 1, 0).getDate();
    const newTxns = prevTxns.map(t => {
      const d = new Date(t.date);
      const newDate = new Date(currentMonth.year, currentMonth.month, Math.min(d.getDate(), lastDay));
      return { ...t, id: crypto.randomUUID(), date: newDate.toISOString().slice(0, 10), status: "PENDENTE" };
    });
    setWs(prev => ({ ...prev, transactions: [...newTxns, ...prev.transactions] }));
  };

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 20 }}>
      <PeriodBar rangeMode={rangeMode} setRangeMode={setRangeMode} customRange={customRange} setCustomRange={setCustomRange} period={period}>
        <button className="btn-ghost" onClick={replicateLastMonth} title="Duplica lançamentos do mês anterior">
          <Icon name="spark" size={13} /> Replicar mês anterior
        </button>
      </PeriodBar>

      {/* KPIs — linguagem simples */}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 14 }}>
        <KPI title="O que entrou" value={fmtBRL(totalIn)} icon="arrowDown" tone="pos"
          sub={`${monthRecs.length} recebimento${monthRecs.length === 1 ? "" : "s"}`} />
        <KPI title="O que saiu" value={fmtBRL(totalOut)} icon="arrowUp" tone="neg"
          sub={deltaPct !== 0 ? `${deltaPct > 0 ? "+" : ""}${deltaPct.toFixed(0)}% vs mês passado` : `${monthTxns.length} lançamento${monthTxns.length === 1 ? "" : "s"}`} />
        <KPI title={balance >= 0 ? "Sobrou" : "Faltou"} value={fmtBRL(Math.abs(balance))} icon="wallet" tone={balance >= 0 ? "pos" : "neg"}
          sub={balance >= 0 ? "Você lucrou neste período" : "Gastou mais do que recebeu"} />
        <KPI title="Estão me devendo" value={fmtBRL(totalOverdue)} icon="alert"
          tone={totalOverdue > 0 ? "neg" : "pos"}
          sub={totalOverdue > 0 ? `${overdueRecs.length} cobrança${overdueRecs.length === 1 ? "" : "s"} em atraso` : "Tudo em dia"} />
      </div>

      {/* Resumo do mês + Cobranças em atraso */}
      <div style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr", gap: 14 }}>
        <div className="card" style={{ padding: 18 }}>
          <h3 style={{ margin: 0, marginBottom: 4, fontSize: 14, fontWeight: 600 }}>Resumo do mês</h3>
          <div style={{ fontSize: 11.5, color: "var(--fg-3)", marginBottom: 14 }}>Para onde foi o dinheiro que entrou</div>
          <DREGerencial totalIn={totalIn} totalOut={totalOut} balance={balance} monthTxns={monthTxns} />
        </div>
        <div className="card" style={{ padding: 18 }}>
          <h3 style={{ margin: 0, marginBottom: 4, fontSize: 14, fontWeight: 600 }}>Cobranças em atraso</h3>
          <div style={{ fontSize: 11.5, color: "var(--fg-3)", marginBottom: 14 }}>Clientes que ainda não pagaram</div>
          <Inadimplencia recs={recs} />
        </div>
      </div>

      {/* Histórico + O que vem por aí */}
      <div style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr", gap: 14 }}>
        <div className="card" style={{ padding: 18 }}>
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 4 }}>
            <h3 style={{ margin: 0, fontSize: 14, fontWeight: 600 }}>Histórico</h3>
            <div style={{ display: "flex", gap: 12, fontSize: 11.5, color: "var(--fg-2)" }}>
              <span style={{ display:"flex", alignItems:"center", gap:5 }}><span style={{ width:8, height:8, borderRadius:2, background:accent }} />entrou</span>
              <span style={{ display:"flex", alignItems:"center", gap:5 }}><span style={{ width:8, height:8, borderRadius:2, background:"var(--fg-1)" }} />saiu</span>
            </div>
          </div>
          <div style={{ fontSize: 11.5, color: "var(--fg-3)", marginBottom: 14 }}>Últimos 6 meses</div>
          <BarsCompare months={months} accent={accent} />
        </div>
        <div className="card" style={{ padding: 18 }}>
          <h3 style={{ margin: 0, marginBottom: 4, fontSize: 14, fontWeight: 600 }}>O que vem por aí</h3>
          <div style={{ fontSize: 11.5, color: "var(--fg-3)", marginBottom: 14 }}>Próximas entradas e saídas</div>
          <FluxoProjetado txns={txns} recs={recs} />
        </div>
      </div>

      {/* Maiores gastos + Onde o dinheiro foi */}
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
        <div className="card" style={{ padding: 18 }}>
          <h3 style={{ margin: 0, marginBottom: 14, fontSize: 14, fontWeight: 600 }}>Maiores gastos do período</h3>
          {top5.length > 0 ? <HBars items={top5} accent={accent} /> : <Empty />}
        </div>
        <div className="card" style={{ padding: 18 }}>
          <h3 style={{ margin: 0, marginBottom: 16, fontSize: 14, fontWeight: 600 }}>Onde o dinheiro foi</h3>
          {catData.length > 0 ? <Donut data={catData} accent={accent} size={170} /> : <Empty />}
        </div>
      </div>
    </div>
  );
}

// ---------- PERSONAL dashboard ----------
function DashboardPersonal({ ws, accent, currentMonth, rangeMode, setRangeMode, customRange, setCustomRange }) {
  const period = usePeriod(currentMonth, rangeMode, customRange);
  const { txns, monthTxns, monthRecs, totalOut, totalIn, balance, months } = useData(ws, currentMonth, period);

  // Contas a pagar — apenas próximos 30 dias (corrige bug de mostrar todos os pendentes)
  const today = new Date(); today.setHours(0, 0, 0, 0);
  const in30 = new Date(today); in30.setDate(in30.getDate() + 30); in30.setHours(23, 59, 59);
  const due30 = (txns || []).filter(t => {
    const d = parseDate(t.date);
    return (t.status === "PENDENTE" || t.status === "AGENDADO") && d >= today && d <= in30;
  });
  const due30Total = due30.reduce((s, t) => s + (Number(t.value) || 0), 0);

  // Gastos por categoria — onde o dinheiro foi
  const byCat = {};
  monthTxns.forEach(t => {
    const k = t.category || "Sem categoria";
    byCat[k] = (byCat[k] || 0) + (Number(t.value) || 0);
  });
  const catData = Object.entries(byCat).map(([label, value]) => ({ label, value })).sort((a, b) => b.value - a.value);
  const catTotal = catData.reduce((s, c) => s + c.value, 0) || 1;

  // Maiores gastos (top 5)
  const top5 = [...monthTxns].sort((a, b) => b.value - a.value).slice(0, 5).map(t => ({ label: t.desc, value: t.value }));

  // Top subcategorias do período (Uber, Mercado, Aluguel...) pra preencher
  // o card "Onde foi o dinheiro" com destaques específicos.
  const subAgg = {};
  monthTxns.forEach(t => {
    const sub = (t.subcategory || "").trim();
    if (!sub) return;
    if (!subAgg[sub]) subAgg[sub] = { total: 0, count: 0, category: t.category || "" };
    subAgg[sub].total += Number(t.value) || 0;
    subAgg[sub].count += 1;
  });
  const topSubs = Object.entries(subAgg)
    .map(([name, d]) => ({ name, total: d.total, count: d.count, category: d.category }))
    .sort((a, b) => b.total - a.total)
    .slice(0, 6);

  // Como está indo o ano (saldo acumulado nos últimos 6 meses)
  let acc = 0;
  const cumTrend = months.map(m => { acc += m.in - m.out; return { label: m.label, v: acc }; });

  // Paleta decorativa pra fatias do donut — mantida em hex (não são cores de status)
  const catColors = ["#7c3aed", "var(--info)", "#0fbb6b", "#f59e0b", "#ef4444", "#14b8a6", "#ec4899", "#84cc16"];

  // Orçamento (usa monthlyGoal como teto)
  const budget = ws.monthlyGoal || 0;
  const budgetPct = budget > 0 ? Math.min(100, (totalOut / budget) * 100) : 0;
  const budgetColor = budgetPct > 100 ? "var(--danger)" : budgetPct > 80 ? "var(--warn)" : accent;

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 20 }}>
      <PeriodBar rangeMode={rangeMode} setRangeMode={setRangeMode} customRange={customRange} setCustomRange={setCustomRange} period={period} />

      {/* KPIs — linguagem doméstica */}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 14 }}>
        <KPI title="Quanto entrou"      value={fmtBRL(totalIn)}    icon="arrowDown" tone="pos"
          sub={`${monthRecs.length} recebimento${monthRecs.length === 1 ? "" : "s"}`} />
        <KPI title="Quanto você gastou" value={fmtBRL(totalOut)}   icon="arrowUp"   tone="neg"
          sub={`${monthTxns.length} lançamento${monthTxns.length === 1 ? "" : "s"}`} />
        <KPI title={balance >= 0 ? "Sobrou este mês" : "Faltou este mês"} value={fmtBRL(Math.abs(balance))} icon="wallet" tone={balance >= 0 ? "pos" : "neg"}
          sub={balance >= 0 ? "Você guardou esse valor" : "Gastou mais do que recebeu"} />
        <KPI title="Contas a pagar"     value={fmtBRL(due30Total)} icon="calendar"  tone="warn"
          sub={`${due30.length} nos próximos 30 dias`} />
      </div>

      {/* Avisos de vencimento (aparece só se houver itens) */}
      <AvisosVencimento txns={txns} />

      {/* Orçamento mensal — sempre fixo em cima do "Onde foi o dinheiro" no dashboard pessoal */}
      {budget > 0 ? (
        <div className="card" style={{ padding: 18 }}>
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 10 }}>
            <div>
              <div style={{ fontSize: 12, color: "var(--fg-3)", textTransform: "uppercase", letterSpacing: 0.6, marginBottom: 4 }}>Orçamento mensal</div>
              <div style={{ fontSize: 20, fontWeight: 600, color: "var(--fg-1)", fontVariantNumeric: "tabular-nums", overflow:"hidden", textOverflow:"ellipsis", whiteSpace:"nowrap" }}>
                {fmtBRL(totalOut)} <span style={{ color: "var(--fg-3)", fontWeight: 400, fontSize: 14 }}>/ {fmtBRL(budget)}</span>
              </div>
            </div>
            <div style={{ textAlign: "right" }}>
              <div style={{ fontSize: 28, fontWeight: 600, color: budgetColor, fontVariantNumeric: "tabular-nums" }}>
                {budgetPct.toFixed(0)}%
              </div>
              <div style={{ fontSize: 11, color: "var(--fg-3)" }}>
                {budget - totalOut >= 0 ? `Disponível: ${fmtBRL(budget - totalOut)}` : `Excedido: ${fmtBRL(totalOut - budget)}`}
              </div>
            </div>
          </div>
          <div style={{ height: 10, background: "var(--surface-2)", borderRadius: 999, overflow: "hidden" }}>
            <div style={{ width:`${Math.min(100, budgetPct)}%`, height:"100%", borderRadius:999, transition:"width .8s cubic-bezier(.2,.8,.2,1)", background: budgetColor }} />
          </div>
        </div>
      ) : (
        // Estado vazio — meta ainda não configurada
        <div className="card" style={{ padding: 18, display: "flex", alignItems: "center", gap: 16 }}>
          <div style={{ width: 44, height: 44, borderRadius: 12, background: `color-mix(in oklab, ${accent} 10%, transparent)`, color: accent, display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }}>
            <Icon name="target" size={22} />
          </div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 12, color: "var(--fg-3)", textTransform: "uppercase", letterSpacing: 0.6, marginBottom: 3 }}>Orçamento mensal</div>
            <div style={{ fontSize: 14, fontWeight: 600, color: "var(--fg-1)", marginBottom: 2 }}>Defina sua meta de gasto pra acompanhar o quanto sobra do mês</div>
            <div style={{ fontSize: 11.5, color: "var(--fg-3)" }}>Ajuda a saber se está dentro do limite que você se propôs.</div>
          </div>
          <button
            className="btn-ghost"
            onClick={() => alert("Vá em Configurações → Meta de gasto mensal pra definir o valor.")}
            style={{ flexShrink: 0, fontSize: 12 }}
          >
            <Icon name="edit" size={12} /> Definir meta
          </button>
        </div>
      )}

      {/* Onde foi o dinheiro — donut + categorias com barras + top destaques */}
      {catData.length > 0 && (
        <div className="card" style={{ padding: 18 }}>
          <h3 style={{ margin: 0, marginBottom: 4, fontSize: 14, fontWeight: 600 }}>Onde foi o dinheiro</h3>
          <div style={{ fontSize: 11.5, color: "var(--fg-3)", marginBottom: 14 }}>Seus gastos agrupados por categoria neste período</div>
          <div style={{ display: "grid", gridTemplateColumns: "auto minmax(280px, 1.1fr) minmax(220px, 1fr)", gap: 24, alignItems: "start" }}>

            {/* Coluna 1: Donut */}
            <div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 10 }}>
              <Donut data={catData} palette={catColors} size={170} showLegend={false} />
              <div style={{ textAlign: "center" }}>
                <div style={{ fontSize: 11, color: "var(--fg-3)", textTransform: "uppercase", letterSpacing: 0.5 }}>Total no período</div>
                <div style={{ fontSize: 16, fontWeight: 600, color: "var(--fg-1)", fontVariantNumeric: "tabular-nums", marginTop: 2 }}>{fmtBRL(catTotal)}</div>
              </div>
            </div>

            {/* Coluna 2: Categorias com barras inline */}
            <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
              {catData.slice(0, 6).map((c, i) => {
                const color = catColors[i % catColors.length];
                const pct = (c.value / catTotal) * 100;
                return (
                  <div key={c.label}>
                    <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 4 }}>
                      <span style={{ width: 10, height: 10, borderRadius: 3, background: color, flexShrink: 0 }} />
                      <span style={{ flex: 1, fontSize: 12.5, color: "var(--fg-1)", fontWeight: 500, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{c.label}</span>
                      <span style={{ fontSize: 11, color: "var(--fg-3)", fontVariantNumeric: "tabular-nums" }}>{pct.toFixed(0)}%</span>
                      <span style={{ fontSize: 12.5, color: "var(--fg-1)", fontVariantNumeric: "tabular-nums", fontWeight: 600 }}>{fmtBRL(c.value)}</span>
                    </div>
                    <div style={{ height: 4, background: "var(--surface-2)", borderRadius: 999, overflow: "hidden" }}>
                      <div style={{ width: `${pct}%`, height: "100%", background: color, borderRadius: 999, transition: "width .8s cubic-bezier(.2,.8,.2,1)" }} />
                    </div>
                  </div>
                );
              })}
              {catData.length > 6 && (
                <div style={{ fontSize: 11, color: "var(--fg-3)" }}>+ {catData.length - 6} outras categorias</div>
              )}
            </div>

            {/* Coluna 3: Top destaques específicos (subcategorias) */}
            <div style={{ borderLeft: "1px solid var(--border)", paddingLeft: 18, minWidth: 0 }}>
              <div style={{ fontSize: 11, color: "var(--fg-3)", textTransform: "uppercase", letterSpacing: 0.6, fontWeight: 500, marginBottom: 10 }}>
                Maiores destaques
              </div>
              {topSubs.length > 0 ? (
                <div style={{ display: "flex", flexDirection: "column", gap: 9 }}>
                  {topSubs.map((s, i) => {
                    const subPct = (s.total / catTotal) * 100;
                    return (
                      <div key={s.name} style={{ display: "flex", alignItems: "center", gap: 8 }}>
                        <span style={{ width: 22, height: 22, borderRadius: 6, background: "var(--surface-2)", color: "var(--fg-2)", display: "flex", alignItems: "center", justifyContent: "center", fontSize: 10, fontWeight: 700, flexShrink: 0, fontVariantNumeric: "tabular-nums" }}>
                          {i + 1}
                        </span>
                        <div style={{ flex: 1, minWidth: 0 }}>
                          <div style={{ fontSize: 12.5, color: "var(--fg-1)", fontWeight: 500, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{s.name}</div>
                          <div style={{ fontSize: 10.5, color: "var(--fg-3)" }}>
                            {s.count}× · {subPct.toFixed(0)}% do total
                          </div>
                        </div>
                        <span style={{ fontSize: 12.5, color: "var(--fg-1)", fontVariantNumeric: "tabular-nums", fontWeight: 600 }}>{fmtBRL(s.total)}</span>
                      </div>
                    );
                  })}
                </div>
              ) : (
                <div style={{ fontSize: 11.5, color: "var(--fg-3)", lineHeight: 1.5, paddingTop: 6 }}>
                  Sem subcategorias detectadas. Ao importar uma fatura, a IA detecta nomes específicos (Uber, Mercado, Aluguel) que aparecem aqui.
                </div>
              )}
            </div>

          </div>
        </div>
      )}

      {/* Renda × Gastos + Contas fixas vs. extras */}
      <div style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr", gap: 14 }}>
        <div className="card" style={{ padding: 18 }}>
          <div style={{ display:"flex", justifyContent:"space-between", alignItems:"center", marginBottom:4 }}>
            <h3 style={{ margin: 0, fontSize: 14, fontWeight: 600 }}>Renda × Gastos</h3>
            <div style={{ display:"flex", gap:12, fontSize:11.5, color:"var(--fg-2)" }}>
              <span style={{ display:"flex", alignItems:"center", gap:5 }}><span style={{ width:8, height:8, borderRadius:2, background:accent }} />renda</span>
              <span style={{ display:"flex", alignItems:"center", gap:5 }}><span style={{ width:8, height:8, borderRadius:2, background:"var(--fg-1)" }} />gasto</span>
            </div>
          </div>
          <div style={{ fontSize: 11.5, color: "var(--fg-3)", marginBottom: 14 }}>Últimos 6 meses</div>
          <BarsCompare months={months} accent={accent} />
        </div>
        <div className="card" style={{ padding: 18 }}>
          <h3 style={{ margin: 0, marginBottom: 4, fontSize: 14, fontWeight: 600 }}>Contas fixas vs. extras</h3>
          <div style={{ fontSize: 11.5, color: "var(--fg-3)", marginBottom: 14 }}>O que se repete todo mês × o que é eventual</div>
          <FixasVariaveis monthTxns={monthTxns} allTxns={txns} />
        </div>
      </div>

      {/* Maiores gastos + Como está indo o ano */}
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
        <div className="card" style={{ padding: 18 }}>
          <h3 style={{ margin: 0, marginBottom: 14, fontSize: 14, fontWeight: 600 }}>Maiores gastos do período</h3>
          {top5.length > 0 ? <HBars items={top5} accent={accent} /> : <Empty />}
        </div>
        <div className="card" style={{ padding: 18 }}>
          <h3 style={{ margin: 0, marginBottom: 4, fontSize: 14, fontWeight: 600 }}>Como está indo o ano</h3>
          <div style={{ fontSize: 11.5, color: "var(--fg-3)", marginBottom: 14 }}>Saldo acumulado mês a mês</div>
          <AreaTrend points={cumTrend} accent={accent} height={150} />
        </div>
      </div>
    </div>
  );
}

window.Dashboard = Dashboard;
