const { useState, useMemo, useEffect, useRef, useCallback } = React;

function Dashboard() {
  const { result, loading, apiDown, error, lastUpdated, fetch: fetchData, reload } = useDashboard();
  const { state: dlState, download } = useDownload();
  const solicitantes = useSolicitantes();

  const [q, setQ] = useState('');
  const [status, setStatus] = useState('todos');
  const [solicitante, setSolicitante] = useState('');
  const [dateFrom, setDateFrom] = useState('');
  const [dateTo, setDateTo] = useState('');
  const [sortKey, setSortKey] = useState('creadoEn');
  const [sortDir, setSortDir] = useState('desc');
  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = useState(20);
  const [density, setDensity] = useState('comoda');
  const [selectedIds, setSelectedIds] = useState(new Set());
  const [previewDoc, setPreviewDoc] = useState(null);
  const [resendRequest, setResendRequest] = useState(null);

  const searchTimeout = useRef(null);
  const [searchInput, setSearchInput] = useState('');

  const doFetch = useCallback((overrides) => {
    const params = {
      search: overrides.search !== undefined ? overrides.search : q,
      solicitante: overrides.solicitante !== undefined ? overrides.solicitante : solicitante,
      status: overrides.status !== undefined ? overrides.status : status,
      dateFrom: overrides.dateFrom !== undefined ? overrides.dateFrom : dateFrom,
      dateTo: overrides.dateTo !== undefined ? overrides.dateTo : dateTo,
      sortBy: overrides.sortBy !== undefined ? overrides.sortBy : sortKey,
      sortDir: overrides.sortDir !== undefined ? overrides.sortDir : sortDir,
      page: overrides.page !== undefined ? overrides.page : page,
      pageSize: overrides.pageSize !== undefined ? overrides.pageSize : pageSize,
    };
    fetchData(params);
  }, [fetchData, q, solicitante, status, dateFrom, dateTo, sortKey, sortDir, page, pageSize]);

  useEffect(() => { doFetch({}); }, []);

  const onSearchInput = (val) => {
    setSearchInput(val);
    clearTimeout(searchTimeout.current);
    searchTimeout.current = setTimeout(() => {
      setQ(val);
      setPage(1);
      doFetch({ search: val, page: 1 });
    }, 400);
  };

  const onStatusChange = (val) => {
    setStatus(val);
    setPage(1);
    setSelectedIds(new Set());
    doFetch({ status: val, page: 1 });
  };

  const onDateFromChange = (val) => {
    setDateFrom(val);
    setPage(1);
    doFetch({ dateFrom: val, page: 1 });
  };

  const onDateToChange = (val) => {
    setDateTo(val);
    setPage(1);
    doFetch({ dateTo: val, page: 1 });
  };

  const onSort = (key) => {
    let newDir;
    if (sortKey === key) {
      newDir = sortDir === 'asc' ? 'desc' : 'asc';
    } else {
      newDir = 'asc';
    }
    setSortKey(key);
    setSortDir(newDir);
    doFetch({ sortBy: key, sortDir: newDir });
  };

  const onPage = (p) => {
    setPage(p);
    setSelectedIds(new Set());
    doFetch({ page: p });
  };

  const onPageSize = (n) => {
    setPageSize(n);
    setPage(1);
    setSelectedIds(new Set());
    doFetch({ pageSize: n, page: 1 });
  };

  const onSolicitanteChange = (val) => {
    setSolicitante(val);
    setPage(1);
    setSelectedIds(new Set());
    doFetch({ solicitante: val, page: 1 });
  };

  const hasFilters = q || status !== 'todos' || solicitante || dateFrom || dateTo;
  const clearFilters = () => {
    setQ(''); setSearchInput(''); setStatus('todos'); setSolicitante(''); setDateFrom(''); setDateTo('');
    setPage(1);
    doFetch({ search: '', solicitante: '', status: 'todos', dateFrom: '', dateTo: '', page: 1 });
  };

  const counts = result.counts || { total: 0, pendiente: 0, firmado: 0, cancelado: 0, expirado: 0 };
  const items = result.items || [];
  const total = result.total || 0;
  const pageCount = Math.max(1, Math.ceil(total / pageSize));
  const currentPage = Math.min(page, pageCount);

  const allVisibleSelected = items.length > 0 && items.every(d => selectedIds.has(d.id));
  const toggleSelectAll = () => {
    const next = new Set(selectedIds);
    if (allVisibleSelected) items.forEach(d => next.delete(d.id));
    else items.forEach(d => next.add(d.id));
    setSelectedIds(next);
  };
  const toggleSelect = (id) => {
    const next = new Set(selectedIds);
    if (next.has(id)) next.delete(id); else next.add(id);
    setSelectedIds(next);
  };

  const bulkDownload = () => {
    let delay = 0;
    items.filter(r => selectedIds.has(r.id)).forEach(r => {
      (r.documentos || []).filter(d => d.urlDescarga).forEach(d => {
        setTimeout(() => download(d), delay);
        delay += 150;
      });
    });
  };

  return (
    <div className={`fd-root firma-root density-${density}`}>
      <TopBar apiDown={apiDown} onRefresh={reload} lastUpdated={lastUpdated}/>

      {apiDown && (
        <div className="fd-error-state">
          <div className="fd-error-icon"><Ico.alert width="28" height="28"/></div>
          <div className="fd-error-title">No se pudo conectar con la API</div>
          <div className="fd-error-sub">{error || 'El servidor no esta disponible. Verifica que la API este corriendo e intenta de nuevo.'}</div>
          <button className="f-btn primary" onClick={reload}><Ico.refresh/> Reintentar</button>
        </div>
      )}

      {!apiDown && <><section className="fd-metrics">
        <MetricCard k="Total" v={counts.total} tone="ink"
          active={status === 'todos'} onClick={() => onStatusChange('todos')}/>
        <MetricCard k="Pendientes" sub="Esperando firma" v={counts.pendiente} tone="pending" emphasis
          active={status === 'pendiente'}
          onClick={() => onStatusChange(status === 'pendiente' ? 'todos' : 'pendiente')}/>
        <MetricCard k="Firmados" sub="Completados" v={counts.firmado} tone="signed"
          active={status === 'firmado'}
          onClick={() => onStatusChange(status === 'firmado' ? 'todos' : 'firmado')}/>
        <MetricCard k="Cancelados" v={counts.cancelado} tone="rejected"
          active={status === 'cancelado'}
          onClick={() => onStatusChange(status === 'cancelado' ? 'todos' : 'cancelado')}/>
        <MetricCard k="Expirados" v={counts.expirado} tone="expired"
          active={status === 'expirado'}
          onClick={() => onStatusChange(status === 'expirado' ? 'todos' : 'expirado')}/>
      </section>

      <FilterBar
        searchInput={searchInput} onSearchInput={onSearchInput}
        status={status} onStatusChange={onStatusChange}
        solicitante={solicitante} onSolicitanteChange={onSolicitanteChange}
        solicitantes={solicitantes}
        dateFrom={dateFrom} onDateFromChange={onDateFromChange}
        dateTo={dateTo} onDateToChange={onDateToChange}
        hasFilters={hasFilters} clearFilters={clearFilters}
      />

      <section className="fd-table-wrap">
        <div className="fd-table-head">
          <div className="fd-table-head-l">
            {selectedIds.size > 0 ? (
              <>
                <strong>{selectedIds.size}</strong> seleccionado{selectedIds.size === 1 ? '' : 's'}
                <button className="f-btn" onClick={bulkDownload} style={{ marginLeft: 12 }}>
                  <Ico.download/> Descargar seleccionados
                </button>
                <button className="f-btn ghost" onClick={() => setSelectedIds(new Set())}>
                  Limpiar seleccion
                </button>
              </>
            ) : (
              <span>
                <strong>{total}</strong> de {counts.total} documentos
                {hasFilters && <span className="fd-filters-active"> · filtros activos</span>}
              </span>
            )}
          </div>
          <div className="fd-table-head-r">
            <button
              className={`fd-chip-toggle ${density === 'compacta' ? 'active' : ''}`}
              onClick={() => setDensity(d => d === 'comoda' ? 'compacta' : 'comoda')}
              title="Alternar densidad"
            >
              <Ico.rows/> {density === 'compacta' ? 'Compacta' : 'Comoda'}
            </button>
          </div>
        </div>

        <div className="fd-table f-scroll">
          <table>
            <thead>
              <tr>
                <th style={{ width: 38 }}>
                  <input type="checkbox" className="fd-chk" checked={allVisibleSelected} onChange={toggleSelectAll} aria-label="Seleccionar todos"/>
                </th>
                <th style={{ width: 80 }}><span className="fd-sort">ID</span></th>
                <SortHeader label="Cliente" k="cliente" sortKey={sortKey} sortDir={sortDir} onSort={onSort}/>
                <SortHeader label="Estado" k="estado" sortKey={sortKey} sortDir={sortDir} onSort={onSort} width={130}/>
                <th style={{ width: 110 }}><span className="fd-sort">Docs</span></th>
                <SortHeader label="Solicitante" k="solicitante" sortKey={sortKey} sortDir={sortDir} onSort={onSort} width={180}/>
                <SortHeader label="Creado" k="creadoEn" sortKey={sortKey} sortDir={sortDir} onSort={onSort} width={110}/>
                <SortHeader label="Expira" k="expiraEn" sortKey={sortKey} sortDir={sortDir} onSort={onSort} width={110}/>
                <th style={{ width: 80, textAlign: 'right' }}>Acciones</th>
              </tr>
            </thead>
            <tbody>
              {loading && <SkeletonRows rows={8}/>}
              {!loading && items.length === 0 && (
                <tr><td colSpan={9} className="fd-empty">
                  <div className="fd-empty-inner">
                    <Ico.doc/>
                    <div><strong>No se encontraron documentos</strong></div>
                    <div className="fd-empty-sub">Revisa los filtros aplicados.</div>
                    {hasFilters && <button className="f-btn" onClick={clearFilters}><Ico.close/> Limpiar filtros</button>}
                  </div>
                </td></tr>
              )}
              {!loading && items.map(r => (
                <Row key={r.id} r={r}
                  selected={selectedIds.has(r.id)}
                  onToggleSelect={() => toggleSelect(r.id)}
                  onOpen={() => setPreviewDoc(r)}
                  onResend={() => setResendRequest(r)}
                />
              ))}
            </tbody>
          </table>
        </div>

        <Pagination page={currentPage} pageCount={pageCount} pageSize={pageSize} total={total}
          onPage={onPage} onPageSize={onPageSize}/>
      </section></>}

      <PreviewModal request={previewDoc} onClose={() => setPreviewDoc(null)} onDownloadDoc={download} onResend={(r) => setResendRequest(r)}/>
      <ResendModal request={resendRequest} onClose={() => setResendRequest(null)}/>
    </div>
  );
}

