// Tabla de solicitudes + ficha detallada
const { useState: useStateR, useMemo: useMemoR, useEffect: useEffectR } = React;
const PAGE = 15;

// Helpers para tipo de solicitud
const TIPO_LABEL = { solicitud: 'Solicitud de código', cambio: 'Cambio de código' };
function getTipo(r) { return r.tipo === 'cambio' ? 'cambio' : 'solicitud'; }

function RequestsView({ reqs, user, filters, setFilters, openReq, selected, toast }) {
  const f = { q: '', status: '', prov: '', assignee: '', from: '', to: '', stale: false, tipo: '', ...filters };
  const [sort, setSort] = useStateR({ k: 'createdAt', dir: -1 });
  const [page, setPage] = useStateR(0);
  const set = (k, v) => { setFilters({ ...f, [k]: v }); setPage(0); };
  const staleIds = useMemoR(() => new Set(S.stale(reqs).map(r => r.id)), [reqs]);

  const base = useMemoR(() => {
    const q = f.q.trim().toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
    return reqs.filter(r => {
      if (f.tipo && getTipo(r) !== f.tipo) return false;
      if (f.prov && r.negocio.provincia !== f.prov) return false;
      if (f.assignee === '_none' ? r.assignee : f.assignee && r.assignee !== f.assignee) return false;
      if (f.from && r.createdAt.slice(0, 10) < f.from) return false;
      if (f.to && r.createdAt.slice(0, 10) > f.to) return false;
      if (f.stale && !staleIds.has(r.id)) return false;
      if (q) {
        const hay = [r.id, r.responsable.firstName + ' ' + r.responsable.lastName, r.negocio.name, r.responsable.idNumber, r.negocio.idNumber, r.responsable.email, r.negocio.email].join(' ').toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
        if (!hay.includes(q.replace(/[\s-]/g, '')) && !hay.includes(q)) return false;
      }
      return true;
    });
  }, [reqs, f.q, f.tipo, f.prov, f.assignee, f.from, f.to, f.stale]);
  const rows = useMemoR(() => {
    const r = f.status ? base.filter(x => x.status === f.status) : base;
    const val = x => sort.k === 'responsable' ? x.responsable.firstName + x.responsable.lastName : sort.k === 'negocio' ? x.negocio.name : sort.k === 'provincia' ? x.negocio.provincia : x[sort.k];
    return [...r].sort((a, b) => String(val(a)).localeCompare(String(val(b)), 'es') * sort.dir);
  }, [base, f.status, sort]);
  const counts = useMemoR(() => Object.fromEntries(S.STATUSES.map(s => [s.id, base.filter(r => r.status === s.id).length])), [base]);
  const pages = Math.max(1, Math.ceil(rows.length / PAGE));
  const pg = Math.min(page, pages - 1);
  const view = rows.slice(pg * PAGE, pg * PAGE + PAGE);
  const active = Object.entries(f).filter(([k, v]) => v && k !== 'status' && k !== 'tipo').length;
  const tipoCount = { solicitud: reqs.filter(r => getTipo(r) === 'solicitud').length, cambio: reqs.filter(r => getTipo(r) === 'cambio').length };

  const Th = ({ k, children }) => <th><button onClick={() => setSort({ k, dir: sort.k === k ? -sort.dir : -1 })}>{children}{sort.k === k && <Icon name="chevronDown" size={13} style={{ transform: sort.dir > 0 ? 'rotate(180deg)' : '' }} />}</button></th>;

  return (
    <div className="ga-card" style={{ overflow: 'hidden' }}>
      <div className="ga-filters">
        <div className="ga-search">
          <Icon name="search" size={18} />
          <input className="input" placeholder="Buscar por nombre, identificación o N.° de solicitud" value={f.q} onChange={e => set('q', e.target.value)} aria-label="Buscar" />
        </div>
        <select className="select" value={f.prov} onChange={e => set('prov', e.target.value)} aria-label="Provincia"><option value="">Provincia: todas</option>{PROVS.map(p => <option key={p}>{p}</option>)}</select>
        <select className="select" value={f.assignee} onChange={e => set('assignee', e.target.value)} aria-label="Responsable"><option value="">Responsable: todos</option><option value="_none">Sin asignar</option>{S.db.users.filter(u => u.role !== 'consulta').map(u => <option key={u.id} value={u.id}>{u.name}</option>)}</select>
        <input className="input" type="date" value={f.from} onChange={e => set('from', e.target.value)} aria-label="Desde" title="Desde" />
        <input className="input" type="date" value={f.to} onChange={e => set('to', e.target.value)} aria-label="Hasta" title="Hasta" />
        {active > 0 && <button className="btn btn-text btn-sm" onClick={() => { setFilters({ status: f.status, tipo: f.tipo }); setPage(0); }}><Icon name="x" size={15} /> Limpiar</button>}
        <div style={{ marginLeft: 'auto' }}><ExportMenu rows={rows} user={user} toast={toast} /></div>
      </div>

      {/* Selector de tipo de formulario */}
      <div className="ga-tipo-bar">
        <button className={'ga-tipo-btn' + (!f.tipo ? ' on' : '')} onClick={() => set('tipo', '')}>
          <Icon name="list" size={15} /> Todos <em>{reqs.length}</em>
        </button>
        <button className={'ga-tipo-btn solicitud' + (f.tipo === 'solicitud' ? ' on' : '')} onClick={() => set('tipo', 'solicitud')}>
          <Icon name="file" size={15} /> Solicitudes <em>{tipoCount.solicitud}</em>
        </button>
        <button className={'ga-tipo-btn cambio' + (f.tipo === 'cambio' ? ' on' : '')} onClick={() => set('tipo', 'cambio')}>
          <Icon name="refresh" size={15} /> Cambios <em>{tipoCount.cambio}</em>
        </button>
      </div>

      <div className="ga-chips">
        <button className={'ga-chip' + (!f.status ? ' on' : '')} onClick={() => set('status', '')}>Todas <em>{base.length}</em></button>
        {S.STATUSES.map(s => <button key={s.id} className={'ga-chip' + (f.status === s.id ? ' on' : '')} onClick={() => set('status', s.id)}><i style={{ background: f.status === s.id ? '#fff' : s.color }} />{s.label} <em>{counts[s.id]}</em></button>)}
        {f.stale && <button className="ga-chip on" style={{ background: 'var(--red-ink)', borderColor: 'var(--red-ink)' }} onClick={() => set('stale', false)}><Icon name="alert" size={14} /> Requieren atención <Icon name="x" size={13} /></button>}
      </div>

      {rows.length === 0 ? <div className="ga-empty"><b>No hay resultados</b>Probá con otros filtros o términos de búsqueda.</div> : <>
        <div className="ga-table-wrap">
          <table className="ga-table">
            <thead><tr>
              <Th k="id">N.° solicitud</Th><Th k="createdAt">Ingreso</Th><Th k="responsable">Responsable</Th><Th k="negocio">Negocio</Th>
              <th>Identificación</th><Th k="provincia">Provincia</Th><th>Teléfono</th><th>Correo</th><Th k="status">Estado</Th><th>Asignado a</th><Th k="updatedAt">Actualizado</Th>
            </tr></thead>
            <tbody>{view.map(r => (
              <tr key={r.id} className={selected === r.id ? 'sel' : ''} onClick={() => openReq(r.id)} tabIndex={0} onKeyDown={e => e.key === 'Enter' && openReq(r.id)}>
                <td><span className="id mono">{r.id}</span>{!r.demo && r.status === 'recibida' && <span className="new-tag">NUEVA</span>}{r.demo && <span className="demo-tag">DEMO</span>}<span className={'tipo-tag tipo-tag--' + getTipo(r)}>{getTipo(r) === 'cambio' ? 'CAMBIO' : 'SOLICITUD'}</span></td>
                <td className="muted">{GFmt.date(r.createdAt)}</td>
                <td className="strong">{r.responsable.firstName} {r.responsable.lastName}</td>
                <td className="strong">{r.negocio.name}</td>
                <td className="tnum muted">{GFmt.idNum(r.negocio.idType, r.negocio.idNumber)}</td>
                <td>{r.negocio.provincia}</td>
                <td className="tnum muted">{GFmt.phone('', r.responsable.phone)}</td>
                <td className="muted" style={{ maxWidth: 200, overflow: 'hidden', textOverflow: 'ellipsis' }}>{r.responsable.email}</td>
                <td><StatusPill id={r.status} short />{staleIds.has(r.id) && <span title="Sin movimiento reciente" style={{ color: 'var(--red)', marginLeft: 6, verticalAlign: -3, display: 'inline-block' }}><Icon name="clock" size={15} /></span>}</td>
                <td><Assignee uid={r.assignee} /></td>
                <td className="muted">{GFmt.rel(r.updatedAt)}</td>
              </tr>))}</tbody>
          </table>
        </div>
        <div className="ga-cards">{view.map(r => (
          <div className="ga-rc" key={r.id} onClick={() => openReq(r.id)}>
            <div className="ga-rc-top"><span className="mono" style={{ fontSize: 12.5, color: 'var(--blue)', fontWeight: 600 }}>{r.id}{r.demo && <span className="demo-tag" style={{ fontSize: 10, color: '#8A5A00', background: 'var(--yellow-50)', padding: '1px 5px', borderRadius: 4, marginLeft: 6 }}>DEMO</span>}<span className={'tipo-tag tipo-tag--' + getTipo(r)} style={{ marginLeft: 6 }}>{getTipo(r) === 'cambio' ? 'CAMBIO' : 'SOLICITUD'}</span></span><StatusPill id={r.status} short /></div>
            <b>{r.negocio.name}</b>
            <div style={{ fontSize: 13, color: 'var(--ink-2)' }}>{r.responsable.firstName} {r.responsable.lastName}</div>
            <div className="ga-rc-meta"><span>{GFmt.date(r.createdAt)}</span><span>{r.negocio.provincia}</span><span>{r.assignee ? S.userName(r.assignee) : 'Sin asignar'}</span></div>
          </div>))}</div>
        <div className="ga-pager">
          <span>Mostrando {pg * PAGE + 1}–{Math.min(rows.length, pg * PAGE + PAGE)} de {rows.length}</span>
          <div className="ga-pager-b">
            <button className="btn btn-ghost btn-sm" disabled={pg === 0} onClick={() => setPage(pg - 1)} aria-label="Anterior"><Icon name="chevronLeft" size={16} /></button>
            <span style={{ alignSelf: 'center', padding: '0 8px' }}>{pg + 1} / {pages}</span>
            <button className="btn btn-ghost btn-sm" disabled={pg >= pages - 1} onClick={() => setPage(pg + 1)} aria-label="Siguiente"><Icon name="chevronRight" size={16} /></button>
          </div>
        </div>
      </>}
    </div>
  );
}

