/* Panel web · capa interactiva · Pieza 3b
   El panel no es la mini-app estirada. En 390 px la navegación es una PILA:
   entrás, volvés. En 1180 px eso es un desperdicio — la lista no debería
   desaparecer para ver un trabajo. Acá el detalle es un CAJÓN que entra por
   la derecha y deja la lista visible detrás, que es lo que hace que puedas
   recorrer ocho trabajos sin perder el lugar.

   Tres cosas más que sólo existen acá: edición en el lugar (la configuración
   no navega a otra pantalla), menú de acciones anclado al botón en vez de
   hoja desde abajo, y Esc para salir.                                      */

const P = {
  card:{ background:T.g900, border:`1px solid ${T.g700}`, borderRadius:20, padding:'26px 26px 24px', boxShadow:'0 6px 20px rgba(0,0,0,.22)', display:'flex', flexDirection:'column', minWidth:0 },
  lbl:{ fontFamily:T.mono, fontSize:9, letterSpacing:'.13em', textTransform:'uppercase', color:T.c500 },
};

/* .week-grid / .day-col / .turn verbatim de panel.html:685-748:
     .week-grid repeat(5,1fr) gap 14 — CINCO columnas, no seis
     .day-col   radio 16, padding 16 14, gap 8
     .day-head  space-between baseline, borde abajo, pad-bottom 10, mb 4
     .day-name  mono 11 tracking .14em peso 500 · .day-count sans 11
     .turn      padding 8 10, radio 6, fondo verde al 5%, borde izq 2px
                .turn.edit violeta al 7% · .turn.revert coral al 7%
     .turn-time mono 11 · .turn-name sans 600 12 · .turn-svc sans 11    */
const DAY = {
  grid:{ display:'grid', gridTemplateColumns:'repeat(5,1fr)', gap:14, alignItems:'start' },
  col:{ background:T.g900, border:`1px solid ${T.g700}`, borderRadius:16, padding:'16px 14px', display:'flex', flexDirection:'column', gap:8, minWidth:0 },
  head:{ display:'flex', justifyContent:'space-between', alignItems:'baseline', borderBottom:`1px solid ${T.g700}`, paddingBottom:10, marginBottom:4 },
  name:{ fontFamily:T.mono, fontSize:11, color:T.c100, letterSpacing:'.14em', fontWeight:500 },
  count:{ fontFamily:T.sans, fontSize:11, color:T.c500 },
};
const turnoTono = j => esCobrado(j.tsm) ? { bg:'rgba(29,185,84,.05)', bd:T.green }
  : j.tsm === 'CANCELADO' ? { bg:'rgba(232,106,95,.07)', bd:T.coral }
  : { bg:'rgba(108,99,255,.07)', bd:T.v600 };