// ── Top bar (no client input) ─────────────────────────────────
function fmtUpdatedAt(date) {
  if (!date) return '';
  const meses = ['enero','febrero','marzo','abril','mayo','junio','julio','agosto','septiembre','octubre','noviembre','diciembre'];
  const d = date.getDate();
  const m = meses[date.getMonth()];
  const h = String(date.getHours()).padStart(2,'0');
  const min = String(date.getMinutes()).padStart(2,'0');
  return d + ' de ' + m + ' ' + h + ':' + min;
}

function TopBar({ apiDown, onRefresh, lastUpdated }) {
  return (
    <header className="fd-header">
      <div className="fd-brand">
        <div className="fd-brand-mark">
          <svg width="22" height="22" viewBox="0 0 22 22" fill="none">
            <rect x="1.5" y="1.5" width="19" height="19" rx="3" stroke="currentColor" strokeWidth="1.4"/>
            <path d="M6 13.5c2-4 4-4 5-4s2 3 5-2" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round"/>
          </svg>
        </div>
        <div>
          <div className="fd-brand-name">Firma Electronica</div>
          <div className="fd-brand-sub">Panel de Gestion · Grupo Defensa</div>
        </div>
      </div>
      <div className="fd-header-r">
        {lastUpdated && (
          <span className="fd-last-updated">Actualizado: {fmtUpdatedAt(lastUpdated)}</span>
        )}
        <span className={`fd-source ${apiDown ? 'error' : 'live'}`}>
          <span className="fd-source-dot"/>
          {apiDown ? 'DESCONECTADO' : 'CONECTADO'}
        </span>
        <button className="f-btn ghost" onClick={onRefresh}><Ico.refresh/> Actualizar</button>
      </div>
    </header>
  );
}

