// ─── Micos CRM · Visor de adjuntos ─────────────────
// Abre un adjunto a pantalla completa, al estilo del visor de adjuntos de
// Gmail: lienzo oscuro, barra superior con el nombre + acciones (imprimir,
// descargar, abrir) y el documento centrado como una "página". Se abre
// escuchando el evento `micos:open-doc` para no pasar callbacks por toda la
// jerarquía de la bandeja.

const { useState: _useStateDV, useEffect: _useEffectDV } = React;

// Metadatos por tipo de archivo
const _DOC_META = {
  pdf: { label: 'PDF',  color: '#ea4335' },
  xls: { label: 'Hoja de cálculo', color: '#34a853' },
  doc: { label: 'Documento', color: '#4285f4' },
  img: { label: 'Imagen', color: '#a142f4' },
};
function _docMeta(tipo) { return _DOC_META[tipo] || { label: (tipo || 'Archivo').toUpperCase(), color: '#9aa0a6' }; }

// #35 — "Abrir en el ERP": navega al expediente del adjunto (bundles separados,
// window.location alcanza). Reusa el helper de crm/thread.jsx (cargado antes);
// fallback por las dudas.
function _crmAbrirExpDoc(publicId) {
  const nav = window.crmAbrirExpediente || ((id) => { window.location.href = '/erp/expedientes/' + encodeURIComponent(id); });
  nav(publicId);
}
// Descarga real del adjunto (ingesta n8n → Storage): ancla temporal con
// `download`, así baja el archivo sin sacar al usuario del visor. Solo para
// adjuntos reales (con id) — el endpoint ya fuerza Content-Disposition.
function _crmDescargarAdjunto(a) {
  if (!a || a.id == null) return;
  const link = document.createElement('a');
  link.href = `/api/crm-adjuntos/${a.id}`;
  link.download = a.nombre || 'adjunto';
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}

// Botón de la barra superior (icono ghost claro sobre fondo oscuro)
function _DVBtn({ icon: Icon, label, onClick, size = 19 }) {
  return (
    <button
      type="button"
      onClick={(e) => { onClick && onClick(e); e.currentTarget.blur(); }}
      title={label}
      aria-label={label}
      className="inline-flex items-center justify-center rounded-full cursor-pointer transition-colors"
      style={{ width: 40, height: 40, background: 'transparent', color: 'rgba(255,255,255,0.86)' }}
      onMouseEnter={(e) => { e.currentTarget.style.background = 'rgba(255,255,255,0.12)'; }}
      onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; }}
    >
      <Icon size={size} />
    </button>
  );
}

