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

// ── Icons ──────────────────────────────────────────────────────
const Ico = {
  search: (p) => (
    <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" {...p}>
      <circle cx="7" cy="7" r="5"/><path d="m11 11 3 3"/>
    </svg>
  ),
  download: (p) => (
    <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <path d="M8 2v8m0 0 3-3m-3 3L5 7"/><path d="M2.5 12v1.5A1.5 1.5 0 0 0 4 15h8a1.5 1.5 0 0 0 1.5-1.5V12"/>
    </svg>
  ),
  close: (p) => (
    <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" {...p}>
      <path d="m4 4 8 8M12 4l-8 8"/>
    </svg>
  ),
  doc: (p) => (
    <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinejoin="round" {...p}>
      <path d="M3.5 2h6L13 5.5V14H3.5z"/><path d="M9.5 2v3.5H13"/>
    </svg>
  ),
  refresh: (p) => (
    <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <path d="M2.5 8a5.5 5.5 0 0 1 9.4-3.9L14 6"/><path d="M14 2.5V6h-3.5"/>
      <path d="M13.5 8a5.5 5.5 0 0 1-9.4 3.9L2 10"/><path d="M2 13.5V10h3.5"/>
    </svg>
  ),
  check: (p) => (
    <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <path d="m3.5 8.5 3 3 6-7"/>
    </svg>
  ),
  clock: (p) => (
    <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" {...p}>
      <circle cx="8" cy="8" r="6"/><path d="M8 4.5V8l2.5 1.5"/>
    </svg>
  ),
  x: (p) => (
    <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" {...p}>
      <circle cx="8" cy="8" r="6"/><path d="m5.5 5.5 5 5M10.5 5.5l-5 5"/>
    </svg>
  ),
  alert: (p) => (
    <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" {...p}>
      <path d="M8 1.5 14.5 13h-13z"/><path d="M8 6v3.5M8 11.5v.5"/>
    </svg>
  ),
  eye: (p) => (
    <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}>
      <path d="M1.5 8s2.5-5 6.5-5 6.5 5 6.5 5-2.5 5-6.5 5-6.5-5-6.5-5z"/>
      <circle cx="8" cy="8" r="2"/>
    </svg>
  ),
  more: (p) => (
    <svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" {...p}>
      <circle cx="3.5" cy="8" r="1.4"/><circle cx="8" cy="8" r="1.4"/><circle cx="12.5" cy="8" r="1.4"/>
    </svg>
  ),
  copy: (p) => (
    <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinejoin="round" {...p}>
      <rect x="5.5" y="5.5" width="8" height="8" rx="1.2"/>
      <path d="M10.5 5.5V3a1 1 0 0 0-1-1h-6a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2"/>
    </svg>
  ),
  rows: (p) => (
    <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" {...p}>
      <rect x="2" y="3" width="12" height="3" rx="1"/>
      <rect x="2" y="10" width="12" height="3" rx="1"/>
    </svg>
  ),
};

Ico.send = (p) => (
  <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" {...p}>
    <path d="M14.5 1.5 6.5 9.5"/><path d="M14.5 1.5 10 14.5 6.5 9.5 1.5 6 14.5 1.5z"/>
  </svg>
);

Ico.linkIcon = (p) => (
  <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" {...p}>
    <path d="M6.5 9.5 9.5 6.5"/>
    <path d="M7 4.5 8.5 3a2.5 2.5 0 0 1 3.5 3.5L10.5 8"/>
    <path d="M9 11.5 7.5 13A2.5 2.5 0 0 1 4 9.5L5.5 8"/>
  </svg>
);

const STATUS_META = {
  pendiente: { label: 'Pendiente',  Icon: Ico.clock },
  firmado:   { label: 'Firmado',    Icon: Ico.check },
  cancelado: { label: 'Cancelado',  Icon: Ico.x },
  expirado:  { label: 'Expirado',   Icon: Ico.alert },
};

function StatusPill({ estado }) {
  const meta = STATUS_META[estado] || { label: estado };
  return <span className={`f-pill ${estado}`}>{meta.label}</span>;
}

function fmtDate(iso) {
  if (!iso) return '—';
  const d = new Date(iso);
  if (isNaN(d)) return '—';
  return window.Firma.formatCL(d);
}
function fmtDateTime(iso) {
  if (!iso) return '—';
  const d = new Date(iso);
  if (isNaN(d)) return '—';
  return window.Firma.formatCLTime(d);
}

