// src/pages/Cobranza.jsx
import { useState, useEffect, useMemo } from "react";
import { api } from "../lib/api";
import { Loader, ErrorBox, Filters, Select, colorSemaforo } from "../components/UI";
import Modal from "../components/Modal";
import { useColumnasAjustables } from "../lib/useColumnasAjustables";
import { setVistaActual, onRefrescar } from "../lib/vistaActual";

const MESES = ["ENERO","FEBRERO","MARZO","ABRIL","MAYO","JUNIO","JULIO","AGOSTO","SEPTIEMBRE","OCTUBRE","NOVIEMBRE","DICIEMBRE"];
const ANOS = [2024, 2025, 2026];
const AGRUPACIONES = [{value:"SEDE",label:"Por Sede"},{value:"PROGRAMA",label:"Por Programa"},{value:"ASESOR",label:"Por Asesor"}];
const SEDES = ["TODOS","LIMA","AREQUIPA","PIURA","TRUJILLO"];
const FRECS = ["TODOS","DOM","SAB","NOC","MAN","VIR","TAR"];

// Colores por cartera — diferenciados y legibles (sin azul, reservado para TOTAL)
// ANTERIOR = ámbar suave | MES = verde menta | TOTAL = lila/violeta suave
const BG_ANT = "#fef3c7", BG_MES = "#d1fae5", BG_TOT = "#ede9fe";
// Versiones más oscuras para hover de cada cartera
const HV_ANT = "#fde68a", HV_MES = "#a7f3d0", HV_TOT = "#ddd6fe";

function toMonto(s){ const n = parseFloat(String(s).replace("S/","").replace(/,/g,"").trim()); return isNaN(n)?0:n; }
function toPct(s){ const n = parseFloat(String(s).replace("%","").trim()); return isNaN(n)?0:n; }
// Formato moneda SIN decimales (solo visualización)
function fmtMoneda(s){
  if (s == null) return "";
  if (!String(s).includes("S/")) return s;        // no es monto, devolver tal cual
  const n = toMonto(s);
  return "S/ " + n.toLocaleString("es-PE", { maximumFractionDigits: 0 });
}

function MiniBar({ valStr }) {
  if (!valStr || !String(valStr).includes("%")) return <span style={{color:"#cbd5e1"}}>—</span>;
  const pct = toPct(valStr);
  const c = colorSemaforo(pct);
  const w = Math.min(Math.max(pct,0),100);
  return (
    <div style={{display:"flex",alignItems:"center",gap:5}}>
      <span style={{fontSize:10,fontWeight:700,color:c.fg,minWidth:30,textAlign:"right"}}>{pct.toFixed(0)}%</span>
      <div style={{flex:1,background:"#e2e8f0",borderRadius:4,height:5,overflow:"hidden",minWidth:30}}>
        <div style={{width:`${w}%`,background:c.fill,height:"100%"}} />
      </div>
    </div>
  );
}