// ---------- Ficha ----------
const DOC_LABEL = { cedula: 'Cédula del representante legal', evidencia: 'Referencia visual del negocio', personeria: 'Personería jurídica' };

function RequestDrawer({ id, user, onClose, toast }) {
  const r = S.get(id);
  const [to, setTo] = useStateR(null);
  const [note, setNote] = useStateR('');
  const [notify, setNotify] = useStateR(true);
  const [cmt, setCmt] = useStateR('');
  useEffectR(() => { setTo(null); setNote(''); setCmt(''); }, [id]);
  useEffectR(() => { const k = e => e.key === 'Escape' && onClose(); window.addEventListener('keydown', k); return () => window.removeEventListener('keydown', k); }, []);
  if (!r) return null;
  const manage = S.canManage(user, r);
  const canAssign = S.can(user, 'assign');
  const needsNote = to === 'pendiente' || to === 'rechazada';
  const rules = S.db.settings.rules;

  function applyStatus() {
    if (!to || to === r.status) return;
    if (needsNote && !note.trim()) return;
    S.setStatus(r.id, to, note.trim(), user, notify);
    toast(`Estado actualizado a "${S.STATUS[to].label}".`);
    setTo(null); setNote('');
  }
  function addComment() { if (!cmt.trim()) return; S.comment(r.id, cmt.trim(), user); setCmt(''); toast('Observación agregada.'); }
  const copy = (v) => { navigator.clipboard && navigator.clipboard.writeText(v); toast('Copiado al portapapeles.'); };
  const D = ({ k, v, full, cp }) => <div className={full ? 'full' : ''}><dt>{k}</dt><dd>{v || '—'}{cp && v && <button className="ga-cp" onClick={() => copy(cp === true ? v : cp)} aria-label={'Copiar ' + k}><Icon name="copy" size={14} /></button>}</dd></div>;

  const histText = h => {
    const who = <b>{S.userName(h.by)}</b>;
    if (h.type === 'created') return <>{who} envió la solicitud</>;
    if (h.type === 'status') return <>{who} cambió el estado de <StatusPill id={h.from} short /> a <StatusPill id={h.to} short /></>;
    if (h.type === 'assign') return h.to ? <>{who} asignó a <b>{S.userName(h.to)}</b></> : <>{who} quitó la asignación</>;
    if (h.type === 'comment') return <>{who} agregó una observación interna</>;
    if (h.type === 'notify') return <>{who} preparó una notificación</>;
    return who;
  };
  const histIc = { created: 'send', status: 'refresh', assign: 'user', comment: 'message', notify: 'mail' };

  return (
    <>
      <div className="ga-drawer-bg" onClick={onClose} />
      <aside className="ga-drawer" role="dialog" aria-modal="true" aria-label={'Solicitud ' + r.id} data-screen-label="Ficha de solicitud">
        <div className="ga-dh">
          <div className="ga-dh-t">
            <div className="ga-dh-id"><b className="mono">{r.id}</b><StatusPill id={r.status} /><span className={'tipo-tag tipo-tag--' + getTipo(r)}>{getTipo(r) === 'cambio' ? '🔄 Cambio de código' : '📋 Solicitud de código'}</span>{r.demo && <span className="pill no-dot" style={{ background: 'var(--yellow-50)', color: '#8A5A00' }}>Dato ficticio de demostración</span>}</div>
            <h2>{r.negocio.name}</h2>
            <p>Ingresó el {GFmt.dateTime(r.createdAt)} · Actualizada {GFmt.rel(r.updatedAt)}</p>
          </div>
          <button className="ga-icobtn" onClick={onClose} aria-label="Cerrar"><Icon name="x" size={20} /></button>
        </div>
        <div className="ga-db">
          <div className="ga-db-l">
            <section className="ga-card ga-sec"><div className="ga-card-b">
              <h3 style={{ marginBottom: 14 }}><Icon name="user" size={18} /> Información del responsable</h3>
              <dl className="ga-dl">
                <D k="Nombre completo" v={`${r.responsable.firstName} ${r.responsable.lastName}`} />
                <D k={ID_TYPES[r.responsable.idType]} v={GFmt.idNum(r.responsable.idType, r.responsable.idNumber)} cp={r.responsable.idNumber} />
                <D k="Fecha de nacimiento" v={new Date(r.responsable.birthDate + 'T12:00').toLocaleDateString('es-CR', { day: 'numeric', month: 'long', year: 'numeric' })} />
                <D k="Teléfono" v={GFmt.phone(r.responsable.phoneCode, r.responsable.phone)} cp={r.responsable.phoneCode + r.responsable.phone} />
                <D k="Correo electrónico" v={r.responsable.email} full cp />
              </dl>
            </div></section>
            <section className="ga-card ga-sec"><div className="ga-card-b">
              <h3 style={{ marginBottom: 14 }}><Icon name="store" size={18} /> Datos del negocio</h3>
              <dl className="ga-dl">
                <D k="Nombre o razón social" v={r.negocio.name} full cp />
                <D k={ID_TYPES[r.negocio.idType]} v={GFmt.idNum(r.negocio.idType, r.negocio.idNumber)} cp={r.negocio.idNumber} />
                <D k="Teléfono del negocio" v={GFmt.phone(r.negocio.phoneCode, r.negocio.phone)} cp={r.negocio.phoneCode + r.negocio.phone} />
                <D k="Correo de facturación" v={r.negocio.email} full cp />
                <D k="Provincia / Cantón / Distrito" v={`${r.negocio.provincia} › ${r.negocio.canton} › ${r.negocio.distrito}`} full />
                <D k="Dirección exacta" v={r.negocio.direccion} full />
              </dl>
            </div></section>
            <section className="ga-card ga-sec"><div className="ga-card-b">
              <h3 style={{ marginBottom: 14 }}><Icon name="clip" size={18} /> Documentos adjuntos</h3>
              <div className="ga-docs">
                {['cedula', 'evidencia', 'personeria'].map(slot => {
                  const d = r.docs.find(x => x.slot === slot);
                  if (!d) return <div className="ga-doc missing" key={slot}><div className="ga-doc-p"><span className="ph"><Icon name="file" size={22} />NO APORTADO</span></div><div className="ga-doc-b"><small>{DOC_LABEL[slot]}</small><b style={{ color: 'var(--gray-500)' }}>{slot === 'personeria' ? 'No aplica / no aportado' : 'Falta documento'}</b></div></div>;
                  const pdf = /pdf/.test(d.type);
                  return <div className="ga-doc" key={slot}>
                    <div className="ga-doc-p">{d.thumb ? <img src={d.thumb} alt={d.name} /> : <span className="ph mono"><Icon name={pdf ? 'file' : 'image'} size={22} />{pdf ? 'PDF' : 'IMAGEN'}</span>}</div>
                    <div className="ga-doc-b"><small>{DOC_LABEL[slot]}</small><b title={d.name}>{d.name}</b><small>{GFmt.bytes(d.size)}</small></div>
                  </div>;
                })}
              </div>
              <p style={{ fontSize: 12, color: 'var(--gray-500)', marginTop: 12, display: 'flex', gap: 6, alignItems: 'center' }}><Icon name="lock" size={14} /> En producción los archivos se sirven desde almacenamiento privado mediante enlaces temporales firmados.</p>
            </div></section>
            <section className="ga-card ga-sec"><div className="ga-card-b">
              <h3 style={{ marginBottom: 14 }}><Icon name="clock" size={18} /> Historial y observaciones</h3>
              {S.can(user, 'manage') ? (
                <div className="ga-cmt">
                  <textarea className="textarea" placeholder="Agregar una observación interna (no visible para el solicitante)…" value={cmt} onChange={e => setCmt(e.target.value)} />
                  <div className="ga-row"><span style={{ fontSize: 12, color: 'var(--gray-500)' }}>Se registra con tu usuario, fecha y hora.</span><button className="btn btn-primary btn-sm" style={{ marginLeft: 'auto' }} disabled={!cmt.trim()} onClick={addComment}><Icon name="message" size={16} /> Agregar observación</button></div>
                </div>) : <div className="ga-info" style={{ marginBottom: 16 }}><Icon name="lock" size={16} /> Tu rol es de solo consulta.</div>}
              <ol className="ga-tl">
                {[...r.history].reverse().map((h, i) => (
                  <li key={i}>
                    <span className={'ga-tl-ic ' + h.type}><Icon name={histIc[h.type] || 'info'} size={14} /></span>
                    <div>
                      <div className="ga-tl-h">{histText(h)}</div>
                      <div className="ga-tl-m">{GFmt.dateTime(h.at)}</div>
                      {h.text && <div className={'ga-tl-txt' + (h.type === 'comment' ? ' c' : '')}>{h.text}</div>}
                    </div>
                  </li>))}
              </ol>
            </div></section>
          </div>

          <div className="ga-db-r">
            <section className="ga-card ga-sec"><div className="ga-card-b">
              <h3 style={{ marginBottom: 12 }}><Icon name="users" size={18} /> Colaborador asignado</h3>
              {canAssign ? (
                <select className="select" style={{ height: 46, fontSize: 14 }} value={r.assignee || ''} onChange={e => { S.assign(r.id, e.target.value || null, user); toast(e.target.value ? `Asignada a ${S.userName(e.target.value)}.` : 'Asignación removida.'); }}>
                  <option value="">Sin asignar</option>
                  {S.db.users.filter(u => u.role !== 'consulta' && u.active).map(u => <option key={u.id} value={u.id}>{u.name} · {S.ROLES[u.role].label}</option>)}
                </select>
              ) : (
                <div className="ga-row"><Assignee uid={r.assignee} />{!r.assignee && S.can(user, 'manage') && <button className="btn btn-ghost btn-sm" style={{ marginLeft: 'auto' }} onClick={() => { S.assign(r.id, user.id, user); toast('Te asignaste la solicitud.'); }}>Tomar solicitud</button>}</div>
              )}
              {rules.notifyAssign && canAssign && <p style={{ fontSize: 12, color: 'var(--gray-500)', marginTop: 8 }}>Se notifica al colaborador al asignar.</p>}
            </div></section>

            <section className="ga-card ga-sec"><div className="ga-card-b">
              <h3 style={{ marginBottom: 12 }}><Icon name="refresh" size={18} /> Cambiar estado</h3>
              {!manage && <div className="ga-info" style={{ marginBottom: 10 }}><Icon name="lock" size={16} /><span>{S.can(user, 'manage') ? 'Solo el colaborador asignado o un supervisor puede cambiar el estado.' : 'Tu rol no permite modificar solicitudes.'}</span></div>}
              <div className="ga-status-pick">
                {S.STATUSES.map(s => (
                  <button key={s.id} className={'ga-sp' + ((to || r.status) === s.id ? ' on' : '')} disabled={!manage} style={(to || r.status) === s.id ? { borderColor: s.color, background: s.bg, color: s.color } : null} onClick={() => setTo(s.id === r.status ? null : s.id)}>
                    <i style={{ background: s.color }} />{s.label}{r.status === s.id && <span className="cur">ACTUAL</span>}
                  </button>))}
              </div>
              {to && to !== r.status && (
                <div className="ga-note">
                  <label className="ga-fl" style={{ fontSize: 13 }}>{needsNote ? <>Motivo <span style={{ color: 'var(--red)' }}>*</span></> : 'Nota (opcional)'}</label>
                  <textarea className="textarea" value={note} onChange={e => setNote(e.target.value)} placeholder={to === 'pendiente' ? 'Indicá qué información o documento falta…' : to === 'rechazada' ? 'Motivo del rechazo…' : to === 'aprobada' ? 'Ej.: código creado en el sistema comercial…' : ''} />
                  {needsNote && !note.trim() && <p className="gf-error" style={{ fontSize: 12 }}><Icon name="alert" size={14} /> El motivo es obligatorio para este estado.</p>}
                  <label className="ga-tgl" style={{ opacity: rules.statusEmails ? 1 : .55 }}>
                    <input type="checkbox" checked={notify && rules.statusEmails} disabled={!rules.statusEmails} onChange={e => setNotify(e.target.checked)} />
                    {rules.statusEmails ? 'Notificar al solicitante por correo' : 'Correos de estado desactivados en Automatizaciones'}
                  </label>
                  <div className="ga-row">
                    <button className="btn btn-ghost btn-sm" onClick={() => { setTo(null); setNote(''); }}>Cancelar</button>
                    <button className="btn btn-primary btn-sm" style={{ flex: 1 }} disabled={needsNote && !note.trim()} onClick={applyStatus}>Confirmar cambio</button>
                  </div>
                </div>)}
            </div></section>

            <section className="ga-card ga-sec"><div className="ga-card-b">
              <h3 style={{ marginBottom: 12 }}><Icon name="calendar" size={18} /> Fechas</h3>
              <dl className="ga-dl" style={{ gridTemplateColumns: '1fr' }}>
                <D k="Fecha de ingreso" v={GFmt.dateTime(r.createdAt)} />
                <D k="Última actualización" v={`${GFmt.dateTime(r.updatedAt)} · ${S.userName(r.history[r.history.length - 1].by)}`} />
                {r.resolvedAt && <D k="Resuelta" v={`${GFmt.dateTime(r.resolvedAt)} · ${((new Date(r.resolvedAt) - new Date(r.createdAt)) / 864e5).toFixed(1)} días`} />}
                <D k="Movimientos registrados" v={r.history.length} />
              </dl>
            </div></section>
          </div>
        </div>
      </aside>
    </>
  );
}

Object.assign(window, { RequestsView, RequestDrawer });