function DocViewer() {
  const [doc, setDoc] = _useStateDV(null); // { attachment, email }
  // Adjunto real (ingesta n8n → nuestra DB, viene con `id`) cuya carga falló
  // (los 9 sembrados con storage_path NULL dan 404 "adjunto sin archivo" en
  // el endpoint) — cae con gracia al visor simulado de siempre en vez de
  // mostrar un hueco roto.
  const [broken, setBroken] = _useStateDV(false);

  _useEffectDV(() => {
    const onOpen = (e) => { setBroken(false); setDoc(e.detail); };
    window.addEventListener('micos:open-doc', onOpen);
    return () => window.removeEventListener('micos:open-doc', onOpen);
  }, []);

  _useEffectDV(() => {
    if (!doc) return;
    const onKey = (e) => { if (e.key === 'Escape') setDoc(null); };
    window.addEventListener('keydown', onKey);
    // bloquear scroll de fondo
    const prev = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => { window.removeEventListener('keydown', onKey); document.body.style.overflow = prev; };
  }, [doc]);

  if (!doc) return null;

  const { attachment: a, email } = doc;
  const meta = _docMeta(a.tipo);
  const expId = email && email.linkedExpedienteId;
  const remitente = email && email.messages && email.messages[email.messages.length - 1]
    ? email.messages[email.messages.length - 1].from.nombre : null;
  const isSheet = a.tipo === 'xls';
  // Adjunto real: tiene `id` (ingesta n8n → Storage) y todavía no se cayó a
  // "roto". El mock del seed (sin `id`) sigue siempre con el visor simulado.
  const isReal = a.id != null && !broken;
  const isWidePreview = isReal && (a.tipo === 'pdf' || a.tipo === 'img');

  return (
    <div className="fixed inset-0 z-50 flex flex-col animate-fade-in" style={{ background: 'rgba(11,12,14,0.97)' }}>
      {/* Barra superior */}
      <div className="flex items-center gap-2 px-3 flex-shrink-0" style={{ height: 64, color: '#fff' }}>
        <_DVBtn icon={IconX} label="Cerrar" onClick={() => setDoc(null)} size={20} />
        <div
          className="flex items-center justify-center flex-shrink-0 ml-1"
          style={{ width: 36, height: 36, borderRadius: 8, background: `color-mix(in oklab, ${meta.color} 26%, transparent)`, color: '#fff' }}
        >
          <IconPaperclip size={17} />
        </div>
        <div className="min-w-0 flex-1 ml-1">
          <p className="text-[14px] font-semibold truncate" style={{ color: '#fff' }}>{a.nombre}</p>
          <p className="text-[11.5px] truncate" style={{ color: 'rgba(255,255,255,0.55)' }}>
            {meta.label}{remitente ? ` · de ${remitente}` : ''}{expId ? ` · ${expId}` : ''}
          </p>
        </div>
        <div className="flex items-center gap-0.5 flex-shrink-0">
          {expId && <_DVBtn icon={IconExternal} label={`Abrir ${expId} en el ERP`} onClick={() => _crmAbrirExpDoc(expId)} size={18} />}
          {/* Imprimir/Descargar solo para adjuntos REALES (con archivo en
              Storage). El visor simulado del seed no tiene archivo que bajar —
              esconder el control es más honesto que un botón que no hace nada. */}
          {isReal && a.tipo === 'pdf' && <_DVBtn icon={IconPrinter} label="Imprimir" onClick={() => window.open(`/api/crm-adjuntos/${a.id}`, '_blank', 'noopener')} size={18} />}
          {isReal && <_DVBtn icon={IconDownload} label="Descargar" onClick={() => _crmDescargarAdjunto(a)} size={19} />}
        </div>
      </div>

      {/* Lienzo del documento */}
      <div className="flex-1 overflow-auto flex justify-center px-4 py-6" style={{ minHeight: 0 }}>
        <div
          className="w-full animate-scale-in"
          style={{
            maxWidth: isSheet ? 920 : (isWidePreview ? 900 : 780),
            background: '#fff',
            borderRadius: 4,
            boxShadow: '0 18px 50px -12px rgba(0,0,0,0.6)',
            alignSelf: 'flex-start',
            overflow: 'hidden',
          }}
        >
          {isReal
            ? <_RealDocPreview a={a} meta={meta} onBroken={() => setBroken(true)} />
            : (isSheet ? <_SheetPreview a={a} /> : <_DocPreview a={a} meta={meta} expId={expId} remitente={remitente} />)}
        </div>
      </div>
    </div>
  );
}