// ── Metric card ───────────────────────────────────────────────
function MetricCard({ k, sub, v, tone, emphasis, active, onClick }) {
  return (
    <button className={`fd-metric fd-metric-${tone} ${emphasis ? 'fd-metric-em' : ''} ${active ? 'active' : ''}`}
      onClick={onClick} type="button">
      <div className="fd-metric-k">{k}</div>
      <div className="fd-metric-v">{v}</div>
      {sub && <div className="fd-metric-sub">{sub}</div>}
      {active && <div className="fd-metric-active-tag">Filtrando</div>}
    </button>
  );
}

// ── Filter bar (search + status + dates) ──────────────────────
function FilterBar({ searchInput, onSearchInput, status, onStatusChange, solicitante, onSolicitanteChange, solicitantes, dateFrom, onDateFromChange, dateTo, onDateToChange, hasFilters, clearFilters }) {
  const statusOptions = [
    { value: 'pendiente', label: 'Pendiente' },
    { value: 'firmado', label: 'Firmado' },
    { value: 'cancelado', label: 'Cancelado' },
    { value: 'expirado', label: 'Expirado' },
  ];

  return (
    <section className="fd-filters" style={{ gridTemplateColumns: '1.8fr 1fr 1.2fr .9fr .9fr auto' }}>
      <div className="fd-filter-search">
        <Ico.search/>
        <input className="fd-search-input"
          placeholder="Buscar cliente por nombre o RUT..."
          value={searchInput}
          onChange={e => onSearchInput(e.target.value)}
        />
        {searchInput && <button className="fd-search-clear" onClick={() => onSearchInput('')} aria-label="Limpiar"><Ico.close/></button>}
      </div>
      <div className="fd-filter-group">
        <label className="fd-filter-label">Estado</label>
        <Combobox
          value={status}
          onChange={onStatusChange}
          options={statusOptions}
          placeholder="Todos los estados"
          allLabel="Todos"
          allValue="todos"
        />
      </div>
      <div className="fd-filter-group">
        <label className="fd-filter-label">Solicitante</label>
        <Combobox
          value={solicitante}
          onChange={onSolicitanteChange}
          options={solicitantes}
          placeholder="Todos"
          allLabel="Todos"
        />
      </div>
      <div className="fd-filter-group">
        <label className="fd-filter-label">Desde</label>
        <input className="f-input" type="date" value={dateFrom} onChange={e => onDateFromChange(e.target.value)}/>
      </div>
      <div className="fd-filter-group">
        <label className="fd-filter-label">Hasta</label>
        <input className="f-input" type="date" value={dateTo} onChange={e => onDateToChange(e.target.value)}/>
      </div>
      <div className="fd-filter-group fd-filter-clear">
        <label className="fd-filter-label">&nbsp;</label>
        <button className="f-btn ghost" onClick={clearFilters} disabled={!hasFilters}>
          <Ico.close/> Limpiar
        </button>
      </div>
    </section>
  );
}