const Turno = ({ j, on }) => { const t = turnoTono(j);
  return (
    <button onClick={on} style={{ display:'flex', flexDirection:'column', alignItems:'flex-start', gap:3, padding:'8px 10px', borderRadius:6, background:t.bg, border:'none', borderLeft:`2px solid ${t.bd}`, cursor:'pointer', textAlign:'left', width:'100%' }}>
      <span style={{ fontFamily:T.mono, fontSize:11, color:T.c300 }}>{j.hora}</span>
      <span style={{ fontFamily:T.sans, fontWeight:600, fontSize:12, color:T.c100, width:'100%', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{j.cli}</span>
      <span style={{ fontFamily:T.sans, fontSize:11, color:T.c500, width:'100%', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{j.svc}</span>
    </button>
  );
};

/* ── cajón de detalle ─────────────────────────────────────── */
function Drawer({ open, title, sub, onClose, children, footer, ancho }) {
  React.useEffect(() => {
    if (!open) return;
    const k = e => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', k);
    return () => window.removeEventListener('keydown', k);
  }, [open, onClose]);
  if (!open) return null;
  return (
    <div style={{ position:'absolute', inset:0, zIndex:40, display:'flex', justifyContent:'flex-end' }}>
      <div onClick={onClose} style={{ position:'absolute', inset:0, background:'rgba(8,7,6,.55)', animation:'pwfade 160ms ease-out' }} />
      <aside style={{ position:'relative', width:ancho || 440, maxWidth:'92%', height:'100%', background:T.g950, borderLeft:`1px solid ${T.g700}`,
        boxShadow:'-18px 0 48px rgba(0,0,0,.45)', display:'flex', flexDirection:'column', animation:'pwslide 220ms cubic-bezier(.2,.9,.3,1)' }}>
        <header style={{ flex:'none', display:'flex', alignItems:'flex-start', gap:12, padding:'22px 24px 18px', borderBottom:`1px solid ${T.g800}` }}>
          <div style={{ flex:1, minWidth:0 }}>
            <div style={{ fontFamily:T.sans, fontSize:17, fontWeight:700, color:T.c100, letterSpacing:'-.2px', lineHeight:1.3 }}>{title}</div>
            <div style={{ fontFamily:T.mono, fontSize:10.5, letterSpacing:'.07em', color:T.c500, marginTop:5 }}>{sub}</div>
          </div>
          <button onClick={onClose} aria-label="Cerrar" style={{ width:30, height:30, flex:'none', display:'grid', placeItems:'center', background:'transparent', border:`1px solid ${T.g700}`, borderRadius:8, color:T.c500, fontSize:13, cursor:'pointer', padding:0 }}>✕</button>
        </header>
        <div style={{ flex:1, minHeight:0, overflowY:'auto', padding:'20px 24px 24px', scrollbarWidth:'none', display:'flex', flexDirection:'column', gap:16 }}>{children}</div>
        {footer && <div style={{ flex:'none', padding:'14px 24px 18px', borderTop:`1px solid ${T.g800}`, display:'flex', gap:10 }}>{footer}</div>}
      </aside>
    </div>
  );
}

const PBtn = ({ children, on, tone = 'sec', wide }) => {
  const bg = tone === 'pri' ? T.v600 : tone === 'mal' ? 'transparent' : 'transparent';
  const fg = tone === 'pri' ? '#fff' : tone === 'mal' ? T.coral : T.c100;
  const bd = tone === 'pri' ? T.v600 : tone === 'mal' ? T.coBorder : T.g700;
  return (
    <button onClick={on} style={{ flex:wide?1:'none', minHeight:42, padding:'0 18px', borderRadius:10, background:bg, border:`1px solid ${bd}`, color:fg,
      fontFamily:T.sans, fontSize:13.5, fontWeight:600, cursor:'pointer', transition:'background 160ms ease, border-color 160ms ease' }}>{children}</button>
  );
};

/* ── menú de acciones anclado ─────────────────────────────────
   En el celular la hoja sube desde abajo porque el pulgar está ahí. Con mouse
   el menú tiene que salir DONDE hiciste click, no en el otro extremo. */
function AccMenu({ job, patron, onAccion, onRelevar, onPasar, onClose }) {
  const v = VOZ[patron] || VOZ.C;
  /* Sin backdrop. Un div que cubre para capturar el click de afuera es un
     bloqueador invisible: en fixed tapaba la página entera —los otros dos
     teléfonos incluidos— y sobrevivía al scroll. Escuchar el pointerdown
     cierra el menú SIN comerse el click, que además es lo correcto: si el
     tipo va a otra cosa, que llegue de una. */
  const pop = React.useRef(null);
  React.useEffect(() => {
    const fuera = e => { const w = pop.current && pop.current.parentElement;
      if (w && !w.contains(e.target)) onClose(); };
    const esc = e => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('pointerdown', fuera, true);
    window.addEventListener('keydown', esc);
    return () => { document.removeEventListener('pointerdown', fuera, true); window.removeEventListener('keydown', esc); };
  }, [onClose]);
  const acc = job.tsm === 'RELEVADO' ? [['FINALIZADO','Finalizado'],['CANCELADO','Cancelar']] : accionesDe(patron, job.tsm);
  const abierto = !esCierre(job.tsm);
  const puedeReagendar = abierto && job.hora && job.hora !== '—';
  const item = (lbl, wa, col, on, falta) => (
    <button key={lbl} onClick={on} style={{ display:'flex', flexDirection:'column', alignItems:'flex-start', gap:3, width:'100%', padding:'11px 14px', background:'transparent', border:'none', borderTop:`1px solid ${T.g800}`, cursor:'pointer', textAlign:'left' }}>
      <span style={{ display:'flex', alignItems:'center', gap:8, width:'100%' }}>
        <span style={{ fontFamily:T.sans, fontSize:13.5, fontWeight:600, color:col }}>{lbl}</span>
        {falta && <span style={{ marginLeft:'auto', fontFamily:T.mono, fontSize:7.5, letterSpacing:'.1em', color:T.c500, background:T.g800, border:`1px solid ${T.g700}`, borderRadius:4, padding:'2px 5px' }}>FALTA EN TSM</span>}
      </span>
      <span style={{ fontFamily:T.sans, fontSize:11.5, lineHeight:1.4, color:T.c500 }}>“{wa}”</span>
    </button>
  );
  return (
    <div ref={pop} style={{ position:'absolute', right:0, bottom:'calc(100% + 8px)', zIndex:45, width:320, background:T.g900, border:`1px solid ${T.g700}`, borderRadius:14, boxShadow:'0 18px 48px rgba(0,0,0,.55)', overflow:'hidden', animation:'pwpop 140ms cubic-bezier(.2,.9,.3,1)' }}>
        <div style={{ padding:'12px 14px', fontFamily:T.mono, fontSize:9, letterSpacing:'.13em', textTransform:'uppercase', color:T.c500 }}>Qué pasó · le escribe a {job.cli.split(' ')[0]}</div>
        {acc.map(([est,lbl]) => { const t = EST_TONO[est];
          return item(lbl, MSG_WA[est], t === 'coral' ? T.coral : t === 'green' ? T.green : T.c100, () => onAccion(est));
        })}
        {puedeReagendar && item(PROPUESTAS.REAGENDAR.lbl(v), PROPUESTAS.REAGENDAR.wa(v), T.v600, onPasar, true)}
    </div>
  );
}

/* ── toast del panel ──────────────────────────────────────────
   Arriba a la derecha: en escritorio la mirada vuelve ahí después de hacer
   click en un botón de barra, y no tapa la tabla que acabás de tocar.     */
function PToast({ msg, tono, k }) {
  const bg = tono === 'ok' ? T.green : tono === 'mal' ? T.coral : T.v600;
  const fg = tono === 'ok' ? '#08240F' : tono === 'mal' ? '#3B120D' : '#FFFFFF';
  return (
    <div style={{ position:'absolute', top:76, right:24, zIndex:50, minWidth:280, maxWidth:400, padding:'13px 18px', background:bg, borderRadius:12,
      boxShadow:'0 14px 40px rgba(0,0,0,.5)', display:'flex', flexDirection:'column', gap:3, pointerEvents:'none', animation:'pwtoast 2.6s cubic-bezier(.2,.9,.3,1) forwards' }}>
      <span style={{ fontFamily:T.sans, fontSize:14.5, fontWeight:700, color:fg, letterSpacing:'-.1px' }}>{msg}</span>
      <span style={{ fontFamily:T.mono, fontSize:8.5, letterSpacing:'.11em', textTransform:'uppercase', color:fg }}>{k}</span>
    </div>
  );
}

/* ── detalle del trabajo, dentro del cajón ────────────────── */
function DrawerJob({ job, cfg, onPaso, onNota, onDoc, onFoto }) {
  const pago = esCobrado(job.tsm), canc = job.tsm === 'CANCELADO';
  const pasos = pasosDe(cfg), ult = pasos.length - 1;
  const paso = pago ? ult : job.paso;
  const esPres = job.dia === 'PRESUPUESTO';
  const [nota, setNota] = React.useState('');
  const notas = job.notas || [];
  return (
    <>
      <div style={{ ...P.card, padding:'20px 22px 18px', gap:14 }}>
        <div style={{ display:'flex', alignItems:'baseline', gap:12 }}>
          <div>
            <div style={P.lbl}>{pago ? 'Cobrado' : canc ? 'No se cobró' : 'A cobrar'}</div>
            <div style={{ fontFamily:T.mono, fontSize:26, fontWeight:500, color:pago?T.green:canc?T.c500:T.c100, letterSpacing:'-.8px', marginTop:6, textDecoration:canc?'line-through':'none' }}>{money(job.monto)}</div>
          </div>
          <div style={{ marginLeft:'auto', textAlign:'right' }}>
            <div style={P.lbl}>Cuándo</div>
            <div style={{ fontFamily:T.mono, fontSize:13, color:T.c300, marginTop:6 }}>{job.dia}{job.hora !== '—' && ' · ' + job.hora}</div>
          </div>
        </div>
        <div style={{ display:'flex', alignItems:'center', gap:10, paddingTop:13, borderTop:`1px solid ${T.g800}` }}>
          <WBadge tsm={job.tsm} />
          <span style={{ fontFamily:T.sans, fontSize:12.5, color:T.c500 }}>{job.extra}</span>
        </div>
      </div>

      <Bitacora job={job} />

      <div style={{ ...P.card, padding:'20px 22px 18px', gap:12 }}>
        <div style={{ display:'flex', alignItems:'baseline' }}>
          <span style={P.lbl}>Estado del trabajo</span>
          <span style={{ ...P.lbl, marginLeft:'auto' }}>Quién lo marcó</span>
        </div>
        {/* Ver Detalle: hist manda, también al pintar. */}
        {pasos.map((k,i) => { const d = pasoDe(k, cfg.patron, job), ev = evidencia(job, k);
          const por = (job.hist||[])[i] || (ev ? d.por : null), ok = !!por;
          const tocable = !esCierre(job.tsm) && i === paso + 1 && !d.auto;
          /* Ver Detalle: pendiente es botón, hecho es hito. */
          if (d.ir && !ok) return (
            <button key={k} onClick={() => !esCierre(job.tsm) && onDoc('items')} disabled={esCierre(job.tsm)}
              style={{ display:'flex', alignItems:'center', gap:10, minHeight:44, width:'100%', margin:'4px 0 6px', padding:'0 13px', background:T.vSoft, border:`1px solid ${T.vBorder}`, borderRadius:11, cursor:esCierre(job.tsm)?'default':'pointer', textAlign:'left' }}>
              <span style={{ width:20, height:20, flex:'none', borderRadius:6, display:'grid', placeItems:'center', background:T.v600, color:'#fff', fontSize:13, lineHeight:1 }}>+</span>
              <span style={{ flex:1, minWidth:0 }}>
                <span style={{ display:'block', fontFamily:T.sans, fontSize:13, fontWeight:700, color:T.c100 }}>{d.t}</span>
                <span style={{ display:'block', fontFamily:T.sans, fontSize:11.5, color:T.c500, marginTop:1 }}>{d.x}</span>
              </span>
              <span style={{ flex:'none', fontFamily:T.mono, fontSize:8, letterSpacing:'.1em', color:T.c300 }}>ABRIR →</span>
            </button>
          );
          return (
            <button key={k} onClick={() => { if (esCierre(job.tsm) || d.auto) return; if (d.ir === 'items') { onDoc('items'); return; } onPaso(job.id, i); }} disabled={esCierre(job.tsm) || d.auto}
              style={{ display:'flex', alignItems:'center', gap:12, minHeight:38, width:'100%', background:'transparent', border:'none', padding:0, textAlign:'left', cursor:esCierre(job.tsm)?'default':'pointer' }}>
              <span style={{ width:20, height:20, flex:'none', borderRadius:8, display:'grid', placeItems:'center', background:ok?T.gSoft:'transparent', border:`1px solid ${ok?T.gBorder:T.g700}`, color:ok?T.green:T.g700, fontSize:10 }}>{ok?'✓':''}</span>
              <span style={{ flex:1, minWidth:0 }}>
                <span style={{ display:'block', fontFamily:T.sans, fontSize:13.5, fontWeight:ok?600:400, color:ok?T.c100:T.c500 }}>{ok && d.th ? d.th : d.t}</span>
                {!ok && <span style={{ display:'block', fontFamily:T.sans, fontSize:11.5, color:T.c500, marginTop:2 }}>{d.x}</span>}
              </span>
              {por
                ? <span style={{ flex:'none', fontFamily:T.mono, fontSize:8, letterSpacing:'.1em', padding:'3px 6px', borderRadius:4, color:por==='mia'?T.c100:T.c300, background:por==='mia'?T.vSoft:T.g800, border:`1px solid ${por==='mia'?T.vBorder:T.g700}` }}>{por==='mia'?'MIA':'VOS'}</span>
                : d.auto ? <span style={{ flex:'none', fontFamily:T.mono, fontSize:8, letterSpacing:'.1em', color:T.c500 }}>AUTOMÁTICO</span>
                : (tocable || d.ir) && <span style={{ flex:'none', fontFamily:T.mono, fontSize:8, letterSpacing:'.1em', color:T.c300 }}>{d.ir ? 'ABRIR →' : 'CLIC'}</span>}
              {ok && !esCierre(job.tsm) && i === job.paso && !MSG_WA[k] && <span style={{ flex:'none', fontFamily:T.mono, fontSize:8, letterSpacing:'.1em', color:T.c500 }}>DESHACER</span>}
            </button>
          );
        })}
      </div>

      {(pago || esPres) && (
        <button onClick={() => onDoc(pago ? 'recibo' : 'presupuesto')} style={{ ...P.card, padding:'16px 20px', flexDirection:'row', alignItems:'center', gap:13, cursor:'pointer', textAlign:'left' }}>
          <span style={{ width:28, height:34, flex:'none', borderRadius:4, border:`1px solid ${pago?T.gBorder:T.vBorder}`, background:pago?T.gSoft:T.vSoft, display:'grid', placeItems:'center', fontFamily:T.mono, fontSize:8, color:pago?T.green:T.v600 }}>{pago?'REC':'PRE'}</span>
          <span style={{ flex:1, minWidth:0 }}>
            <span style={{ display:'block', fontFamily:T.sans, fontSize:14, fontWeight:600, color:T.c100 }}>{pago ? `Recibo N° 00${job.id}` : `Presupuesto N° ${job.id}`}</span>
            <span style={{ display:'block', fontFamily:T.mono, fontSize:9.5, letterSpacing:'.09em', color:T.c500, marginTop:3 }}>{pago ? 'EMITIDO Y ENVIADO' : job.enviado ? 'ENVIADO · SIN RESPUESTA' : 'SIN ENVIAR'}</span>
          </span>
          <span style={{ color:T.c500, fontSize:13 }}>→</span>
        </button>
      )}

      <div style={{ ...P.card, padding:'20px 22px 18px', gap:11 }}>
        <span style={P.lbl}>Anotaciones {notas.length ? `· ${notas.length}` : ''}</span>
        {/* La foto sacada desde el celular tiene que VERSE acá: antes la web
            mostraba sólo el texto y no había manera de saber que había una
            imagen cargada. Miniatura de 56 px, la misma que el teléfono. */}
        {notas.map((n,i) => (
          <div key={i} style={{ display:'flex', gap:11, alignItems:'flex-start', paddingTop:i?11:0, borderTop:i?`1px solid ${T.g800}`:'none' }}>
            {n.foto ? <Miniatura n={n} /> : <span style={{ width:3, alignSelf:'stretch', flex:'none', borderRadius:9, background:T.vBorder, display:'block' }} />}
            <span style={{ flex:1, minWidth:0 }}>
              <span style={{ display:'block', fontFamily:T.sans, fontSize:13, lineHeight:1.5, color:T.c300 }}>{n.t}</span>
              <span style={{ display:'block', fontFamily:T.mono, fontSize:9, letterSpacing:'.09em', color:T.c500, marginTop:3 }}>{n.cuando}{n.foto ? ' · DESDE EL CELULAR' : ''}</span>
            </span>
          </div>
        ))}
        <div style={{ display:'flex', gap:8 }}>
          <input value={nota} onChange={e => setNota(e.target.value)} placeholder="Lo que viste, una medida, un pendiente…"
            onKeyDown={e => { if (e.key === 'Enter' && nota.trim()) { onNota(job.id, nota.trim()); setNota(''); } }}
            style={{ flex:1, minWidth:0, height:40, boxSizing:'border-box', padding:'0 12px', background:T.g950, border:`1px solid ${nota?T.vBorder:T.g700}`, borderRadius:10, color:T.c100, fontFamily:T.sans, fontSize:13, outline:'none' }} />
          <PBtn on={() => { if (nota.trim()) { onNota(job.id, nota.trim()); setNota(''); } }}>Anotar</PBtn>
          {onFoto && <PBtn on={() => onFoto(job.id)}>Foto</PBtn>}
        </div>
      </div>
    </>
  );
}

Object.assign(window, { Drawer, PBtn, AccMenu, PToast, DrawerJob, P, DAY, Turno, turnoTono });
