/* ============================================================
   EDUCARE — Cobrança POR ATENDIMENTO REALIZADO
   Cada sessão marcada como "realizada" gera uma cobrança (valor do
   cadastro, editável por sessão). Faltas entram como R$ 0,00 (mantêm
   frequência, não cobram). NÃO há renovação/mensalidade automática.
   Fonte única de dados; sincroniza com o Financeiro.
   Chave de unicidade: pid + data (impede lançamento duplicado).
   ============================================================ */
(function () {
  const { useState } = React;
  const Icon = window.Icon;

  const KEY = "educare-charges";
  const OLD_KEY = "educare-billing"; // modelo antigo (mensalidade fixa) — será removido na migração
  const MON_FULL = ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"];
  const pad2 = (n) => String(n).padStart(2, "0");
  const isoOf = (dt) => `${dt.getFullYear()}-${pad2(dt.getMonth() + 1)}-${pad2(dt.getDate())}`;
  const D = (iso) => { const [y, m, d] = String(iso).split("-").map(Number); return new Date(y, (m || 1) - 1, d || 1); };
  const todayISO = () => (window.todayISO ? window.todayISO() : isoOf(new Date()));
  const addDays = (iso, n) => { const d = D(iso); d.setDate(d.getDate() + n); return isoOf(d); };
  const fmtDMY = (iso) => { const [y, m, d] = iso.split("-"); return `${d}/${m}/${y}`; };
  const fmtDM = (iso) => { const [, m, d] = iso.split("-"); return `${d}/${m}`; };
  const brl = (v) => "R$ " + (Math.round(v || 0)).toLocaleString("pt-BR");
  const feeOf = (p) => Math.max(0, Math.round(Number(p && p.fee)) || 0);
  const who = () => (window.__USER && window.__USER.name) || "Profissional";
  const cid = (pid, iso) => pid + "|" + iso;                          // chave de unicidade
  const daysBetween = (isoA, isoB) => Math.round((D(isoB) - D(isoA)) / 86400000);

  // ---- Períodos (lente semanal/mensal) ----
  const mondayOf = (iso) => { const d = D(iso); const off = (d.getDay() + 6) % 7; return addDays(iso, -off); };
  const monthKeyOf = (iso) => iso.slice(0, 7);
  function periodKeyOf(type, iso) { return type === "semana" ? mondayOf(iso) : monthKeyOf(iso); }
  function currentKey(type) { return periodKeyOf(type, todayISO()); }
  function periodRange(type, key) {
    if (type === "semana") return { start: key, end: addDays(key, 6) };
    const [y, m] = key.split("-").map(Number);
    return { start: `${y}-${pad2(m)}-01`, end: isoOf(new Date(y, m, 0)) };
  }
  function periodLabel(type, key) {
    if (type === "semana") { const { start, end } = periodRange(type, key); return `Semana de ${fmtDM(start)} a ${fmtDMY(end)}`; }
    const [y, m] = key.split("-").map(Number); return `${MON_FULL[m - 1].toLowerCase()} de ${y}`;
  }
  function monthLabel(ym) { const [y, m] = ym.split("-").map(Number); return `${MON_FULL[m - 1]} ${y}`; }
  function prevKey(type, key) { return type === "semana" ? addDays(key, -7) : periodKeyOf("mes", (function () { const [y, m] = key.split("-").map(Number); return isoOf(new Date(y, m - 2, 1)); })()); }
  function nextKey(type, key) { return type === "semana" ? addDays(key, 7) : periodKeyOf("mes", (function () { const [y, m] = key.split("-").map(Number); return isoOf(new Date(y, m, 1)); })()); }
  function keyIsPast(type, key) { return periodRange(type, key).end < todayISO(); }
  // Vencimento: mensal = dia 5 do mês; semanal = domingo (fim da semana).
  function dueOf(type, key) { if (type === "semana") return periodRange(type, key).end; const [y, m] = key.split("-").map(Number); return `${y}-${pad2(m)}-05`; }

  // ---- Store ----
  /* As cobranças vêm do Supabase (app/db.jsx), hidratadas no boot por
     data.jsx. O mapa em memória mantém a mesma forma de antes. */
  function load() {
    const vindas = window.__COBRANCAS_DO_BANCO;
    if (!Array.isArray(vindas)) return null;
    const charges = {};
    vindas.forEach((c) => { charges[cid(c.pid, c.dateISO)] = c; });
    return { charges, v: SEED_V };
  }
  /* Gravação por cobrança: o upsert usa (paciente, data) como chave. */
  function avisarFalha(e, acao) {
    console.error("[Billing] " + acao + " falhou:", e);
    window.dispatchEvent(new CustomEvent("educare-db-erro", {
      detail: (e && e.message) || ("Falha ao " + acao + " a cobrança."),
    }));
  }
  function salvarUma(c) {
    if (!window.EducareDB) return;
    window.EducareDB.salvarCobranca(c).catch((e) => avisarFalha(e, "salvar"));
  }
  function apagarUma(pid, iso) {
    if (!window.EducareDB) return;
    window.EducareDB.apagarCobranca(pid, iso).catch((e) => avisarFalha(e, "remover"));
  }
  function save() { /* não há mais estado global a gravar: cada cobrança vai sozinha */ }
  let state = load() || { charges: {}, v: SEED_V };

  // ---- Migração: remove o modelo antigo (mensalidade fixa) que gerava duplicatas ----
  function migrateFromOld() {
    let removed = false;
    try { if (localStorage.getItem(OLD_KEY)) { localStorage.removeItem(OLD_KEY); removed = true; } } catch (e) { /* */ }
    return removed;
  }

  // ---- Seed demonstrativo (por atendimento) na primeira vez ----
  function seed() {
    const ym = todayISO().slice(0, 7); const [y, m] = ym.split("-").map(Number);
    const prevYM = isoOf(new Date(y, m - 2, 1)).slice(0, 7);
    const prev2YM = isoOf(new Date(y, m - 3, 1)).slice(0, 7);
    const charges = {};
    const byId = (id) => (window.PATIENTS || []).find((p) => p.id === id);
    const put = (pid, iso, value, kind, paid, method, payDate) => {
      if (!byId(pid)) return;
      const c = { pid, dateISO: iso, value: kind === "falta" ? 0 : value, kind: kind || "realizado", paid: paid || 0, method: method || "", payDate: payDate || "", payWho: paid ? "Sistema" : "", log: [] };
      if (paid) c.log.push({ ts: Date.now(), who: "Sistema", action: "pagamento", amount: paid, method: method || "" });
      charges[cid(pid, iso)] = c;
    };
    const dim = (yy, mm) => new Date(yy, mm, 0).getDate();
    const someDays = (yy, mm, arr) => arr.map((d) => `${yy}-${pad2(mm)}-${pad2(Math.min(d, dim(yy, mm)))}`);
    const dpay = (dd) => `${y}-${pad2(m)}-${pad2(dd)}`;
    // Helena (400): 2 sessões no mês, TOTALMENTE PAGAS (card verde "Pago")
    someDays(y, m, [3, 10]).forEach((iso) => put("helena", iso, 400, "realizado", 400, "Pix", dpay(15)));
    // Théo (160): 3 sessões no mês, TOTALMENTE PAGAS
    someDays(y, m, [1, 8, 15]).forEach((iso) => put("theo", iso, 160, "realizado", 160, "Dinheiro", dpay(20)));
    // Laura (350): 2 sessões no mês em aberto + 1 falta; junho em atraso
    someDays(y, m, [2, 9]).forEach((iso) => put("laura", iso, 350, "realizado"));
    put("laura", `${y}-${pad2(m)}-16`, 0, "falta");
    { const [yy, mm] = prevYM.split("-").map(Number); someDays(yy, mm, [4, 11]).forEach((iso) => put("laura", iso, 350, "realizado")); }
    // Miguel (480): 3 meses acumulados em aberto
    [ym, prevYM, prev2YM].forEach((pm) => { const [yy, mm] = pm.split("-").map(Number); someDays(yy, mm, [6, 20]).forEach((iso) => put("miguel", iso, 480, "realizado")); });
    return { charges, v: SEED_V };
  }

  const SEED_V = 2; // bump força recriar o demo coerente (com pacientes pagos)
  const migratedOld = migrateFromOld();
  /* seed() existia só para popular a demonstração. Com base real ele não roda:
     as cobranças chegam do banco na hidratação. */
  void seed;

  const remaining = (c) => c.kind === "falta" ? 0 : Math.max(0, (c.value || 0) - (c.paid || 0));
  const listCharges = () => Object.keys(state.charges).map((k) => state.charges[k]);
  const chargesOfPatient = (pid) => listCharges().filter((c) => c.pid === pid).sort((a, b) => a.dateISO.localeCompare(b.dateISO));
  function chargesInPeriod(pid, type, key) { const { start, end } = periodRange(type, key); return chargesOfPatient(pid).filter((c) => c.dateISO >= start && c.dateISO <= end); }

  function periodInfo(pid, type, key) {
    const cs = chargesInPeriod(pid, type, key);
    const realized = cs.filter((c) => c.kind !== "falta");
    const total = realized.reduce((s, c) => s + (c.value || 0), 0);
    const paid = realized.reduce((s, c) => s + Math.min(c.paid || 0, c.value || 0), 0);
    const rem = Math.max(0, total - paid);
    const faltas = cs.filter((c) => c.kind === "falta").length;
    let status = "none";
    if (total > 0) {
      if (rem <= 0) status = "pago";
      else if (paid > 0) status = "parcial";
      else status = keyIsPast(type, key) || dueOf(type, key) < todayISO() ? "atrasado" : "aberto";
    }
    return { count: cs.length, atendimentos: cs, realizadas: realized.length, faltas, total, paid, rem, status, due: dueOf(type, key) };
  }

  // Pendência acumulada de períodos ANTERIORES (do mesmo tipo de lente).
  function priorOpen(pid, type, key) {
    const { start } = periodRange(type, key);
    const cs = chargesOfPatient(pid).filter((c) => c.dateISO < start);
    const rem = cs.reduce((s, c) => s + remaining(c), 0);
    // rótulo do período anterior em aberto mais recente
    let label = "", openKeys = [];
    cs.forEach((c) => { if (remaining(c) > 0) { const k = periodKeyOf(type, c.dateISO); if (!openKeys.includes(k)) openKeys.push(k); } });
    if (openKeys.length === 1) label = periodShort(type, openKeys[0]);
    else if (openKeys.length > 1) label = "meses anteriores";
    return { rem, label, count: openKeys.length };
  }
  function periodShort(type, key) { if (type === "semana") return "semana de " + fmtDM(key); const [y, m] = key.split("-").map(Number); return `${MON_FULL[m - 1].toLowerCase()}`; }

  // Histórico mensal do paciente (agrega por mês, mais recente primeiro).
  function history(pid) {
    const cs = chargesOfPatient(pid); const byMonth = {};
    cs.forEach((c) => { const ym = monthKeyOf(c.dateISO); (byMonth[ym] = byMonth[ym] || []).push(c); });
    return Object.keys(byMonth).sort((a, b) => b.localeCompare(a)).map((ym) => {
      const arr = byMonth[ym]; const realized = arr.filter((c) => c.kind !== "falta");
      const total = realized.reduce((s, c) => s + c.value, 0);
      const paid = realized.reduce((s, c) => s + Math.min(c.paid || 0, c.value), 0);
      const rem = Math.max(0, total - paid);
      const due = dueOf("mes", ym);
      const payDates = realized.filter((c) => c.payDate).map((c) => c.payDate).sort();
      const payDate = payDates.length ? payDates[payDates.length - 1] : "";
      const method = (realized.find((c) => c.method) || {}).method || "";
      let status = "none";
      if (total > 0) status = rem <= 0 ? "pago" : paid > 0 ? "parcial" : (due < todayISO() ? "atrasado" : "aberto");
      const overdueDays = status === "atrasado" || (status === "parcial" && due < todayISO()) ? Math.max(0, daysBetween(due, todayISO())) : 0;
      return { ym, total, paid, rem, status, due, payDate, method, overdueDays, count: arr.length };
    });
  }

  function logAppend(c, action, amount, method) { c.log = c.log || []; c.log.push({ ts: Date.now(), who: who(), action, amount: Math.round(amount) || 0, method: method || "" }); }

  // Registra/edita um atendimento (cobrança). kind: "realizado" | "falta".
  // Retorna { warnPaidPeriod } se caiu num período que já estava quitado.
  function recordSession(pid, iso, value, kind, type, key) {
    const id = cid(pid, iso);
    const wasPaidPeriod = (function () { if (!type || !key) return false; const info = periodInfo(pid, type, key); return info.total > 0 && info.rem <= 0; })();
    const existing = state.charges[id];
    const c = existing || { pid, dateISO: iso, value: 0, kind: "realizado", paid: 0, method: "", payDate: "", payWho: "", log: [] };
    c.kind = kind === "falta" ? "falta" : "realizado";
    c.value = c.kind === "falta" ? 0 : Math.max(0, Math.round(value) || 0);
    if (c.paid > c.value) c.paid = c.value;
    logAppend(c, existing ? "editar" : "lançar", c.value, "");
    state.charges[id] = c; salvarUma(c);
    return { warnPaidPeriod: wasPaidPeriod && c.kind !== "falta" };
  }
  function removeSession(pid, iso) { delete state.charges[cid(pid, iso)]; apagarUma(pid, iso); }

  // Quita um período (valor total ou parcial), abatendo do atendimento mais ANTIGO primeiro.
  function payPeriod(pid, type, key, amount, method) {
    const cs = chargesInPeriod(pid, type, key).filter((c) => remaining(c) > 0).sort((a, b) => a.dateISO.localeCompare(b.dateISO));
    let left = amount == null ? cs.reduce((s, c) => s + remaining(c), 0) : Math.max(0, Math.round(amount) || 0);
    const total = Math.min(left, cs.reduce((s, c) => s + remaining(c), 0));
    if (total <= 0) return;
    for (const c of cs) { if (left <= 0) break; const take = Math.min(remaining(c), left); c.paid = (c.paid || 0) + take; c.method = method || c.method; c.payDate = todayISO(); c.payWho = who(); logAppend(c, "pagamento", take, method); left -= take; }
    cs.forEach(salvarUma);
    // Billing é a fonte única: o Financeiro DERIVA as receitas destas cobranças
    // (não gravamos recebimento separado — era o que gerava as duplicatas).
  }
  function unpayPeriod(pid, type, key) {
    chargesInPeriod(pid, type, key).forEach((c) => { if ((c.paid || 0) > 0) { logAppend(c, "estorno", -(c.paid || 0), ""); c.paid = 0; c.payDate = ""; c.method = ""; c.payWho = ""; salvarUma(c); } });
  }

  // ---- Totais e linhas DERIVADOS (billing é a fonte única do Financeiro) ----
  const ymShort = (ym) => MON_FULL[+ym.split("-")[1] - 1].slice(0, 3).toLowerCase();
  function receita() { return listCharges().reduce((s, c) => s + Math.min(c.paid || 0, c.value || 0), 0); }
  function emAberto() { return listCharges().reduce((s, c) => s + remaining(c), 0); }
  function atrasadoTotal() { return listCharges().reduce((s, c) => s + (dueOf("mes", monthKeyOf(c.dateISO)) < todayISO() ? remaining(c) : 0), 0); }
  function openMonthsList(pid) { const by = {}; chargesOfPatient(pid).forEach((c) => { const r = remaining(c); if (r > 0) { const ym = monthKeyOf(c.dateISO); by[ym] = (by[ym] || 0) + r; } }); return Object.keys(by).sort((a, b) => b.localeCompare(a)).map((ym) => ({ ym, rem: by[ym] })); }
  // Linhas agregadas por paciente+mês para a tabela do Financeiro.
  function ledgerLines() {
    const byKey = {};
    listCharges().forEach((c) => { const ym = monthKeyOf(c.dateISO); const k = c.pid + "|" + ym; (byKey[k] = byKey[k] || []).push(c); });
    return Object.keys(byKey).map((k) => {
      const arr = byKey[k]; const pid = k.split("|")[0], ym = k.split("|")[1];
      const realized = arr.filter((c) => c.kind !== "falta");
      const total = realized.reduce((s, c) => s + c.value, 0);
      const paid = realized.reduce((s, c) => s + Math.min(c.paid || 0, c.value), 0);
      const rem = Math.max(0, total - paid);
      const due = dueOf("mes", ym);
      const payDates = realized.filter((c) => c.payDate).map((c) => c.payDate).sort();
      const payDate = payDates.length ? payDates[payDates.length - 1] : "";
      const method = (realized.find((c) => c.method) || {}).method || "";
      let status = "none"; if (total > 0) status = rem <= 0 ? "pago" : paid > 0 ? "parcial" : (due < todayISO() ? "atrasado" : "aberto");
      return { pid, ym, date: payDate || due, desc: `${monthLabel(ym)} · ${arr.length} ${arr.length === 1 ? "atendimento" : "atendimentos"}`, value: total, paid, rem, status, method, count: arr.length };
    });
  }

  // ---- Migração/consolidação do Financeiro (duplicatas do modelo antigo) ----
  function migrateFinance() {
    const pays = window.PAYMENTS || [];
    let report = null;
    try {
      if (!localStorage.getItem("educare-fin-migrated")) {
        const dup = pays.filter((p) => p._user && p.pid); // receitas atreladas a paciente = agora derivadas do billing
        // conflitos: mesmo paciente+período com valores divergentes → sinalizar (não descartar)
        const vk = {}; let conflicts = 0;
        dup.forEach((p) => { const base = (p.desc || "").replace(/\s*·.*$/, ""); const k = p.pid + "|" + base; if (vk[k] != null && vk[k] !== p.value) conflicts++; else vk[k] = p.value; });
        try { const prev = JSON.parse(localStorage.getItem("educare-recebimentos-arquivo") || "[]"); localStorage.setItem("educare-recebimentos-arquivo", JSON.stringify(prev.concat(dup))); } catch (e) { /* */ }
        try { localStorage.setItem("educare-recebimentos", JSON.stringify(pays.filter((p) => p._user && !p.pid))); } catch (e) { /* */ }
        localStorage.setItem("educare-fin-migrated", "1");
        report = { removed: dup.length, conflicts };
      }
    } catch (e) { /* */ }
    // Toda carga: remove receitas atreladas a paciente do array em memória (evita dupla contagem).
    const keep = pays.filter((p) => !p.pid);
    window.PAYMENTS.length = 0; keep.forEach((p) => window.PAYMENTS.push(p));
    return report;
  }
  const finMigration = migrateFinance();

  /* Chamado pelo boot depois que data.jsx hidrata window.__COBRANCAS_DO_BANCO:
     billing.jsx é carregado antes dos dados chegarem, então precisa reler. */
  function recarregar() { state = load() || { charges: {}, v: SEED_V }; }

  window.Billing = {
    recarregar,
    todayISO, currentKey, periodLabel, periodRange, prevKey, nextKey, keyIsPast, monthLabel, ymShort, brl, fmtDMY, feeOf, monthKeyOf,
    periodInfo, priorOpen, history, chargesInPeriod, recordSession, removeSession, payPeriod, unpayPeriod, remaining,
    receita, emAberto, atrasadoTotal, openMonthsList, ledgerLines, dueOf,
    migratedOld, finMigration,
  };

  const STMETA = {
    pago: { l: "Pago", col: "#16A34A", bg: "rgba(22,163,74,.12)" },
    aberto: { l: "Em aberto", col: "var(--text-2)", bg: "var(--surface-2)" },
    atrasado: { l: "Atrasado", col: "#DC2626", bg: "rgba(220,38,38,.10)" },
    parcial: { l: "Parcial", col: "#D97706", bg: "rgba(217,119,6,.12)" },
    none: { l: "Sem cobrança", col: "var(--text-3)", bg: "var(--surface-2)" },
  };
  const stBadge = (st, rem) => {
    const m = STMETA[st] || STMETA.none;
    const label = st === "parcial" ? `Parcial • falta ${brl(rem)}` : m.l;
    return <span style={{ fontSize: 11, fontWeight: 800, color: st === "aberto" || st === "none" ? "var(--text-2)" : "#fff", background: st === "aberto" || st === "none" ? "var(--surface-3)" : m.col, borderRadius: 20, padding: "2px 9px" }}>{label}</span>;
  };

  window.BillingUI = { STMETA, stBadge };

  // ---- Integração: registrar atendimento (fluxo existente) gera a cobrança ----
  // A cobrança só nasce de um atendimento realizado, com o valor do cadastro.
  if (window.addAtendimento && !window.addAtendimento.__billingWrapped) {
    const orig = window.addAtendimento;
    const wrapped = function (data) {
      const rec = orig(data);
      try {
        if (rec && rec.pid && rec.dateIso && (rec.status || "realizado") === "realizado") {
          const p = (window.PATIENTS || []).find((x) => x.id === rec.pid);
          recordSession(rec.pid, rec.dateIso, feeOf(p), "realizado");
        }
      } catch (e) { /* */ }
      return rec;
    };
    wrapped.__billingWrapped = true;
    window.addAtendimento = wrapped;
  }

  // ---- Painel lateral "Pagamentos do mês" (lista de pacientes; toque abre o detalhe) ----
  function toneOpen(nMonths) {
    if (nMonths <= 0) return { col: "#16A34A", bd: "rgba(22,163,74,.35)", bg: "rgba(22,163,74,.08)" };
    if (nMonths === 1) return { col: "#DC2626", bd: "rgba(220,38,38,.30)", bg: "rgba(220,38,38,.06)" };
    if (nMonths === 2) return { col: "#B91C1C", bd: "rgba(185,28,28,.45)", bg: "rgba(185,28,28,.12)" };
    return { col: "#7F1D1D", bd: "rgba(127,29,29,.6)", bg: "rgba(127,29,29,.16)" };
  }
  function PagamentosPanel({ onNavigate }) {
    const [refYM, setRefYM] = useState(monthKeyOf(todayISO()));
    const [, force] = useState(0); const refresh = () => force((n) => n + 1);
    const [detail, setDetail] = useState(null);
    const [toast, setToast] = useState(null);
    React.useEffect(() => { if (!toast) return; const id = setTimeout(() => setToast(null), 4000); return () => clearTimeout(id); }, [toast]);
    const isCur = refYM === monthKeyOf(todayISO());
    const patients = (window.PATIENTS || []).filter((p) => chargesOfPatient(p.id).length > 0);
    let recebido = 0, aberto = 0, comPend = 0;
    const rows = patients.map((p) => {
      const info = periodInfo(p.id, "mes", refYM);
      const openM = openMonthsList(p.id).filter((m) => m.ym <= refYM);
      const tot = openM.reduce((s, m) => s + m.rem, 0);
      // mês em aberto mais ANTIGO (menor ym) = maior tempo de atraso
      const oldestOpen = openM.length ? openM.reduce((min, m) => (m.ym < min ? m.ym : min), openM[0].ym) : "9999-99";
      recebido += info.paid; aberto += tot; if (tot > 0) comPend++;
      return { p, info, openM, tot, oldestOpen };
    });
    // Em aberto/atrasado no topo (mais antigo primeiro), depois em dia; alfabético dentro de cada grupo.
    const cmpNome = (a, b) => a.p.name.localeCompare(b.p.name, "pt-BR", { sensitivity: "base" });
    const pend = rows.filter((r) => r.tot > 0).sort((a, b) => (a.oldestOpen < b.oldestOpen ? -1 : a.oldestOpen > b.oldestOpen ? 1 : cmpNome(a, b)));
    const emDia = rows.filter((r) => r.tot <= 0).sort(cmpNome);
    const ordered = pend.concat(emDia);
    const stepM = (dir) => setRefYM((ym) => { const [y, m] = ym.split("-").map(Number); const d = new Date(y, m - 1 + dir, 1); return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}`; });

    return (
      <div className="card">
        <div className="card-title">
          <span className="ct"><Icon name="wallet" size={18} />Pagamentos do mês</span>
          <button className="link" onClick={() => onNavigate("agenda")}>Ver agenda ›</button>
        </div>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 6, margin: "2px 2px 10px" }}>
          <button className="cal-nav" aria-label="Mês anterior" onClick={() => stepM(-1)}><Icon name="chevL" size={16} /></button>
          <b style={{ fontSize: 13, textTransform: "capitalize" }}>{monthLabel(refYM)}{!isCur && <span style={{ fontSize: 11, color: "var(--text-3)", fontWeight: 700 }}> · consulta</span>}</b>
          <button className="cal-nav" aria-label="Próximo mês" onClick={() => stepM(1)} disabled={isCur} style={{ opacity: isCur ? 0.4 : 1 }}><Icon name="chevR" size={16} /></button>
        </div>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 6, marginBottom: 8 }}>
          <div style={{ background: "rgba(22,163,74,.10)", borderRadius: 10, padding: "7px 10px" }}><span style={{ fontSize: 11, color: "var(--text-3)", fontWeight: 700 }}>Recebido</span><br /><b style={{ color: "#16A34A", fontSize: 15 }}>{brl(recebido)}</b></div>
          <div style={{ background: "rgba(220,38,38,.08)", borderRadius: 10, padding: "7px 10px" }}><span style={{ fontSize: 11, color: "var(--text-3)", fontWeight: 700 }}>Em aberto</span><br /><b style={{ color: "#DC2626", fontSize: 15 }}>{brl(aberto)}</b></div>
        </div>
        <p style={{ margin: "0 0 10px", fontSize: 11.5, color: "var(--text-3)", fontWeight: 700 }}>{comPend} {comPend === 1 ? "paciente com pendência" : "pacientes com pendência"}</p>

        <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
          {ordered.length === 0 && <div className="rail-empty">Nenhum atendimento lançado ainda.</div>}
          {ordered.map(({ p, info, openM, tot }) => {
            const t = toneOpen(openM.length);
            const mostrar = openM.slice(0, 3);
            const restante = openM.length - mostrar.length;
            return (
              <button key={p.id} type="button" onClick={() => setDetail(p.id)} style={{ display: "block", width: "100%", textAlign: "left", cursor: "pointer", border: "1px solid " + t.bd, background: t.bg, borderRadius: 12, padding: "9px 11px", color: "var(--text)" }}>
                <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                  <span className={"avatar sm " + p.color} style={{ flex: "none" }}>{p.initials}</span>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap" }}>
                      <b style={{ fontSize: 13 }}>{p.name}</b>
                      {openM.length >= 2 && <span style={{ fontSize: 13 }}>{openM.length >= 3 ? "🚨" : "⚠️"}</span>}
                      {openM.length >= 3 && <span style={{ fontSize: 10, fontWeight: 800, color: "#fff", background: t.col, borderRadius: 20, padding: "1px 7px" }}>{openM.length} meses</span>}
                    </div>
                    {tot > 0
                      ? <span style={{ fontSize: 12.5, fontWeight: 800, color: t.col }}>{brl(tot)} em aberto</span>
                      : <span style={{ fontSize: 12, fontWeight: 800, color: "#16A34A" }}>em dia</span>}
                    {tot > 0 && <div style={{ marginTop: 3, fontSize: 11, color: "var(--text-2)" }}>{mostrar.map((m) => `${brl(m.rem)} ${ymShort(m.ym)}`).join(" · ")}{restante > 0 ? ` · +${restante} ${restante === 1 ? "mês" : "meses"}` : ""}</div>}
                  </div>
                </div>
              </button>
            );
          })}
        </div>

        {detail && window.AtendDetailModal && <window.AtendDetailModal pid={detail} type="mes" pkey={refYM} onClose={() => setDetail(null)} onChange={refresh} setToast={setToast} />}
        {toast && <div style={{ position: "fixed", left: "50%", bottom: 22, transform: "translateX(-50%)", zIndex: 120, display: "flex", alignItems: "center", gap: 9, padding: "11px 16px", borderRadius: 12, boxShadow: "var(--shadow-lg)", fontSize: 13.5, fontWeight: 700, color: "#fff", background: toast.err ? "#DC2626" : "var(--primary)" }}><Icon name={toast.err ? "x" : "clipboardCheck"} size={16} /> {toast.text}</div>}
      </div>
    );
  }
  window.PagamentosPanel = PagamentosPanel;
})();