// ── Sort header ───────────────────────────────────────────────
function SortHeader({ label, k, sortKey, sortDir, onSort, width, align }) {
  const active = sortKey === k;
  return (
    <th style={{ width, textAlign: align }}>
      <button className={`fd-sort ${active ? 'active' : ''} ${align === 'right' ? 'right' : ''}`} onClick={() => onSort(k)}>
        <span>{label}</span>
        <span className={`fd-sort-arrow ${active ? sortDir : ''}`}>
          {active ? (sortDir === 'asc' ? '▲' : '▼') : '▲'}
        </span>
      </button>
    </th>
  );
}

// ── Table row (SignatureRequest) ───────────────────────────────
function Row({ r, selected, onToggleSelect, onOpen, onResend }) {
  return (
    <tr className={`fd-row ${selected ? 'selected' : ''}`} onClick={onOpen}>
      <td onClick={e => e.stopPropagation()}>
        <input type="checkbox" className="fd-chk" checked={selected} onChange={onToggleSelect} aria-label={'Seleccionar ' + r.id}/>
      </td>
      <td className="f-mono fd-id-num">{r.id}</td>
      <td>
        <div className="fd-doc-name">{r.cliente}</div>
        <div className="fd-doc-sub f-mono">{r.rutCliente}</div>
      </td>
      <td><StatusPill estado={r.estado}/></td>
      <td>
        <span className="fd-doc-count">{r.documentosFirmados}/{r.totalDocumentos}</span>
      </td>
      <td>
        <div className="fd-signer">{r.solicitante}</div>
      </td>
      <td className="fd-date">{fmtDate(r.creadoEn)}</td>
      <td className="fd-date">
        <ExpiryCell expiraEn={r.expiraEn} estado={r.estado}/>
      </td>
      <td style={{ textAlign: 'right' }} onClick={e => e.stopPropagation()}>
        <div className="fd-row-actions">
          <button className="fd-iconbtn" onClick={onOpen} title="Ver detalle"><Ico.eye/></button>
          {r.firmaLink && (
            <button className="fd-iconbtn" onClick={onResend} title="Reenviar correo"><Ico.send/></button>
          )}
        </div>
      </td>
    </tr>
  );
}