function copyToClipboard(text) {
  if (navigator.clipboard && window.isSecureContext) {
    return navigator.clipboard.writeText(text);
  }
  const ta = document.createElement('textarea');
  ta.value = text;
  ta.style.position = 'fixed';
  ta.style.left = '-9999px';
  document.body.appendChild(ta);
  ta.select();
  document.execCommand('copy');
  document.body.removeChild(ta);
  return Promise.resolve();
}

const EMPTY_RESULT = { items: [], total: 0, page: 1, pageSize: 20, counts: { total: 0, pendiente: 0, firmado: 0, rechazado: 0, expirado: 0 } };

function useDashboard() {
  const [result, setResult] = useState(EMPTY_RESULT);
  const [loading, setLoading] = useState(true);
  const [apiDown, setApiDown] = useState(false);
  const [error, setError] = useState(null);
  const [lastUpdated, setLastUpdated] = useState(null);
  const paramsRef = useRef({});
  const abortRef = useRef(null);
  const intervalRef = useRef(null);

  const fetch_ = useCallback((params) => {
    if (abortRef.current) abortRef.current.abort();
    const ctrl = new AbortController();
    abortRef.current = ctrl;

    paramsRef.current = params;
    setLoading(true);
    window.Firma.tryFetchPaged(params, ctrl.signal)
      .then(data => {
        if (ctrl.signal.aborted) return;
        setResult(data);
        setApiDown(false);
        setError(null);
        setLastUpdated(new Date());
        setLoading(false);
      })
      .catch(err => {
        if (err.name === 'AbortError') return;
        setResult(EMPTY_RESULT);
        setApiDown(true);
        setError(String(err.message || err));
        setLoading(false);
      });
  }, []);

  const reload = useCallback(() => fetch_(paramsRef.current), [fetch_]);

  useEffect(() => {
    intervalRef.current = setInterval(() => { fetch_(paramsRef.current); }, 5 * 60 * 1000);
    return () => clearInterval(intervalRef.current);
  }, [fetch_]);

  return { result, loading, apiDown, error, lastUpdated, fetch: fetch_, reload };
}

// ── Hook: load solicitantes list ───────────────────────────────
function useSolicitantes() {
  const [list, setList] = useState([]);
  useEffect(() => {
    window.Firma.fetchSolicitantes().then(setList);
  }, []);
  return list;
}

// ── Hook: download with feedback ───────────────────────────────
function useDownload() {
  const [state, setState] = useState({});
  const cfg = window.FIRMA_CONFIG;

  const download = useCallback((doc) => {
    setState(s => ({ ...s, [doc.id]: 'downloading' }));

    if (doc.urlDescarga && !doc.urlDescarga.startsWith('#')) {
      const url = doc.urlDescarga.startsWith('http')
        ? doc.urlDescarga
        : cfg.baseUrl + doc.urlDescarga;

      fetch(url, { headers: authHeaders() })
        .then(r => { if (!r.ok) throw new Error('HTTP ' + r.status); return r.blob(); })
        .then(blob => {
          const a = document.createElement('a');
          a.href = URL.createObjectURL(blob);
          a.download = (doc.nombre || 'documento') + '.pdf';
          document.body.appendChild(a);
          a.click();
          a.remove();
          URL.revokeObjectURL(a.href);
          setState(s => ({ ...s, [doc.id]: 'done' }));
          setTimeout(() => setState(s => { const n = { ...s }; delete n[doc.id]; return n; }), 1400);
        })
        .catch(() => { setState(s => { const n = { ...s }; delete n[doc.id]; return n; }); });
    } else {
      setState(s => ({ ...s, [doc.id]: 'done' }));
      setTimeout(() => setState(s => { const n = { ...s }; delete n[doc.id]; return n; }), 1400);
    }
  }, [cfg]);

  return { state, download };
}