// ─── Preview REAL (adjunto con `id`, ingesta n8n → Storage) ────────────────
// img -> <img> directo al endpoint (mime real, inline); pdf -> iframe con
// pre-chequeo (un <iframe> no dispara `onError` ante un 404, a diferencia de
// <img>, así que se valida antes con un HEAD); xls/doc/otro -> sin preview
// posible, botón "Descargar" (el server ya fuerza Content-Disposition
// attachment para esos mimes), TAMBIÉN con pre-chequeo HEAD (un <a href> tampoco
// dispara `onError`, así que sin el HEAD un mock del seed ofrecería una descarga
// que da 404 en vez de caer al visor simulado como img/pdf). `onBroken` avisa al
// padre para caer al visor simulado de siempre (edge case: 9 adjuntos sembrados
// con `id` pero sin archivo real en Storage — el endpoint da 404 "adjunto sin
// archivo").
function _RealDocPreview({ a, meta, onBroken }) {
  const url = `/api/crm-adjuntos/${a.id}`;

  if (a.tipo === 'img') {
    return (
      <div style={{ display: 'flex', justifyContent: 'center', background: '#202124' }}>
        <img
          src={url}
          alt={a.nombre}
          style={{ display: 'block', maxWidth: '100%', maxHeight: '80vh', objectFit: 'contain' }}
          onError={onBroken}
        />
      </div>
    );
  }

  if (a.tipo === 'pdf') {
    return <_RealPdfPreview url={url} onBroken={onBroken} />;
  }

  // xls / doc / otro: sin vista previa posible → tarjeta de descarga, pero solo
  // si el archivo EXISTE (mismo pre-chequeo HEAD que el pdf).
  return <_RealDownloadPreview a={a} meta={meta} url={url} onBroken={onBroken} />;
}

// Pre-chequeo HEAD compartido: ni un <iframe> (pdf) ni un <a href> (descarga)
// disparan `onError` ante un 404 (a diferencia de <img>) — el 404 "carga" como
// contenido igual. El HEAD es la única forma confiable de detectar el edge case
// de los adjuntos sembrados sin storage_path. Devuelve null (chequeando) | true
// (existe) | false (roto); en false avisa al padre (onBroken) para caer al mock.
function _useHeadOk(url, onBroken) {
  const [ok, setOk] = _useStateDV(null); // null = chequeando, true/false

  _useEffectDV(() => {
    let cancelled = false;
    fetch(url, { method: 'HEAD', credentials: 'same-origin' })
      .then((r) => { if (!cancelled) setOk(r.ok); })
      .catch(() => { if (!cancelled) setOk(false); });
    return () => { cancelled = true; };
  }, [url]);

  _useEffectDV(() => {
    if (ok === false) onBroken();
  }, [ok]);

  return ok;
}

// PDF real: se valida con un HEAD antes de montar el <iframe> (ver _useHeadOk).
function _RealPdfPreview({ url, onBroken }) {
  const ok = _useHeadOk(url, onBroken);

  if (ok !== true) return null; // chequeando o roto: el padre ya cae al mock si ok===false

  return (
    <iframe
      title="Vista previa del PDF"
      src={url}
      style={{ display: 'block', width: '100%', height: '80vh', border: 'none' }}
    />
  );
}

// Descarga real (xls/doc/otro): idéntico pre-chequeo HEAD que el pdf — si el
// archivo no existe (mock del seed), cae al visor simulado en vez de ofrecer una
// descarga rota.
function _RealDownloadPreview({ a, meta, url, onBroken }) {
  const ok = _useHeadOk(url, onBroken);

  if (ok !== true) return null; // chequeando o roto: el padre ya cae al mock si ok===false

  return <_DownloadOnly a={a} meta={meta} url={url} />;
}