export default function Cobranza() {
  const hoy = new Date();
  const [ano, setAno] = useState(hoy.getFullYear());
  const [mes, setMes] = useState(hoy.getMonth() + 1);
  const [agrupacion, setAgrupacion] = useState("SEDE");
  const [sectorista, setSectorista] = useState("TODOS");
  const [sede, setSede] = useState("TODOS");
  const [frec, setFrec] = useState("TODOS");
  const [filas, setFilas] = useState([]);
  const [sectoristas, setSectoristas] = useState(["TODOS"]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const [modal, setModal] = useState(null);
  const [sedeMap, setSedeMap] = useState({}); // programa -> sede (sede.json)
  const [exportando, setExportando] = useState(false);
  const [alumnos, setAlumnos] = useState([]);      // todos los alumnos (1 sola consulta)
  const [buscadorAbierto, setBuscadorAbierto] = useState(false);

  const esPrograma = agrupacion === "PROGRAMA";
  // índices según agrupación
  const IDX = esPrograma
    ? { saldo:13, ant:[4,5,6], mes:[7,8,9], tot:[10,11,12] }
    : { saldo:10, ant:[1,2,3], mes:[4,5,6], tot:[7,8,9] };

  useEffect(() => {
    let activo = true;
    setVistaActual(`cobranza:${ano}|${mes}|${sectorista}|${agrupacion}`);
    const cargar = () => {
      setLoading(true); setError(null);
      api.cobranza(ano, mes, sectorista, agrupacion)
        .then((res) => {
          if (!activo) return;
          setFilas(res.filas || []);
          setSectoristas(res.sectoristas || ["TODOS"]);
          setLoading(false);
        })
        .catch((e) => { if (activo) { setError(e.message); setLoading(false); } });
    };
    cargar();
    const off = onRefrescar(cargar);
    return () => { activo = false; off(); };
  }, [ano, mes, agrupacion, sectorista]);

  // Cargar TODOS los alumnos una sola vez (para exportar y buscar) — 1 consulta cacheada
  useEffect(() => {
    let activo = true;
    api.cobranzaDetalleTodos(ano, mes, sectorista)
      .then((res) => { if (activo) setAlumnos(res.alumnos || []); })
      .catch(() => { if (activo) setAlumnos([]); });
    return () => { activo = false; };
  }, [ano, mes, sectorista]);

  // Cargar clasificación de sede (sede.json) para los programas visibles
  useEffect(() => {
    if (!esPrograma) return;
    const nombres = filas
      .filter((f) => String(f[0]).toUpperCase() !== "TOTAL GENERAL")
      .map((f) => String(f[0]));
    if (nombres.length === 0) return;
    let activo = true;
    api.clasificarSede(nombres)
      .then((res) => { if (activo) setSedeMap(res.mapa || {}); })
      .catch(() => { if (activo) setSedeMap({}); });
    return () => { activo = false; };
  }, [filas, esPrograma]);

  // Filtro sede/frecuencia (solo PROGRAMA) en cliente — usa sede.json
  const datos = useMemo(() => {
    let arr = filas.filter((f) => String(f[0]).toUpperCase() !== "TOTAL GENERAL");
    if (esPrograma) {
      if (sede !== "TODOS") {
        arr = arr.filter((f) => {
          const s = (sedeMap[String(f[0])] || "LIMA").toUpperCase();
          return s === sede.toUpperCase();
        });
      }
      if (frec !== "TODOS") arr = arr.filter((f) => String(f[1]).toUpperCase() === frec);
    }
    return arr;
  }, [filas, esPrograma, sede, frec, sedeMap]);

  // KPIs: 3 tarjetas (recalculadas con datos filtrados)
  const kpis = useMemo(() => {
    let cAnt=0,obAnt=0,cMes=0,obMes=0,cTot=0,obTot=0;
    datos.forEach((f) => {
      cAnt += toMonto(f[IDX.ant[0]]); obAnt += toMonto(f[IDX.ant[1]]);
      cMes += toMonto(f[IDX.mes[0]]); obMes += toMonto(f[IDX.mes[1]]);
      cTot += toMonto(f[IDX.tot[0]]); obTot += toMonto(f[IDX.tot[1]]);
    });
    return { cAnt,obAnt,cMes,obMes,cTot,obTot, saldo: cTot-obTot };
  }, [datos, IDX]);

  const headers = esPrograma
    ? ["PROGRAMA","FREC.","N° CUOTA","VENCIMIENTO","CTA X COB. MES ANT.","COB. MES ANT.","% ANT","CTA X COB EN CURSO","COB. EN CURSO","% MES","CTA X COB TOTAL","COB. TOTAL","% TOTAL","SALDO","OPC."]
    : ["GRUPO","CTA X COB. MES ANT.","COB. MES ANT.","% ANT","CTA X COB EN CURSO","COB. EN CURSO","% MES","CTA X COB TOTAL","COB. TOTAL","% TOTAL","SALDO","OPC."];

  // Anchos para columnas redimensionables (1ª columna más ancha, resto estándar)
  const anchosCob = headers.map((h, i) => i === 0 ? (esPrograma ? 280 : 200) : (h === "FREC." || h.startsWith("%") || h === "OPC." ? 80 : 120));
  const cols = useColumnasAjustables(anchosCob);

  function cartClase(ci) {
    if (IDX.ant.includes(ci)) return "cart-ant";
    if (IDX.mes.includes(ci)) return "cart-mes";
    if (IDX.tot.includes(ci)) return "cart-tot";
    return "";
  }

  // Alumnos visibles según filtros activos (mismo dataset que Ver / Estado de Cuenta)
  const alumnosFiltrados = useMemo(() => {
    let arr = alumnos;
    if (esPrograma) {
      if (sede !== "TODOS") arr = arr.filter((a) => String(a.sede).toUpperCase() === sede.toUpperCase());
      if (frec !== "TODOS") arr = arr.filter((a) => String(a.frecuencia).toUpperCase() === frec);
    }
    return arr;
  }, [alumnos, esPrograma, sede, frec]);

  function grupoDe(a) {
    // El programa detallado del alumno, en TODOS los filtros (Sede, Asesor, Programa).
    return a.programa;
  }

  // Exportar el DETALLE DE ALUMNOS (rápido: usa el dataset ya cargado, sin N consultas)
  async function exportarDetalle() {
    setExportando(true);
    try {
      const base = alumnosFiltrados;
      if (base.length === 0) { alert("No hay alumnos para exportar con los filtros actuales."); return; }

      const toDate = (v) => {
        if (!v || v === "-") return "";
        return String(v).trim();
      };
      const pct = (cob, cta) => cta > 0 ? cob/cta : null;

      const XLSX = await import("xlsx-js-style");
      const COLS = ["GRUPO","MATRÍCULA","ALUMNO","N° CUOTA","F. VENC.","CTA ANT.","COB ANT.","% ANT","CTA MES","COB MES","% MES","CTA TOT","COB TOT","% TOT","SALDO"];

      // Colores suaves por cartera (igual que el dashboard): ANT ámbar, MES verde, TOT lila
      const CART = { ant:"FEF3C7", mes:"D1FAE5", tot:"EDE9FE" };
      const cartFill = (c) => {
        if ([5,6,7].includes(c)) return CART.ant;
        if ([8,9,10].includes(c)) return CART.mes;
        if ([11,12,13].includes(c)) return CART.tot;
        return null;
      };
      const headerStyle = { font:{bold:true,color:{rgb:"FFFFFF"},sz:11}, fill:{fgColor:{rgb:"1E40AF"}}, alignment:{horizontal:"center",vertical:"center"} };
      const moneyFmt = '"S/" #,##0';
      const pctFmt = '0%';
      const dateFmt = "dd/mm/yyyy";
      const cellStyle = (c) => { const f = cartFill(c); return f ? { fill:{fgColor:{rgb:f}} } : undefined; };

      const ws = {};
      COLS.forEach((h,c)=>{ ws[XLSX.utils.encode_cell({r:0,c})] = {v:h,t:"s",s:headerStyle}; });

      base.forEach((a, ri) => {
        const r = ri + 1;
        const vals = [
          grupoDe(a), a.matricula, a.alumno, a.num_cuota, toDate(a.fch_venc),
          a.cta_ant, a.cob_ant, pct(a.cob_ant,a.cta_ant),
          a.cta_cur, a.cob_cur, pct(a.cob_cur,a.cta_cur),
          a.cta_tot, a.cob_tot, pct(a.cob_tot,a.cta_tot),
          a.saldo,
        ];
        vals.forEach((v, c) => {
          const ref = XLSX.utils.encode_cell({r,c});
          const st = cellStyle(c);
          if ([5,6,8,9,11,12,14].includes(c)) ws[ref] = { v:Number(v)||0, t:"n", z:moneyFmt, ...(st?{s:st}:{}) };
          else if ([7,10,13].includes(c)) ws[ref] = (v===null) ? { v:"-", t:"s", ...(st?{s:st}:{}) } : { v:Number(v), t:"n", z:pctFmt, ...(st?{s:st}:{}) };
          else ws[ref] = { v: v ?? "", t:"s" };
        });
      });

      // TOTAL GENERAL (suma de montos)
      const rTot = base.length + 1;
      const totalStyle = { font:{bold:true}, fill:{fgColor:{rgb:"EFF6FF"}} };
      const sum = (k) => base.reduce((s,a)=>s+(Number(a[k])||0),0);
      const totVals = { 5:sum("cta_ant"),6:sum("cob_ant"),8:sum("cta_cur"),9:sum("cob_cur"),11:sum("cta_tot"),12:sum("cob_tot"),14:sum("saldo") };
      COLS.forEach((col,c)=>{
        const ref = XLSX.utils.encode_cell({r:rTot,c});
        if (c===0) ws[ref] = {v:"TOTAL GENERAL",t:"s",s:totalStyle};
        else if (totVals[c]!==undefined) ws[ref] = {v:totVals[c],t:"n",z:moneyFmt,s:totalStyle};
        else ws[ref] = {v:"",t:"s",s:totalStyle};
      });

      ws["!ref"] = XLSX.utils.encode_range({ s:{r:0,c:0}, e:{r:rTot,c:COLS.length-1} });
      ws["!cols"] = [{wch:26},{wch:12},{wch:28},{wch:9},{wch:12},{wch:12},{wch:12},{wch:8},{wch:12},{wch:12},{wch:8},{wch:12},{wch:12},{wch:8},{wch:13}];

      const wb = XLSX.utils.book_new();
      XLSX.utils.book_append_sheet(wb, ws, "Cobranza");
      const sufijo = agrupacion + (esPrograma && sede!=="TODOS" ? `_${sede}` : "") + (sectorista!=="TODOS" ? `_${sectorista}` : "");
      XLSX.writeFile(wb, `cobranza_${sufijo}_${ano}_${mes}.xlsx`);
    } finally {
      setExportando(false);
    }
  }

  return (
    <div>
      <h1 className="page-title">📋 Cobranza</h1>

      <Filters>
        <Select label="Año" value={ano} options={ANOS} onChange={(v)=>setAno(+v)} />
        <Select label="Mes" value={mes} options={MESES.map((m,i)=>({value:i+1,label:m}))} onChange={(v)=>setMes(+v)} />
        <Select label="Agrupación" value={agrupacion} options={AGRUPACIONES} onChange={(v)=>{setAgrupacion(v);setSede("TODOS");setFrec("TODOS");}} />
        <Select label="Sectorista" value={sectorista} options={sectoristas} onChange={setSectorista} />
        {esPrograma && <Select label="Sede" value={sede} options={SEDES} onChange={setSede} />}
        {esPrograma && <Select label="Frecuencia" value={frec} options={FRECS} onChange={setFrec} />}
        <div style={{display:"flex",gap:8,alignItems:"flex-end",marginLeft:"auto"}}>
          <button className="btn btn-ghost" style={{height:38}} onClick={()=>setBuscadorAbierto(true)}>🔍 Buscar</button>
          <button className="btn btn-primary" style={{height:38}} disabled={exportando || !alumnosFiltrados.length} onClick={exportarDetalle}>
            {exportando ? "Exportando..." : "⬇️ Exportar"}
          </button>
        </div>
      </Filters>

      {loading ? <Loader text="Calculando cobranza..." /> :
       error ? <ErrorBox msg={error} /> :
       <>
         <Tarjetas kpis={kpis} />

         <div className="table-wrap" style={{marginTop:16, overflowX:"auto"}}>
           <table className="cob-table" {...cols.tableProps}>
             <cols.ColGroup />
             <thead><tr>{headers.map((h, i)=><th key={h} style={{position:"relative"}}>{h}<cols.Resizer index={i} /></th>)}</tr></thead>
             <tbody>
               {datos.map((f, ri) => {
                 // En la tabla principal SIEMPRE son agrupaciones (Sede/Programa/Asesor),
                 // nunca alumnos individuales → NO aplicar rojo por deuda aquí.
                 // Regla "-": si % del grupo está vacío, CTA y COB del grupo → "-"
                 const antVacio = !String(f[IDX.ant[2]]||"").trim() || ["-","—"].includes(String(f[IDX.ant[2]]).trim());
                 const mesVacio = !String(f[IDX.mes[2]]||"").trim() || ["-","—"].includes(String(f[IDX.mes[2]]).trim());
                 const totVacio = !String(f[IDX.tot[2]]||"").trim() || ["-","—"].includes(String(f[IDX.tot[2]]).trim());
                 return (
                   <tr key={ri}>
                     {f.slice(0, headers.length-1).map((v, ci) => {
                       const isPct = IDX.ant[2]===ci || IDX.mes[2]===ci || IDX.tot[2]===ci;
                       let val = v;
                       if ((ci===IDX.ant[0]||ci===IDX.ant[1]||ci===IDX.ant[2]) && antVacio) val = "—";
                       if ((ci===IDX.mes[0]||ci===IDX.mes[1]||ci===IDX.mes[2]) && mesVacio) val = "—";
                       if ((ci===IDX.tot[0]||ci===IDX.tot[1]||ci===IDX.tot[2]) && totVacio) val = "—";
                       const cartCls = cartClase(ci);
                       const clss = (ci===0?"col-name":"") + (cartCls?` ${cartCls}`:"");
                       return (
                         <td key={ci} className={clss.trim()}
                             style={{textAlign: ci===0?"left":"center",
                                     minWidth: ci===0?(esPrograma?300:200):undefined,
                                     maxWidth: ci===0?500:undefined,
                                     whiteSpace: "nowrap",
                                     overflow: ci===0?"hidden":undefined,
                                     textOverflow: ci===0?"ellipsis":undefined}}>
                           {isPct ? (val==="—" ? <span style={{color:"#cbd5e1"}}>—</span> : <MiniBar valStr={val} />) : fmtMoneda(val)}
                         </td>
                       );
                     })}
                     <td>
                       <button className="btn btn-ghost" style={{padding:"4px 10px",fontSize:11}}
                         onClick={() => setModal({ grupo: f[0] })}>👁️ Ver</button>
                     </td>
                   </tr>
                 );
               })}
               {datos.length > 0 && (() => {
                 // Fila TOTAL GENERAL — suma de los datos visibles (respeta filtros)
                 const t = {};
                 [IDX.ant[0],IDX.ant[1],IDX.mes[0],IDX.mes[1],IDX.tot[0],IDX.tot[1],IDX.saldo]
                   .forEach((ci)=>{ t[ci] = datos.reduce((s,f)=>s+toMonto(f[ci]),0); });
                 const ratio = (cob,cta)=> cta>0 ? `${Math.round(cob/cta*100)}%` : "";
                 const cell = (ci) => {
                   if (ci===0) return "TOTAL GENERAL";
                   if (ci===IDX.ant[2]) return ratio(t[IDX.ant[1]],t[IDX.ant[0]]);
                   if (ci===IDX.mes[2]) return ratio(t[IDX.mes[1]],t[IDX.mes[0]]);
                   if (ci===IDX.tot[2]) return ratio(t[IDX.tot[1]],t[IDX.tot[0]]);
                   if (t[ci]!==undefined) return "S/ " + t[ci].toLocaleString("es-PE",{maximumFractionDigits:0});
                   return "";
                 };
                 return (
                   <tr className="total-row">
                     {Array.from({length: headers.length-1}).map((_,ci)=>{
                       const isPct = IDX.ant[2]===ci || IDX.mes[2]===ci || IDX.tot[2]===ci;
                       const val = cell(ci);
                       return (
                         <td key={ci} className={ci===0?"col-name":""}
                             style={{textAlign: ci===0?"left":"center",
                                     whiteSpace:"nowrap"}}>
                           {isPct ? <MiniBar valStr={val} /> : val}
                         </td>
                       );
                     })}
                     <td>—</td>
                   </tr>
                 );
               })()}
             </tbody>
           </table>
         </div>
       </>}

      {modal && (
        <ModalEstadoCuenta grupo={modal.grupo} ano={ano} mes={mes}
          sectorista={sectorista} agrupacion={agrupacion} onClose={() => setModal(null)} />
      )}

      {buscadorAbierto && (
        <ModalBuscador
          alumnos={alumnosFiltrados}
          agrupacion={agrupacion}
          sectorista={sectorista}
          onClose={() => setBuscadorAbierto(false)}
        />
      )}
    </div>
  );
}

function Tarjetas({ kpis }) {
  const alDia = kpis.saldo <= 0.01;
  if (alDia) {
    return (
      <div style={{background:"linear-gradient(135deg,#d1fae5,#a7f3d0)",border:"2px solid #10b981",
        borderRadius:14,padding:18,textAlign:"center"}}>
        <div style={{fontSize:32}}>✅</div>
        <div style={{fontSize:18,fontWeight:800,color:"#065f46",letterSpacing:1}}>AL DÍA</div>
        <div style={{fontSize:12,color:"#047857"}}>Sin deuda pendiente</div>
      </div>
    );
  }
  const cards = [
    ["⚠ MES ANTERIOR","#d97706",kpis.cAnt,kpis.obAnt],
    ["📅 MES EN CURSO","#059669",kpis.cMes,kpis.obMes],
    ["💰 CARTERA TOTAL","#7c3aed",kpis.cTot,kpis.obTot],
  ];
  return (
    <div style={{display:"grid",gridTemplateColumns:"repeat(3,1fr)",gap:14}}>
      {cards.map(([titulo,color,cta,cob]) => {
        const ratio = cta>0 ? (cob/cta*100) : 0;
        const c = colorSemaforo(ratio);
        const saldo = cta - cob;
        return (
          <div key={titulo} style={{background:"#fff",border:"1px solid #e2e8f0",borderRadius:12,overflow:"hidden"}}>
            <div style={{background:color,color:"#fff",padding:"10px 14px",fontWeight:700,fontSize:13,textAlign:"center"}}>{titulo}</div>
            <div style={{padding:14}}>
              <Row k="Cta x Cobrar" v={`S/ ${cta.toLocaleString("es-PE",{maximumFractionDigits:0})}`} />
              <Row k="Cobrado" v={`S/ ${cob.toLocaleString("es-PE",{maximumFractionDigits:0})}`} />
              <Row k="Saldo" v={`S/ ${saldo.toLocaleString("es-PE",{maximumFractionDigits:0})}`} bold color={saldo>0?"#dc2626":"#10b981"} />
              {cta>0 && (
                <div style={{marginTop:10}}>
                  <div style={{display:"flex",justifyContent:"space-between",marginBottom:4}}>
                    <span style={{fontSize:10,fontWeight:600,color:"#64748b",textTransform:"uppercase"}}>% de Pago</span>
                    <span style={{fontSize:14,fontWeight:700,color:c.fg}}>{ratio.toFixed(0)}%</span>
                  </div>
                  <div style={{background:"#e2e8f0",borderRadius:6,height:8,overflow:"hidden"}}>
                    <div style={{width:`${Math.min(ratio,100)}%`,background:c.fill,height:"100%"}} />
                  </div>
                </div>
              )}
            </div>
          </div>
        );
      })}
    </div>
  );
}

function Row({ k, v, bold, color }) {
  return (
    <div style={{display:"flex",justifyContent:"space-between",fontSize:11,color:"#64748b",marginBottom:4,
      ...(bold?{paddingTop:6,borderTop:"1px solid #f1f5f9"}:{})}}>
      <span>{k}</span>
      <span style={{fontWeight:bold?700:600,color:color||"#0f172a"}}>{v}</span>
    </div>
  );
}

function TarjetasResumen({ r }) {
  const cards = [
    ["⚠ MES ANTERIOR","#d97706",r.cAnt,r.obAnt],
    ["📅 MES EN CURSO","#059669",r.cMes,r.obMes],
    ["💰 CARTERA TOTAL","#7c3aed",r.cTot,r.obTot],
  ];
  return (
    <div style={{display:"grid",gridTemplateColumns:"repeat(3,1fr)",gap:14}}>
      {cards.map(([titulo,color,cta,cob]) => {
        const ratio = cta>0 ? (cob/cta*100) : 0;
        const c = colorSemaforo(ratio);
        const saldo = cta - cob;
        return (
          <div key={titulo} style={{background:"#fff",border:"1px solid #e2e8f0",borderRadius:12,overflow:"hidden"}}>
            <div style={{background:color,color:"#fff",padding:"9px 12px",fontWeight:700,fontSize:12,textAlign:"center"}}>{titulo}</div>
            <div style={{padding:12}}>
              <Row k="Cta x Cobrar" v={`S/ ${cta.toLocaleString("es-PE",{maximumFractionDigits:0})}`} />
              <Row k="Cobrado" v={`S/ ${cob.toLocaleString("es-PE",{maximumFractionDigits:0})}`} />
              <Row k="Saldo" v={`S/ ${saldo.toLocaleString("es-PE",{maximumFractionDigits:0})}`} bold color={saldo>0?"#dc2626":"#10b981"} />
              {cta>0 && (
                <div style={{marginTop:8}}>
                  <div style={{display:"flex",justifyContent:"space-between",marginBottom:4}}>
                    <span style={{fontSize:10,fontWeight:600,color:"#64748b",textTransform:"uppercase"}}>% de Pago</span>
                    <span style={{fontSize:13,fontWeight:700,color:c.fg}}>{ratio.toFixed(0)}%</span>
                  </div>
                  <div style={{background:"#e2e8f0",borderRadius:6,height:7,overflow:"hidden"}}>
                    <div style={{width:`${Math.min(ratio,100)}%`,background:c.fill,height:"100%"}} />
                  </div>
                </div>
              )}
            </div>
          </div>
        );
      })}
    </div>
  );
}

function ModalBuscador({ alumnos, agrupacion, sectorista, onClose }) {
  const [texto, setTexto] = useState("");
  const [query, setQuery] = useState("");
  const [porRetirar, setPorRetirar] = useState(new Set());
  const [infoAlumno, setInfoAlumno] = useState(null);

  const cargarPorRetirar = () => {
    api.alumnosPorRetirar()
      .then((r)=>setPorRetirar(new Set((r.matriculas||[]).map(String))))
      .catch(()=>{});
  };
  useEffect(() => { cargarPorRetirar(); }, []);

  const resultados = useMemo(() => {
    const q = query.trim().toLowerCase();
    if (!q) return [];
    return alumnos.filter((a) =>
      String(a.alumno).toLowerCase().includes(q) ||
      String(a.programa).toLowerCase().includes(q) ||
      String(a.matricula).toLowerCase().includes(q)
    );
  }, [alumnos, query]);

  const COLS = ["PROGRAMA","ALUMNO","N° CUOTA","F. VENC.",
    "CTA ANT.","COB ANT.","% ANT","CTA MES","COB MES","% MES","CTA TOT","COB TOT","% TOT","SALDO","INFO"];

  const anchosBusc = COLS.map((h,i) => {
    if (i===0) return 250;
    if (i===1) return 250;
    if (h==="N° CUOTA" || h==="F. VENC.") return 100;
    if (h==="INFO") return 70;
    if (h.startsWith("%")) return 80;
    return 110;
  });
  const cols = useColumnasAjustables(anchosBusc);

  const FIJAS = 4;
  const stickyCol = (j, { esHeader = false, bg = "#fff" } = {}) => {
    if (j >= FIJAS) return {};
    let left = 0;
    for (let k = 0; k < j; k++) left += (cols.anchos[k] || 0);
    const ultima = j === FIJAS - 1;
    const lineaColor = esHeader ? "#475569" : "#e2e8f0";
    return {
      position: "sticky", left, zIndex: esHeader ? 20 : 10, backgroundColor: bg,
      borderRight: "none",
      boxShadow: `inset -1px 0 0 0 ${lineaColor}` + (ultima ? ", 3px 0 5px -2px rgba(0,0,0,0.18)" : ""),
    };
  };

  const pctStr = (cob, cta) => cta > 0 ? `${Math.round(cob/cta*100)}%` : "";

  return (
    <Modal title="🔍 Buscar Alumno" onClose={onClose} width={1360}>
      <div style={{display:"flex",gap:8,marginBottom:16}}>
        <input
          autoFocus
          value={texto}
          onChange={(e)=>setTexto(e.target.value)}
          onKeyDown={(e)=>{ if(e.key==="Enter") setQuery(texto); }}
          placeholder="Escribe nombre, programa o matrícula (ej: Aro) y presiona Enter"
          style={{flex:1,padding:"10px 14px",border:"1px solid #cbd5e1",borderRadius:8,fontSize:14}}
        />
        <button className="btn btn-primary" onClick={()=>setQuery(texto)}>🔍 Buscar</button>
        {query && <button className="btn btn-ghost" onClick={()=>{setTexto("");setQuery("");}}>Limpiar</button>}
      </div>

      {!query ? (
        <div style={{color:"#94a3b8",padding:30,textAlign:"center",fontSize:14}}>
          Escribe un texto y presiona Enter para buscar.
        </div>
      ) : resultados.length === 0 ? (
        <div style={{color:"#94a3b8",padding:30,textAlign:"center",fontSize:14}}>
          Sin coincidencias para "{query}".
        </div>
      ) : (
        <>
          <div style={{fontSize:13,color:"#1e40af",fontWeight:600,marginBottom:8}}>
            {resultados.length} alumno(s) encontrado(s)
          </div>
          <div className="table-wrap" style={{overflow:"auto", maxHeight:"60vh"}}>
            <table className="cob-table" {...cols.tableProps}>
              <cols.ColGroup />
              <thead><tr>{COLS.map((c,i)=>{
                const fija = i < FIJAS;
                const stH = fija ? stickyCol(i,{esHeader:true,bg:"#334155"})
                                 : { position:"sticky", top:0, zIndex:12, backgroundColor:"#334155" };
                return <th key={c} style={{...stH, position:stH.position||"relative"}}>{c}<cols.Resizer index={i} /></th>;
              })}</tr></thead>
              <tbody>
                {resultados.map((a,i)=>{
                  const deuda = a.saldo > 0.01;
                  const retira = porRetirar.has(String(a.matricula));
                  const bgFila = (i % 2 === 1) ? "#f8fafc" : "#fff";
                  const celdas = [
                    {v:a.programa, cls:"col-name", al:"left", texto:true},
                    {v:a.alumno, cls:"col-name", al:"left", texto:true},
                    {v:a.num_cuota},
                    {v:a.fch_venc},
                    {v:fmtMoneda("S/ "+a.cta_ant), cart:"cart-ant"},
                    {v:fmtMoneda("S/ "+a.cob_ant), cart:"cart-ant"},
                    {pct:pctStr(a.cob_ant,a.cta_ant), cart:"cart-ant"},
                    {v:fmtMoneda("S/ "+a.cta_cur), cart:"cart-mes"},
                    {v:fmtMoneda("S/ "+a.cob_cur), cart:"cart-mes"},
                    {pct:pctStr(a.cob_cur,a.cta_cur), cart:"cart-mes"},
                    {v:fmtMoneda("S/ "+a.cta_tot), cart:"cart-tot"},
                    {v:fmtMoneda("S/ "+a.cob_tot), cart:"cart-tot"},
                    {pct:pctStr(a.cob_tot,a.cta_tot), cart:"cart-tot"},
                    {v:fmtMoneda("S/ "+a.saldo), saldo:true},
                  ];
                  return (
                    <tr key={i} className={deuda?"row-deuda":""}
                        style={retira ? { textDecoration:"line-through", textDecorationColor:"#dc2626",
                                          textDecorationThickness:"2px" } : undefined}>
                      {celdas.map((c,j)=>(
                        <td key={j} className={((c.cls||"")+" "+(c.cart||"")).trim()}
                            title={c.texto ? String(c.v) : undefined}
                            style={{textAlign:c.al||"center",
                                    fontWeight:c.saldo?700:undefined,
                                    color:c.saldo&&deuda?"#dc2626":undefined,
                                    whiteSpace:"nowrap",
                                    overflow:c.texto?"hidden":undefined,
                                    textOverflow:c.texto?"ellipsis":undefined,
                                    ...stickyCol(j,{bg:bgFila})}}>
                          {c.pct!==undefined ? (c.pct ? <MiniBar valStr={c.pct} /> : "—") : c.v}
                        </td>
                      ))}
                      <td style={{textAlign:"center"}}>
                        <button
                          onClick={()=>setInfoAlumno({ matricula:a.matricula, alumno:a.alumno, programa:a.programa })}
                          style={{padding:"3px 10px",fontSize:11,fontWeight:700,cursor:"pointer",
                                  border:"1px solid #cbd5e1",borderRadius:6,background:"#f8fafc",color:"#334155"}}
                          title="Ver/editar estado y observaciones">
                          INFO
                        </button>
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        </>
      )}
      {infoAlumno && (
        <ModalInfoAlumno alumno={infoAlumno} onClose={()=>setInfoAlumno(null)}
                         onGuardado={cargarPorRetirar} />
      )}
    </Modal>
  );
}

function ModalEstadoCuenta({ grupo, ano, mes, sectorista, agrupacion, onClose }) {
  const [filas, setFilas] = useState([]);
  const [loading, setLoading] = useState(true);
  const [porRetirar, setPorRetirar] = useState(new Set());  // matrículas POR RETIRAR
  const [soloRetirar, setSoloRetirar] = useState(false);    // filtro: ver solo POR RETIRAR
  const [infoAlumno, setInfoAlumno] = useState(null);       // alumno del pop-up INFO

  useEffect(() => {
    let activo = true;
    setLoading(true);
    api.cobranzaDetalle(grupo, ano, mes, sectorista, agrupacion)
      .then((res) => { if (activo) { setFilas(res.filas || []); setLoading(false); } })
      .catch(() => { if (activo) { setFilas([]); setLoading(false); } });
    return () => { activo = false; };
  }, [grupo, ano, mes, sectorista, agrupacion]);

  // Cargar (y recargar) las matrículas marcadas POR RETIRAR para tachar sus filas
  const cargarPorRetirar = () => {
    api.alumnosPorRetirar()
      .then((r) => setPorRetirar(new Set((r.matriculas || []).map(String))))
      .catch(() => {});
  };
  useEffect(() => { cargarPorRetirar(); }, []);

  const COLS = ["PROGRAMA","ALUMNO","N° CUOTA","F. VENC.","CTA ANT.","COB ANT.","% ANT","CTA MES","COB MES","% MES","CTA TOT","COB TOT","% TOT","SALDO","INFO"];

  // Columnas redimensionables (igual que la tabla principal): PROGRAMA y ALUMNO más anchas
  const anchosDet = COLS.map((h, i) => i === 0 ? 240 : (i === 1 ? 220 : (h==="INFO" ? 70 : h.startsWith("%") ? 80 : 110)));
  const cols = useColumnasAjustables(anchosDet);

  // Congelar las 4 primeras columnas (PROGRAMA, ALUMNO, N° CUOTA, F. VENC.).
  const FIJAS = 4;
  const stickyCol = (j, { esHeader = false, bg = "#fff" } = {}) => {
    if (j >= FIJAS) return {};
    let left = 0;
    for (let k = 0; k < j; k++) left += (cols.anchos[k] || 0);
    const ultima = j === FIJAS - 1;
    const lineaColor = esHeader ? "#475569" : "#e2e8f0";
    return {
      position: "sticky", left, zIndex: esHeader ? 20 : 10, backgroundColor: bg,
      borderRight: "none",
      boxShadow: `inset -1px 0 0 0 ${lineaColor}` + (ultima ? ", 3px 0 5px -2px rgba(0,0,0,0.18)" : ""),
    };
  };

  // Resumen para las 3 tarjetas (siempre visibles) — suma del detalle de alumnos
  const resumen = useMemo(() => {
    let cAnt=0,obAnt=0,cMes=0,obMes=0,cTot=0,obTot=0;
    filas.forEach((f) => {
      if (String(f[0]).toUpperCase() === "TOTAL") return;
      cAnt += toMonto(f[4]); obAnt += toMonto(f[5]);
      cMes += toMonto(f[7]); obMes += toMonto(f[8]);
      cTot += toMonto(f[10]); obTot += toMonto(f[11]);
    });
    return { cAnt,obAnt,cMes,obMes,cTot,obTot };
  }, [filas]);

  // Conteo de alumnos: total, ya pagaron (saldo 0) y por pagar (saldo > 0)
  const conteo = useMemo(() => {
    let total=0, pagaron=0, deben=0;
    filas.forEach((f) => {
      if (String(f[0]).toUpperCase() === "TOTAL") return;
      total++;
      if (toMonto(f[13]) > 0.01) deben++; else pagaron++;
    });
    return { total, pagaron, deben };
  }, [filas]);

  // POR RETIRAR: cantidad de alumnos marcados y suma de su saldo
  const retiro = useMemo(() => {
    let cant=0, saldo=0;
    filas.forEach((f) => {
      if (String(f[0]).toUpperCase() === "TOTAL") return;
      if (porRetirar.has(String(f[0]))) { cant++; saldo += toMonto(f[13]); }
    });
    return { cant, saldo };
  }, [filas, porRetirar]);

  return (
    <Modal title={`📊 Estado de Cuenta — ${grupo}`} onClose={onClose} width={1500}>
      {loading ? <Loader text="Cargando estado de cuenta..." /> :
       filas.length === 0 ? <div style={{color:"#94a3b8",padding:20,textAlign:"center"}}>Sin datos.</div> :
       <>
       <div style={{marginBottom:16}}>
         <TarjetasResumen r={resumen} />
       </div>
       {/* Etiquetas de conteo de alumnos */}
       <div style={{display:"flex",gap:10,marginBottom:14,flexWrap:"wrap",alignItems:"center"}}>
         <span style={{display:"inline-flex",alignItems:"center",gap:6,padding:"6px 14px",
           borderRadius:999,background:"#eff6ff",color:"#1e40af",fontSize:13,fontWeight:700,
           border:"1px solid #bfdbfe"}}>
           👥 Total: {conteo.total}
         </span>
         <span style={{display:"inline-flex",alignItems:"center",gap:6,padding:"6px 14px",
           borderRadius:999,background:"#ecfdf5",color:"#047857",fontSize:13,fontWeight:700,
           border:"1px solid #a7f3d0"}}>
           ✅ Pagaron: {conteo.pagaron}
         </span>
         <span style={{display:"inline-flex",alignItems:"center",gap:6,padding:"6px 14px",
           borderRadius:999,background:"#fffbeb",color:"#b45309",fontSize:13,fontWeight:700,
           border:"1px solid #fde68a"}}>
           ⏳ Por pagar: {conteo.deben}
         </span>
         <span style={{width:1,height:26,background:"#e2e8f0",margin:"0 4px"}} />
         <span style={{display:"inline-flex",alignItems:"center",gap:6,padding:"6px 14px",
           borderRadius:999,background:"#fef2f2",color:"#dc2626",fontSize:13,fontWeight:700,
           border:"1px solid #fecaca"}}>
           🚫 Por retirar: {retiro.cant}
         </span>
         <span style={{display:"inline-flex",alignItems:"center",gap:6,padding:"6px 14px",
           borderRadius:999,background:"#fef2f2",color:"#dc2626",fontSize:13,fontWeight:700,
           border:"1px solid #fecaca"}}>
           💸 Saldo: S/ {retiro.saldo.toLocaleString("es-PE",{maximumFractionDigits:0})}
         </span>
         <label style={{display:"inline-flex",alignItems:"center",gap:6,padding:"6px 14px",
           borderRadius:999,background:soloRetirar?"#fee2e2":"#f8fafc",marginLeft:"auto",
           color:soloRetirar?"#b91c1c":"#64748b",fontSize:13,fontWeight:700,cursor:"pointer",
           border:`1px solid ${soloRetirar?"#fca5a5":"#e2e8f0"}`}}>
           <input type="checkbox" checked={soloRetirar}
             onChange={(e)=>setSoloRetirar(e.target.checked)} style={{cursor:"pointer"}} />
           Ver solo por retirar
         </label>
       </div>
       <div className="table-wrap" style={{overflow:"auto", maxHeight:"60vh"}}>
         <table className="cob-table" {...cols.tableProps}>
           <cols.ColGroup />
           <thead><tr>{COLS.map((c,i)=>{
             const fija = i < FIJAS;
             const stH = fija
               ? stickyCol(i,{esHeader:true,bg:"#334155"})
               : { position:"sticky", top:0, zIndex:12, backgroundColor:"#334155" };
             return <th key={c} style={{...stH, position:stH.position||"relative"}}>{c}<cols.Resizer index={i} /></th>;
           })}</tr></thead>
           <tbody>
             {filas.filter((f)=>String(f[0]).toUpperCase()!=="TOTAL")
                   .filter((f)=> !soloRetirar || porRetirar.has(String(f[0])))
                   .map((f, i) => {
               const saldo = toMonto(f[13]);
               const deuda = saldo > 0.01;
               const antVacio = !String(f[6]||"").trim() || ["-","—"].includes(String(f[6]).trim());
               const mesVacio = !String(f[9]||"").trim() || ["-","—"].includes(String(f[9]).trim());
               const totVacio = !String(f[12]||"").trim() || ["-","—"].includes(String(f[12]).trim());
               const programa = f[14] || "-";
               const retira = porRetirar.has(String(f[0]));
               return (
                 <tr key={i} className={deuda?"row-deuda":""}
                     style={retira ? { textDecoration:"line-through", textDecorationColor:"#dc2626",
                                       textDecorationThickness:"2px" } : undefined}>
                   {f.slice(0, 14).map((v, j) => {
                     let val = (j===0) ? programa : v;
                     if ((j===4||j===5||j===6) && antVacio) val = "—";
                     if ((j===7||j===8||j===9) && mesVacio) val = "—";
                     if ((j===10||j===11||j===12) && totVacio) val = "—";
                     const isPct = [6,9,12].includes(j);
                     let cart = "";
                     if ([4,5,6].includes(j)) cart = "cart-ant";
                     else if ([7,8,9].includes(j)) cart = "cart-mes";
                     else if ([10,11,12].includes(j)) cart = "cart-tot";
                     const clss = (((j===0||j===1)?"col-name":"") + (cart?` ${cart}`:"")).trim();
                     const esTexto = (j===0||j===1);
                     const bgFila = (i % 2 === 1) ? "#f8fafc" : "#fff";
                     return (
                       <td key={j} className={clss}
                           title={esTexto ? String(val) : undefined}
                           style={{textAlign:esTexto?"left":"center",
                                   whiteSpace:"nowrap",
                                   overflow:esTexto?"hidden":undefined,
                                   textOverflow:esTexto?"ellipsis":undefined,
                                   color:j===13&&deuda?"#dc2626":undefined,
                                   fontWeight:j===13?700:undefined,
                                   ...stickyCol(j,{bg:bgFila})}}>
                         {isPct ? (val==="—"?<span style={{color:"#cbd5e1"}}>—</span>:<MiniBar valStr={val} />) : fmtMoneda(val)}
                       </td>
                     );
                   })}
                   <td style={{textAlign:"center"}}>
                     <button
                       onClick={()=>setInfoAlumno({ matricula:f[0], alumno:f[1], programa:programa })}
                       style={{padding:"3px 10px",fontSize:11,fontWeight:700,cursor:"pointer",
                               border:"1px solid #cbd5e1",borderRadius:6,background:"#f8fafc",color:"#334155"}}
                       title="Ver/editar estado y observaciones">
                       INFO
                     </button>
                   </td>
                 </tr>
               );
             })}
           </tbody>
           <tfoot>
             {(() => {
               const alumnos = filas.filter((f)=>String(f[0]).toUpperCase()!=="TOTAL")
                                    .filter((f)=> !soloRetirar || porRetirar.has(String(f[0])));
               if (alumnos.length===0) return null;
               const sum = (j)=>alumnos.reduce((s,f)=>s+toMonto(f[j]),0);
               const t = {4:sum(4),5:sum(5),7:sum(7),8:sum(8),10:sum(10),11:sum(11),13:sum(13)};
               const r = (cob,cta)=>cta>0?`${Math.round(cob/cta*100)}%`:"";
               const celda = (j)=>{
                 if (j===0) return "TOTAL GENERAL";
                 if (j===1||j===2||j===3) return "";
                 if (j===6) return r(t[5],t[4]);
                 if (j===9) return r(t[8],t[7]);
                 if (j===12) return r(t[11],t[10]);
                 if (t[j]!==undefined) return "S/ "+t[j].toLocaleString("es-PE",{maximumFractionDigits:0});
                 return "";
               };
               return (
                 <tr className="total-row">
                   {Array.from({length:14}).map((_,j)=>{
                     const isPct=[6,9,12].includes(j);
                     const val=celda(j);
                     const fija = j < FIJAS;
                     let left = 0; for (let k=0;k<j;k++) left += (cols.anchos[k]||0);
                     const st = {
                       position:"sticky", bottom:0,
                       zIndex: fija ? 15 : 8,
                       backgroundColor:"#eff6ff",
                       padding:"11px 8px",
                       ...(fija ? { left, boxShadow:`inset -1px 0 0 0 #cbd5e1${j===FIJAS-1?", 3px 0 5px -2px rgba(0,0,0,0.18)":""}, inset 0 1px 0 0 #cbd5e1` } : { boxShadow:"inset 0 1px 0 0 #cbd5e1" }),
                     };
                     return (
                       <td key={j} className={j===0?"col-name":""}
                           style={{textAlign:j===0?"left":"center",whiteSpace:"nowrap",...st}}>
                         {isPct?<MiniBar valStr={val} />:val}
                       </td>
                     );
                   })}
                   <td style={{position:"sticky",bottom:0,zIndex:8,backgroundColor:"#eff6ff",boxShadow:"inset 0 1px 0 0 #cbd5e1"}}></td>
                 </tr>
               );
             })()}
           </tfoot>
         </table>
       </div>
       </>}
      {infoAlumno && (
        <ModalInfoAlumno alumno={infoAlumno} onClose={()=>setInfoAlumno(null)}
                         onGuardado={cargarPorRetirar} />
      )}
    </Modal>
  );
}

// Pop-up de INFO por alumno: cambiar estado (EN CURSO / POR RETIRAR) y observaciones.
// Carga y guarda en Supabase (tabla cobranza_estado_alumno).
function ModalInfoAlumno({ alumno, onClose, onGuardado }) {
  const [estado, setEstado] = useState("EN CURSO");
  const [nuevaObs, setNuevaObs] = useState("");
  const [observaciones, setObservaciones] = useState([]);
  const [cargando, setCargando] = useState(true);
  const [guardando, setGuardando] = useState(false);
  const [guardado, setGuardado] = useState(false);

  useEffect(() => {
    let activo = true;
    api.alumnoEstado(alumno.matricula)
      .then((r)=>{ if(activo){ setEstado(r.estado||"EN CURSO"); setObservaciones(r.observaciones||[]); } })
      .catch(()=>{})
      .finally(()=>{ if(activo) setCargando(false); });
    return ()=>{ activo=false; };
  }, [alumno.matricula]);

  const agregarObs = () => {
    const t = nuevaObs.trim();
    if (!t) return;
    const fecha = new Date().toLocaleString("es-PE", { dateStyle:"short", timeStyle:"short" });
    setObservaciones((prev)=>[...prev, { texto:t, fecha }]);
    setNuevaObs("");
    setGuardado(false);
  };

  const guardar = async () => {
    setGuardando(true); setGuardado(false);
    try {
      await api.alumnoEstadoGuardar(alumno.matricula, estado, observaciones);
      setGuardado(true);
      if (onGuardado) onGuardado();
    } catch {
      alert("No se pudo guardar. Intenta de nuevo.");
    } finally {
      setGuardando(false);
    }
  };

  return (
    <Modal title={`ℹ️ Información del alumno`} onClose={onClose} width={560}>
      <div style={{marginBottom:16}}>
        <div style={{fontSize:15,fontWeight:800,color:"#0f172a"}}>{alumno.alumno}</div>
        <div style={{fontSize:12,color:"#64748b",marginTop:2}}>
          Matrícula: {alumno.matricula} · {alumno.programa}
        </div>
      </div>

      <div style={{marginBottom:18}}>
        <label style={{fontSize:12,fontWeight:700,color:"#334155",display:"block",marginBottom:6}}>
          Estado del alumno
        </label>
        <select value={estado} onChange={(e)=>{setEstado(e.target.value); setGuardado(false);}}
          style={{width:"100%",padding:"8px 10px",fontSize:14,borderRadius:8,
                  border:"1px solid #cbd5e1",background:"#fff",
                  color: estado==="POR RETIRAR" ? "#b91c1c" : "#047857", fontWeight:700}}>
          <option value="EN CURSO">EN CURSO</option>
          <option value="POR RETIRAR">POR RETIRAR</option>
        </select>
      </div>

      <div style={{marginBottom:14}}>
        <label style={{fontSize:12,fontWeight:700,color:"#334155",display:"block",marginBottom:6}}>
          Observaciones
        </label>
        <div style={{display:"flex",gap:8}}>
          <input value={nuevaObs} onChange={(e)=>setNuevaObs(e.target.value)}
            onKeyDown={(e)=>{ if(e.key==="Enter") agregarObs(); }}
            placeholder="Escribe una observación…"
            style={{flex:1,padding:"8px 10px",fontSize:13,borderRadius:8,border:"1px solid #cbd5e1"}} />
          <button onClick={agregarObs}
            style={{padding:"8px 14px",fontSize:13,fontWeight:700,cursor:"pointer",
                    border:"none",borderRadius:8,background:"#1e40af",color:"#fff"}}>
            Agregar
          </button>
        </div>
        <div style={{marginTop:10,display:"flex",flexDirection:"column",gap:6,maxHeight:180,overflowY:"auto"}}>
          {observaciones.length===0 ? (
            <div style={{fontSize:12,color:"#94a3b8",padding:"6px 2px"}}>Sin observaciones.</div>
          ) : observaciones.map((o,i)=>(
            <div key={i} style={{background:"#f8fafc",border:"1px solid #eef2f7",borderRadius:8,
                                 padding:"8px 10px",display:"flex",alignItems:"flex-start",gap:8}}>
              <div style={{flex:1}}>
                <div style={{fontSize:13,color:"#334155"}}>{o.texto}</div>
                <div style={{fontSize:10,color:"#94a3b8",marginTop:2}}>{o.fecha}</div>
              </div>
              <button onClick={()=>{ setObservaciones(prev=>prev.filter((_,k)=>k!==i)); setGuardado(false); }}
                title="Eliminar observación (se aplica al guardar)"
                style={{border:"none",background:"transparent",color:"#dc2626",cursor:"pointer",
                        fontSize:16,fontWeight:800,lineHeight:1,padding:"0 2px"}}>
                ×
              </button>
            </div>
          ))}
        </div>
      </div>

      <div style={{display:"flex",justifyContent:"flex-end",alignItems:"center",gap:10,marginTop:8,
                   borderTop:"1px solid #f1f5f9",paddingTop:12}}>
        <button onClick={onClose}
          style={{padding:"8px 16px",fontSize:13,fontWeight:700,cursor:"pointer",
                  border:"1px solid #cbd5e1",borderRadius:8,background:"#fff",color:"#334155"}}>
          Cerrar
        </button>
        <button onClick={guardar} disabled={guardando||cargando}
          style={{padding:"8px 18px",fontSize:13,fontWeight:700,
                  cursor:(guardando||cargando)?"not-allowed":"pointer",
                  border:"none",borderRadius:8,background:"#1e40af",color:"#fff",
                  opacity:(guardando||cargando)?.7:1}}>
          {guardando ? "Guardando…" : "Guardar"}
        </button>
      </div>

      {guardado && (
        <div style={{marginTop:12,display:"flex",alignItems:"center",gap:8,
                     background:"#ecfdf5",border:"1px solid #a7f3d0",color:"#047857",
                     borderRadius:8,padding:"10px 14px",fontSize:13,fontWeight:700}}>
          <span style={{fontSize:16}}>✅</span> Guardado correctamente.
        </div>
      )}
    </Modal>
  );
}