// ── Request Detail Modal ───────────────────────────────────────
function PreviewModal({ request, onClose, onDownloadDoc, onResend }) {
  const [activeDoc, setActiveDoc] = useState(null);

  useEffect(() => {
    if (!request) return;
    setActiveDoc(null);
    const onKey = (e) => { if (e.key === 'Escape') { if (activeDoc) setActiveDoc(null); else onClose(); }};
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [request]);

  if (!request) return null;
  const docs = request.documentos || [];

  if (activeDoc) {
    return (
      <div className="f-modal-backdrop" onClick={() => setActiveDoc(null)}>
        <div className="f-modal" onClick={e => e.stopPropagation()} role="dialog">
          <header className="f-modal-head">
            <div className="f-modal-head-l">
              <div className="f-modal-kicker">
                <span className="f-mono">DOC-{activeDoc.id}</span>
                <span className="dot"/>
                {activeDoc.firmado
                  ? <span className="f-pill firmado">Firmado</span>
                  : <span className="f-pill pendiente">Pendiente</span>}
              </div>
              <h2 className="f-modal-title">{activeDoc.nombre}</h2>
              <p className="f-modal-sub">{activeDoc.tipo}</p>
            </div>
            <div className="f-modal-head-r">
              <button className="f-btn ghost" onClick={() => setActiveDoc(null)} aria-label="Volver"><Ico.close/></button>
            </div>
          </header>
          <div className="f-modal-preview" style={{ minHeight: 500 }}>
            <DocPreview doc={activeDoc}/>
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="f-modal-backdrop" onClick={onClose}>
      <div className="f-modal" onClick={e => e.stopPropagation()} role="dialog">
        <header className="f-modal-head">
          <div className="f-modal-head-l">
            <div className="f-modal-kicker">
              <span className="f-mono">SOL-{request.id}</span>
              <span className="dot"/>
              <StatusPill estado={request.estado}/>
            </div>
            <h2 className="f-modal-title">{request.cliente}</h2>
            <p className="f-modal-sub">{request.rutCliente} · {request.company}</p>
          </div>
          <div className="f-modal-head-r">
            {request.firmaLink && (
              <button className="f-btn ghost" onClick={() => { onClose(); onResend(request); }} style={{ color: 'var(--navy)' }}>
                <Ico.send/> Reenviar
              </button>
            )}
            <button className="f-btn ghost" onClick={onClose} aria-label="Cerrar"><Ico.close/></button>
          </div>
        </header>

        <div className="f-modal-body" style={{ gridTemplateColumns: '280px 1fr' }}>
          <aside className="f-modal-meta">
            <MetaRow k="Cliente" v={request.cliente}/>
            <MetaRow k="RUT" v={request.rutCliente} mono/>
            <MetaRow k="Correo" v={request.emailCliente}/>
            <div className="f-modal-meta-hr"/>
            <MetaRow k="Solicitante" v={request.solicitante}/>
            <MetaRow k="Empresa" v={request.company}/>
            {request.tipoFirma && <MetaRow k="Tipo firma" v={request.tipoFirma}/>}
            <div className="f-modal-meta-hr"/>
            <MetaRow k="Creado" v={fmtDateTime(request.creadoEn)}/>
            <MetaRow k="Expira" v={fmtDate(request.expiraEn)}/>
          </aside>

          <div className="f-modal-docs">
            <div className="f-modal-docs-header">
              <strong>Documentos</strong>
              <span className="f-modal-docs-count">{request.documentosFirmados} de {request.totalDocumentos} firmados</span>
            </div>
            <div className="f-modal-docs-list">
              {docs.length === 0 && (
                <div className="f-doc-unavailable">
                  <div className="f-doc-unavailable-sub">Sin documentos asociados</div>
                </div>
              )}
              {docs.map(d => (
                <div key={d.id} className="f-modal-doc-row">
                  <div className="f-modal-doc-status">
                    {d.firmado ? <Ico.check style={{ color: 'var(--st-signed)' }}/> : <Ico.clock style={{ color: 'var(--st-pending)' }}/>}
                  </div>
                  <div className="f-modal-doc-info">
                    <div className="f-modal-doc-name">{d.nombre}</div>
                    <div className="f-modal-doc-meta">
                      {d.tipo}
                      {d.firmado && d.fechaFirma && <> · Firmado {fmtDate(d.fechaFirma)}</>}
                      {!d.firmado && ' · Pendiente'}
                    </div>
                  </div>
                  <div className="f-modal-doc-actions">
                    <button className="fd-iconbtn" onClick={() => setActiveDoc(d)} title="Ver"><Ico.eye/></button>
                    {d.urlDescarga && (
                      <button className="fd-iconbtn primary" onClick={() => onDownloadDoc(d)} title="Descargar"><Ico.download/></button>
                    )}
                  </div>
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

function MetaRow({ k, v, mono }) {
  return (
    <div className="f-meta-row">
      <span className="f-meta-k">{k}</span>
      <span className={`f-meta-v ${mono ? 'f-mono' : ''}`}>{v || '—'}</span>
    </div>
  );
}

function DocPreview({ doc }) {
  const [state, setState] = useState('loading');
  const [blobUrl, setBlobUrl] = useState(null);
  const urlRef = useRef(null);

  useEffect(() => {
    var url = doc.urlPreview;
    if (!url) { setState('unavailable'); return; }
    if (url === urlRef.current && blobUrl) return;
    urlRef.current = url;
    setState('loading');
    fetch(url, { headers: authHeaders() })
      .then(function(r) { if (!r.ok) throw new Error(r.status); return r.blob(); })
      .then(function(blob) {
        var objectUrl = URL.createObjectURL(blob);
        setBlobUrl(objectUrl);
        setState('ready');
      })
      .catch(function() { setState('unavailable'); });
    return function() { if (blobUrl) URL.revokeObjectURL(blobUrl); };
  }, [doc.urlPreview]);

  if (state === 'unavailable') {
    return (
      <div className="f-doc-unavailable">
        <Ico.doc width="32" height="32"/>
        <div className="f-doc-unavailable-title">Documento no disponible</div>
        <div className="f-doc-unavailable-sub">El archivo no se encuentra en el servidor.</div>
      </div>
    );
  }

  if (state === 'loading') {
    return (
      <div className="f-doc-unavailable">
        <div className="f-doc-unavailable-sub">Cargando documento...</div>
      </div>
    );
  }

  return (
    <iframe className="f-doc-iframe" src={blobUrl} title={doc.nombre}/>
  );
}

// ── Resend Modal ───────────────────────────────────────────────
function ResendModal({ request, onClose }) {
  const [copied, setCopied] = useState(false);
  const [sent, setSent] = useState(false);
  const [sending, setSending] = useState(false);
  const [error, setError] = useState('');
  const [cooldown, setCooldown] = useState(0);
  const timerRef = useRef(null);

  useEffect(() => {
    if (!request) return;
    setCopied(false); setSent(false); setError(''); setCooldown(0);
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => { window.removeEventListener('keydown', onKey); clearInterval(timerRef.current); };
  }, [request]);

  if (!request || !request.firmaLink) return null;

  const copyLink = () => {
    copyToClipboard(request.firmaLink).then(() => {
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    });
  };

  const resend = async () => {
    setSending(true);
    setError('');
    try {
      const baseUrl = (window.FIRMA_CONFIG && window.FIRMA_CONFIG.baseUrl) || '';
      const res = await fetch(baseUrl + '/api/Signature/ResendSignatureEmail', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ idRequest: request.id }),
      });
      if (!res.ok) {
        let msg = 'No se pudo reenviar el correo.';
        try { const data = await res.json(); if (data && data.message) msg = data.message; } catch (_) {}
        setError(msg);
        return;
      }
      setSent(true);
      setCooldown(60);
      timerRef.current = setInterval(() => {
        setCooldown(prev => {
          if (prev <= 1) { clearInterval(timerRef.current); return 0; }
          return prev - 1;
        });
      }, 1000);
    } catch (e) {
      setError('Error de conexión al reenviar el correo.');
    } finally {
      setSending(false);
    }
  };

  const docs = request.documentos || [];

  return (
    <div className="f-modal-backdrop" onClick={onClose}>
      <div className="f-modal resend-modal" onClick={e => e.stopPropagation()} role="dialog">
        <header className="f-modal-head">
          <div className="f-modal-head-l">
            <h2 className="f-modal-title">Reenviar enlace de firma</h2>
            <p className="f-modal-sub">Solicitud SOL-{request.id}</p>
          </div>
          <div className="f-modal-head-r">
            <button className="f-btn ghost" onClick={onClose} aria-label="Cerrar"><Ico.close/></button>
          </div>
        </header>

        <div className="resend-body">
          <div className="resend-client">
            <div className="resend-client-row"><span className="resend-label">Cliente</span><span>{request.cliente}</span></div>
            <div className="resend-client-row"><span className="resend-label">RUT</span><span className="f-mono">{request.rutCliente}</span></div>
            <div className="resend-client-row"><span className="resend-label">Email</span><span>{request.emailCliente}</span></div>
          </div>

          <div className="resend-docs">
            <div className="resend-docs-title">Documentos ({docs.length})</div>
            {docs.map(d => (
              <div key={d.id} className="resend-doc-item">
                <Ico.doc/>
                <span>{d.nombre}</span>
              </div>
            ))}
          </div>

          <div className="resend-link-box">
            <div className="resend-link-icon"><Ico.linkIcon width="20" height="20"/></div>
            <div className="resend-link-content">
              <div className="resend-link-label">Enlace de firma</div>
              <div className="resend-link-url">{request.firmaLink}</div>
            </div>
            <button className="f-btn" onClick={copyLink}>
              {copied ? <><Ico.check/> Copiado</> : <><Ico.copy/> Copiar</>}
            </button>
          </div>

          {error && (
            <div className="resend-error" style={{color:'var(--st-rejected, #b42318)', fontSize:'13px', padding:'8px 12px', background:'rgba(180,35,24,0.08)', borderRadius:'6px'}}>
              {error}
            </div>
          )}

          <div className="resend-actions">
            {sent && cooldown > 0 && (
              <div className="resend-success"><Ico.check style={{color:'var(--st-signed)'}}/> Correo enviado a {request.emailCliente}</div>
            )}
            <button
              className="f-btn primary resend-btn"
              onClick={resend}
              disabled={cooldown > 0 || sending}
            >
              <Ico.send/>
              {sending
                ? 'Enviando...'
                : cooldown > 0
                ? 'Reenviar Correo (' + cooldown + 's)'
                : 'Reenviar Correo'}
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}

// ── Combobox (searchable dropdown) ─────────────────────────────
function Combobox({ value, onChange, options, placeholder, allLabel, allValue }) {
  const [open, setOpen] = useState(false);
  const [search, setSearch] = useState('');
  const ref = useRef(null);
  const inputRef = useRef(null);

  useEffect(() => {
    if (!open) return;
    const onClick = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    const onKey = (e) => { if (e.key === 'Escape') setOpen(false); };
    document.addEventListener('mousedown', onClick);
    document.addEventListener('keydown', onKey);
    return () => { document.removeEventListener('mousedown', onClick); document.removeEventListener('keydown', onKey); };
  }, [open]);

  useEffect(() => {
    if (open && inputRef.current) inputRef.current.focus();
    if (!open) setSearch('');
  }, [open]);

  const av = allValue !== undefined ? allValue : '';
  const allOpts = allLabel ? [{ value: av, label: allLabel }] : [];
  const normalized = options.map(o => typeof o === 'string' ? { value: o, label: o } : o);
  const full = allOpts.concat(normalized);

  const filtered = search
    ? full.filter(o => o.label.toLowerCase().includes(search.toLowerCase()))
    : full;

  const selectedLabel = full.find(o => o.value === value)?.label || placeholder || '';

  const select = (val) => {
    onChange(val);
    setOpen(false);
  };

  return (
    <div className="cb-wrap" ref={ref}>
      <button className={`cb-trigger ${open ? 'open' : ''}`} onClick={() => setOpen(o => !o)} type="button">
        <span className={`cb-trigger-text ${!value ? 'cb-placeholder' : ''}`}>
          {value ? selectedLabel : placeholder}
        </span>
        <svg className={`cb-chevron ${open ? 'up' : ''}`} width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
          <path d="m4 6 4 4 4-4"/>
        </svg>
      </button>
      {open && (
        <div className="cb-dropdown">
          {normalized.length > 5 && (
            <div className="cb-search-wrap">
              <input ref={inputRef} className="cb-search" placeholder="Buscar..." value={search} onChange={e => setSearch(e.target.value)}/>
            </div>
          )}
          <div className="cb-list">
            {filtered.length === 0 && (
              <div className="cb-empty">Sin resultados</div>
            )}
            {filtered.map(o => (
              <button key={o.value} className={`cb-option ${o.value === value ? 'selected' : ''}`}
                onClick={() => select(o.value)} type="button">
                {o.label}
              </button>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

Object.assign(window, {
  Ico, StatusPill, STATUS_META, MetaRow, DocPreview, PreviewModal, ResendModal,
  useDashboard, useSolicitantes, useDownload, fmtDate, fmtDateTime,
  copyToClipboard, Combobox,
});
