/* Eje de tiempo · Pieza 3
   Un solo modelo de fechas para Reportes y Agenda. Antes cada rango se armaba
   a mano —"Semana anterior", una ventana de 3 meses que se corría sobre un
   array de 4— así que la etiqueta y los datos se calculaban por separado y al
   navegar decían cosas distintas.

   Hoy es jueves 3 de septiembre de 2026: el prototipo tiene una fecha fija
   para que los rangos sean comprobables.                                   */

const HOY_D = new Date(2026, 8, 3);
const MES_N = ['enero','febrero','marzo','abril','mayo','junio','julio','agosto','septiembre','octubre','noviembre','diciembre'];
const MES_A = ['ENE','FEB','MAR','ABR','MAY','JUN','JUL','AGO','SEP','OCT','NOV','DIC'];
const DIA_N = ['Domingo','Lunes','Martes','Miércoles','Jueves','Viernes','Sábado'];
const dm = (d, n) => { const x = new Date(d); x.setDate(x.getDate() + n); return x; };
const mm = (d, n) => { const x = new Date(d); x.setDate(1); x.setMonth(x.getMonth() + n); return x; };
const mismoDia = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
const lunesDe = d => { const x = new Date(d); const w = (x.getDay() + 6) % 7; return dm(x, -w); };
const fmtD = d => `${d.getDate()} ${MES_A[d.getMonth()].toLowerCase()}`;

/* Fecha real de cada trabajo. Los del prototipo vienen con etiqueta relativa
   (HOY / MAÑANA / SAB) y el historial con '12 AGO': las dos se resuelven acá
   para que todo lo demás trabaje con Date y no con strings.               */
function fechaJob(j) {
  if (j.dia === 'HOY') return HOY_D;
  if (j.dia === 'MAÑANA') return dm(HOY_D, 1);
  if (j.dia === 'SAB') return dm(HOY_D, 2);
  /* Un presupuesto no tiene día de agenda pero sí fecha de emisión. Sin esto
     devolvía null y nunca entraba en ninguna ventana: "presupuestos enviados"
     daba cero en todos los rangos, estructuralmente. */
  if (j.emitido) return fechaHist(j.emitido);
  return null;
}
function fechaHist(cuando) {
  const m = String(cuando).match(/(\d{1,2})\s*([A-ZÁÉÍÓÚ]{3})/i);
  if (!m) return null;
  const i = MES_A.indexOf(m[2].toUpperCase());
  return i < 0 ? null : new Date(2026, i, parseInt(m[1], 10));
}

const RANGOS_T = ['Semana','Mes','90 días','Año'];

/* Un período = ventana [desde, hasta] + los baldes en que se parte + su
   etiqueta. `off` corre la ventana en la unidad del rango, así que la
   etiqueta y los datos salen del MISMO cálculo y no pueden discrepar.    */
function periodo(rango, off) {
  if (rango === 'Semana') {
    const ini = dm(lunesDe(HOY_D), off * 7), fin = dm(ini, 5);
    return { desde:ini, hasta:dm(fin, 1),
      lbl:`${fmtD(ini)} al ${fmtD(fin)}`,
      baldes:Array.from({ length:6 }, (_, i) => { const d = dm(ini, i);
        return { k:DIA_N[d.getDay()] + (mismoDia(d, HOY_D) ? ' · hoy' : ''), desde:d, hasta:dm(d, 1) }; }) };
  }
  if (rango === 'Mes') {
    const ini = mm(HOY_D, off), fin = mm(ini, 1);
    const sem = [];
    let c = new Date(ini), n = 1;
    while (c < fin) { const prox = dm(c, 7) > fin ? new Date(fin) : dm(c, 7);
      sem.push({ k:`Semana ${n}` + (HOY_D >= c && HOY_D < prox ? ' · en curso' : ''), desde:new Date(c), hasta:prox }); c = prox; n++; }
    return { desde:ini, hasta:fin, lbl:`${MES_N[ini.getMonth()]} ${ini.getFullYear()}`, baldes:sem };
  }
  if (rango === '90 días') {
    const fin = mm(HOY_D, 1 + off), ini = mm(fin, -3);
    return { desde:ini, hasta:fin, lbl:`${MES_A[ini.getMonth()]} – ${MES_A[mm(fin,-1).getMonth()]} ${fin.getFullYear()}`,
      baldes:[0,1,2].map(i => { const d = mm(ini, i); return { k:MES_A[d.getMonth()], desde:d, hasta:mm(d, 1) }; }) };
  }
  const y = HOY_D.getFullYear() + off;
  return { desde:new Date(y,0,1), hasta:new Date(y+1,0,1), lbl:String(y),
    baldes:Array.from({ length:12 }, (_, i) => ({ k:MES_A[i], desde:new Date(y,i,1), hasta:new Date(y,i+1,1) })) };
}