function ExpiryCell({ expiraEn, estado }) {
  if (!expiraEn) return <span>—</span>;
  const now = new Date();
  const exp = new Date(expiraEn);
  const days = Math.round((exp - now) / 86400000);
  if (estado === 'firmado') return <span className="fd-date-good">{fmtDate(expiraEn)}</span>;
  let cls = '';
  if (days < 0) cls = 'fd-date-bad';
  else if (days <= 5) cls = 'fd-date-warn';
  return <span className={cls}>{fmtDate(expiraEn)}{days >= 0 && days <= 5 && <span className="fd-date-sub"> · {days}d</span>}</span>;
}

function SkeletonRows({ rows }) {
  return Array.from({ length: rows }).map((_, i) => (
    <tr key={i} className="fd-skel-row">
      <td><div className="fd-skel" style={{ width: 14, height: 14, borderRadius: 3 }}/></td>
      <td><div className="fd-skel" style={{ width: 50 }}/></td>
      <td><div className="fd-skel" style={{ width: '70%' }}/><div className="fd-skel" style={{ width: '40%', marginTop: 4 }}/></td>
      <td><div className="fd-skel" style={{ width: 80, height: 18, borderRadius: 999 }}/></td>
      <td><div className="fd-skel" style={{ width: 40 }}/></td>
      <td><div className="fd-skel" style={{ width: 120 }}/></td>
      <td><div className="fd-skel" style={{ width: 80 }}/></td>
      <td><div className="fd-skel" style={{ width: 80 }}/></td>
      <td><div className="fd-skel" style={{ width: 28, marginLeft: 'auto' }}/></td>
    </tr>
  ));
}

function Pagination({ page, pageCount, pageSize, total, onPage, onPageSize }) {
  if (total === 0) return null;
  const from = (page - 1) * pageSize + 1;
  const to = Math.min(page * pageSize, total);
  return (
    <div className="fd-pagination">
      <div className="fd-page-l">
        <span>Mostrando <strong>{from}</strong>–<strong>{to}</strong> de <strong>{total}</strong></span>
        <label className="fd-page-size">
          Por pagina
          <select value={pageSize} onChange={e => onPageSize(parseInt(e.target.value, 10))}>
            <option value={10}>10</option>
            <option value={20}>20</option>
            <option value={50}>50</option>
            <option value={100}>100</option>
          </select>
        </label>
      </div>
      <div className="fd-page-r">
        <button className="fd-pagebtn" onClick={() => onPage(1)} disabled={page === 1} title="Primera">&laquo;</button>
        <button className="fd-pagebtn" onClick={() => onPage(page - 1)} disabled={page === 1} title="Anterior">&lsaquo;</button>
        <span className="fd-page-cur">Pagina <strong>{page}</strong> de <strong>{pageCount}</strong></span>
        <button className="fd-pagebtn" onClick={() => onPage(page + 1)} disabled={page === pageCount} title="Siguiente">&rsaquo;</button>
        <button className="fd-pagebtn" onClick={() => onPage(pageCount)} disabled={page === pageCount} title="Ultima">&raquo;</button>
      </div>
    </div>
  );
}

window.Dashboard = Dashboard;