// Tipos sin preview posible (xls/doc/otro) — tarjeta con descarga forzada.
function _DownloadOnly({ a, meta, url }) {
  return (
    <div
      style={{
        padding: '56px 64px', minHeight: 420, color: '#202124',
        display: 'flex', flexDirection: 'column', alignItems: 'center',
        justifyContent: 'center', gap: 18, textAlign: 'center',
      }}
    >
      <div
        style={{
          width: 56, height: 56, borderRadius: 14,
          background: `color-mix(in oklab, ${meta.color} 14%, white)`, color: meta.color,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}
      >
        <IconPaperclip size={24} />
      </div>
      <div>
        <p style={{ fontSize: 16, fontWeight: 800, color: '#202124' }}>{a.nombre}</p>
        <p style={{ fontSize: 12.5, color: '#9aa0a6', marginTop: 4 }}>{meta.label} · sin vista previa disponible</p>
      </div>
      <a href={url} className="btn btn-primary" style={{ textDecoration: 'none' }}>
        <IconDownload size={14} />
        Descargar
      </a>
    </div>
  );
}

// Vista previa tipo "página" de documento (PDF/genérico)
function _DocPreview({ a, meta, expId, remitente }) {
  return (
    <div style={{ padding: '56px 64px', minHeight: 620, color: '#202124' }}>
      <div className="flex items-center justify-between" style={{ borderBottom: '1px solid #e4e6ea', paddingBottom: 20, marginBottom: 28 }}>
        <div>
          <p style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', color: meta.color }}>{meta.label}</p>
          <p style={{ fontSize: 22, fontWeight: 800, marginTop: 4, color: '#202124' }}>{a.nombre.replace(/\.[^.]+$/, '')}</p>
        </div>
        <div style={{ width: 44, height: 44, borderRadius: 10, background: `color-mix(in oklab, ${meta.color} 14%, white)`, color: meta.color, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          <IconPaperclip size={20} />
        </div>
      </div>
      {/* Líneas simuladas de contenido */}
      <div style={{ display: 'flex', flexDirection: 'column', gap: 13 }}>
        {[100, 92, 96, 70, 0, 88, 100, 64, 0, 95, 80].map((w, i) => (
          w === 0
            ? <div key={i} style={{ height: 8 }} />
            : <div key={i} style={{ height: 11, width: `${w}%`, borderRadius: 3, background: i % 4 === 0 ? '#d7dadf' : '#eceef1' }} />
        ))}
      </div>
      <p style={{ marginTop: 40, fontSize: 11.5, fontFamily: 'JetBrains Mono, monospace', color: '#9aa0a6', textAlign: 'center' }}>
        vista previa · el documento real se carga desde el almacenamiento de Micos vía la API
      </p>
    </div>
  );
}

// Vista previa tipo planilla (XLS)
function _SheetPreview({ a }) {
  const cols = ['A', 'B', 'C', 'D', 'E', 'F'];
  const rows = Array.from({ length: 14 });
  return (
    <div style={{ color: '#202124' }}>
      <div style={{ display: 'grid', gridTemplateColumns: `44px repeat(${cols.length}, 1fr)`, fontSize: 12 }}>
        {/* esquina */}
        <div style={{ background: '#f1f3f4', borderRight: '1px solid #e4e6ea', borderBottom: '1px solid #e4e6ea', height: 28 }} />
        {cols.map((c) => (
          <div key={c} style={{ background: '#f1f3f4', borderRight: '1px solid #e4e6ea', borderBottom: '1px solid #e4e6ea', height: 28, display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 700, color: '#5f6368' }}>{c}</div>
        ))}
        {rows.map((_, r) => (
          <React.Fragment key={r}>
            <div style={{ background: '#f8f9fa', borderRight: '1px solid #e4e6ea', borderBottom: '1px solid #eceef1', height: 26, display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 600, color: '#9aa0a6', fontSize: 11 }}>{r + 1}</div>
            {cols.map((c) => (
              <div key={c} style={{ borderRight: '1px solid #eceef1', borderBottom: '1px solid #eceef1', height: 26, padding: '0 8px', display: 'flex', alignItems: 'center' }}>
                {r % 5 !== 4 && <div style={{ height: 8, width: `${40 + ((r * 7 + c.charCodeAt(0)) % 50)}%`, borderRadius: 2, background: (r === 0 ? '#d7dadf' : '#eceef1') }} />}
              </div>
            ))}
          </React.Fragment>
        ))}
      </div>
    </div>
  );
}

// Helper global para disparar el visor desde cualquier parte
function openDoc(attachment, email) {
  window.dispatchEvent(new CustomEvent('micos:open-doc', { detail: { attachment, email } }));
}

Object.assign(window, { DocViewer, openDoc });