/* Todo lo cobrado con su fecha real: trabajos vivos + historial archivado. */
function cobrosCon(jobs) {
  const out = [];
  jobs.filter(j => esCobrado(j.tsm)).forEach(j => { const f = fechaJob(j); if (f) out.push({ f, monto:j.monto, svc:j.svc }); });
  Object.values(HIST).flat().filter(h => esCobrado(h.tsm)).forEach(h => { const f = fechaHist(h.cuando); if (f) out.push({ f, monto:h.monto, svc:h.svc }); });
  return out;
}
const enBalde = (arr, b) => arr.filter(x => x.f >= b.desde && x.f < b.hasta);

/* Navegador de período. Uno solo, usado por Reportes y por Agenda. */
function NavPeriodo({ rango, setRango, off, setOff, lbl, rangos }) {
  return (
    <div style={{ display:'flex', alignItems:'center', gap:10, flexShrink:0 }}>
      {(rangos || RANGOS_T).map(r => (
        <button key={r} onClick={() => { setRango(r); setOff(0); }}
          style={{ display:'inline-flex', alignItems:'center', gap:6, padding:'7px 14px', borderRadius:999, fontFamily:T.sans, fontWeight:500, fontSize:12,
            color:rango===r?T.c100:T.c300, background:rango===r?T.vSoft:'transparent', border:`1px solid ${rango===r?T.vBorder:T.g700}`, cursor:'pointer' }}>{r}</button>
      ))}
      <div style={{ marginLeft:'auto', display:'flex', alignItems:'center', gap:10 }}>
        <button onClick={() => setOff(off - 1)} aria-label="Período anterior" style={{ width:28, height:28, borderRadius:8, background:'transparent', border:`1px solid ${T.g700}`, color:T.c300, cursor:'pointer', fontSize:14, lineHeight:1 }}>‹</button>
        <span style={{ fontFamily:T.mono, fontSize:11, letterSpacing:'.08em', color:T.c100, minWidth:190, textAlign:'center' }}>{lbl}</span>
        <button onClick={() => setOff(off + 1)} aria-label="Período siguiente" style={{ width:28, height:28, borderRadius:8, background:'transparent', border:`1px solid ${T.g700}`, color:T.c300, cursor:'pointer', fontSize:14, lineHeight:1 }}>›</button>
        {off !== 0 && <button onClick={() => setOff(0)} style={{ minHeight:28, padding:'0 10px', borderRadius:8, background:'transparent', border:`1px solid ${T.g700}`, color:T.c500, fontFamily:T.sans, fontSize:11.5, fontWeight:600, cursor:'pointer' }}>Hoy</button>}
      </div>
    </div>
  );
}

Object.assign(window, { HOY_D, MES_N, MES_A, DIA_N, dm, mm, mismoDia, lunesDe, fmtD, fechaJob, fechaHist, RANGOS_T, periodo, cobrosCon, enBalde, NavPeriodo });
