// multimedia.jsx — Videos de campaña para el Estado de WhatsApp.
//
// El punto de esta pantalla: un LINK en un Estado de WhatsApp no reproduce nada,
// queda como texto con miniatura. Por eso acá no se comparte un link: se le pasa
// el ARCHIVO al teléfono, y el menú nativo de compartir se lo entrega a WhatsApp.
//
// Detalle que decide el diseño: en iOS, navigator.share() sólo funciona si se
// llama dentro del gesto del dedo. Por eso el video se descarga ANTES (al abrir
// la ficha) y el botón sólo se habilita cuando ya está en memoria.

(function () {
  const TABLA      = 'multimedia_campana';
  const TABLA_USO  = 'multimedia_uso';

  // En la base la marca va sin tilde y sin apóstrofe, igual que
  // productos_catalogo.catalogo, para que un cruce por marca entre las dos
  // tablas no se rompa. El acento se pone acá, al mostrar. El orden de las
  // pestañas es fijo y no depende de lo que traiga la base: una lista que se
  // reordena sola según qué se cargó cambia de lugar bajo el dedo.
  const ORDEN_MARCAS = ['Esika', 'CyZone', 'Lbel'];
  const NOMBRE_MARCA = { Esika: 'Ésika', CyZone: 'CyZone', Lbel: "L'Bel" };
  const nombreMarca  = m => NOMBRE_MARCA[m] || m || '';

  // Límites reales del Estado de WhatsApp. Si un video los pasa, se avisa —
  // no se deja que la vendedora lo descubra cuando ya publicó.
  const LIMITE_SEG   = 60;
  const LIMITE_BYTES = 16 * 1024 * 1024;

  // ── capacidad del teléfono ─────────────────────────────
  // No se promete "poner en tu estado" si el navegador no sabe compartir
  // archivos. En ese caso el botón dice lo que de verdad va a hacer.
  function puedeCompartirArchivos() {
    try {
      if (typeof navigator === 'undefined' || !navigator.canShare || !navigator.share) return false;
      const prueba = new File([new Blob(['x'], { type: 'video/mp4' })], 'prueba.mp4', { type: 'video/mp4' });
      return navigator.canShare({ files: [prueba] });
    } catch (_) {
      return false;
    }
  }

  function fmtDuracion(seg) {
    if (!seg && seg !== 0) return null;
    const m = Math.floor(seg / 60);
    const s = Math.floor(seg % 60);
    return `${m}:${String(s).padStart(2, '0')}`;
  }

  function fmtPeso(bytes) {
    if (!bytes) return null;
    return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
  }

  async function registrarUso(multimediaId, vendedoraId, via, detalle) {
    // Silencio no es lo mismo que "no pasó nada": sin este registro, una pantalla
    // que nadie usa y una pantalla rota se ven iguales.
    try {
      const sb = await window.getSupabase();
      if (!sb) return;
      await sb.from(TABLA_USO).insert({
        multimedia_id: multimediaId,
        vendedora_id: vendedoraId || null,
        via,
        detalle: detalle ? String(detalle).slice(0, 300) : null,
      });
    } catch (_) { /* el registro nunca puede romper la pantalla */ }
  }

  // ── ficha de un video ──────────────────────────────────

  function VideoSheet({ video, vendedora, onClose }) {
    const T = window.T;
    const compartible = React.useMemo(puedeCompartirArchivos, []);
    const [archivo, setArchivo]   = React.useState(null);   // File listo en memoria
    const [pct, setPct]           = React.useState(0);
    const [estado, setEstado]     = React.useState('cargando'); // cargando | listo | error | enviando | ok
    const [error, setError]       = React.useState('');
    const abortRef = React.useRef(null);

    // Descarga anticipada: al terminar, el botón se habilita.
    React.useEffect(() => {
      let vivo = true;
      const ctrl = new AbortController();
      abortRef.current = ctrl;

      (async () => {
        try {
          setEstado('cargando'); setPct(0);
          const res = await fetch(video.video_url, { signal: ctrl.signal });
          if (!res.ok) throw new Error(`El video no respondió (${res.status})`);

          const total = Number(res.headers.get('content-length')) || video.peso_bytes || 0;
          let blob;

          if (res.body && res.body.getReader && total > 0) {
            const reader = res.body.getReader();
            const trozos = [];
            let leido = 0;
            for (;;) {
              const { done, value } = await reader.read();
              if (done) break;
              trozos.push(value);
              leido += value.length;
              if (vivo) setPct(Math.min(99, Math.round((leido / total) * 100)));
            }
            blob = new Blob(trozos, { type: 'video/mp4' });
          } else {
            blob = await res.blob();
          }

          if (!vivo) return;
          const nombre = `${(video.titulo || 'video').replace(/[^\w\s-]/g, '').trim().replace(/\s+/g, '-').toLowerCase() || 'video'}.mp4`;
          setArchivo(new File([blob], nombre, { type: 'video/mp4' }));
          setPct(100);
          setEstado('listo');
        } catch (e) {
          if (!vivo || e.name === 'AbortError') return;
          setError(e.message || 'No se pudo traer el video');
          setEstado('error');
          registrarUso(video.id, vendedora?.id, 'fallo', e.message);
        }
      })();

      return () => { vivo = false; ctrl.abort(); };
    }, [video.id, video.video_url]);

    // Este handler NO puede tener await antes del share: iOS exige que la
    // llamada salga dentro del gesto. Por eso el archivo ya está listo acá.
    function alTocarBoton() {
      if (!archivo) return;

      if (compartible) {
        setEstado('enviando');
        navigator.share({ files: [archivo], title: video.titulo || 'Inova' })
          .then(() => {
            setEstado('ok');
            registrarUso(video.id, vendedora?.id, 'compartido');
          })
          .catch((e) => {
            setEstado('listo');
            // Cancelar no es un fallo: ella cambió de opinión.
            if (e && e.name === 'AbortError') return;
            setError(e?.message || 'El teléfono no aceptó el video');
            registrarUso(video.id, vendedora?.id, 'fallo', e?.message);
          });
        return;
      }

      // Sin compartir nativo: se descarga y ella lo sube desde la galería.
      const url = URL.createObjectURL(archivo);
      const a = document.createElement('a');
      a.href = url; a.download = archivo.name;
      document.body.appendChild(a); a.click(); a.remove();
      setTimeout(() => URL.revokeObjectURL(url), 60000);
      setEstado('ok');
      registrarUso(video.id, vendedora?.id, 'descargado');
    }

    const muyLargo = video.duracion_seg && video.duracion_seg > LIMITE_SEG;
    const muyPesado = (video.peso_bytes || archivo?.size || 0) > LIMITE_BYTES;

    const etiquetaBoton =
      estado === 'cargando' ? `Preparando el video… ${pct}%`
      : estado === 'enviando' ? 'Abriendo WhatsApp…'
      : estado === 'ok' ? (compartible ? '✓ Listo, elige Estado en WhatsApp' : '✓ Video guardado en tu teléfono')
      : compartible ? 'Poner en mi estado'
      : 'Descargar el video';

    return (
      <div
        onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}
        style={{
          position: 'fixed', inset: 0, zIndex: 90,
          background: 'rgba(20,14,12,0.55)', backdropFilter: 'blur(6px)',
          display: 'flex', alignItems: 'flex-end', justifyContent: 'center',
        }}
      >
        <div style={{
          width: '100%', maxWidth: 520, background: T.paper,
          borderRadius: `${T.r4} ${T.r4} 0 0`,
          padding: '10px 22px calc(26px + env(safe-area-inset-bottom))',
          maxHeight: '92vh', overflowY: 'auto',
          boxShadow: '0 -18px 50px rgba(0,0,0,0.28)',
        }}>
          <div style={{
            width: 38, height: 4, borderRadius: 2, background: T.hairlineStrong,
            margin: '0 auto 18px',
          }} />

          <div style={{
            borderRadius: 18, overflow: 'hidden', background: '#0a0a0a',
            aspectRatio: '9/16', maxHeight: '46vh', margin: '0 auto 18px',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}>
            <video
              src={video.video_url}
              poster={video.portada_url || undefined}
              controls playsInline preload="metadata"
              style={{ width: '100%', height: '100%', objectFit: 'contain', display: 'block' }}
            />
          </div>

          <div style={{
            fontFamily: T.serif, fontSize: 23, color: T.ink,
            letterSpacing: -0.4, lineHeight: 1.15, marginBottom: 6,
          }}>{video.titulo}</div>

          <div style={{
            fontFamily: T.mono, fontSize: 10, letterSpacing: 1.3,
            textTransform: 'uppercase', color: T.inkMute, marginBottom: 16,
          }}>
            {[nombreMarca(video.marca), fmtDuracion(video.duracion_seg), fmtPeso(video.peso_bytes)]
              .filter(Boolean).join(' · ')}
          </div>

          {(muyLargo || muyPesado) && (
            <div style={{
              background: T.warnSoft, border: `1px solid ${T.warn}`,
              borderRadius: T.r1, padding: '11px 13px', marginBottom: 14,
              fontFamily: T.sans, fontSize: 13, color: T.ink, lineHeight: 1.45,
            }}>
              {muyLargo && <div>Dura más de {LIMITE_SEG} segundos. WhatsApp lo va a cortar.</div>}
              {muyPesado && <div>Pesa más de 16 MB. WhatsApp puede rechazarlo.</div>}
            </div>
          )}

          {estado === 'error' && (
            <div style={{
              background: T.dangerSoft, border: `1px solid ${T.danger}`,
              borderRadius: T.r1, padding: '11px 13px', marginBottom: 14,
              fontFamily: T.sans, fontSize: 13, color: T.ink,
            }}>{error}</div>
          )}

          <button
            type="button"
            onClick={alTocarBoton}
            disabled={estado === 'cargando' || estado === 'enviando' || estado === 'error'}
            style={{
              width: '100%', padding: '17px 18px', border: 'none',
              borderRadius: T.r2, cursor: estado === 'listo' || estado === 'ok' ? 'pointer' : 'default',
              background: estado === 'ok' ? T.ok : (estado === 'listo' ? T.accent : T.paperDeep),
              color: estado === 'listo' || estado === 'ok' ? '#fff' : T.inkMute,
              fontFamily: T.sans, fontSize: 16, fontWeight: 600, letterSpacing: -0.1,
              transition: 'background 160ms ease',
            }}
          >{etiquetaBoton}</button>

          <div style={{
            fontFamily: T.sans, fontSize: 12.5, color: T.inkSoft,
            marginTop: 12, lineHeight: 1.5, textAlign: 'center',
          }}>
            {compartible
              ? 'Se abre el menú de tu teléfono. Toca WhatsApp y después Estado.'
              : 'El video queda en tu galería. Ábrelo desde WhatsApp › Estado.'}
          </div>

          <button type="button" onClick={onClose} style={{
            width: '100%', padding: '13px', marginTop: 8, background: 'none',
            border: 'none', cursor: 'pointer', fontFamily: T.mono, fontSize: 11,
            letterSpacing: 1.4, textTransform: 'uppercase', color: T.inkMute,
          }}>Cerrar</button>
        </div>
      </div>
    );
  }

  // ── pantalla ───────────────────────────────────────────

  // El boton fisico "atras" del telefono. La app es una sola pagina y nunca
  // escribe historial, asi que ese boton salia de la app entera en vez de
  // volver al inicio.
  //
  // Medido el 20-ago-2026 en un telefono de 843 px de alto: con 96 videos la
  // cuadricula mide 18.553 px -- 22 pantallas. La unica salida era una palabra
  // de 13 px alla arriba. Por eso se reporta como "entre y no puedo salir":
  // no faltaba el boton, faltaba poder alcanzarlo.
  //
  // Dos niveles: si hay una hoja de video abierta, atras cierra la hoja; si no,
  // cierra la pantalla. Al salir por el boton de arriba se retira la entrada
  // que empujamos, para no comerse el siguiente "atras" de la vendedora.
  function useBotonAtras(hayHoja, cerrarHoja, cerrarPantalla) {
    const ref = React.useRef(null);
    ref.current = { hayHoja, cerrarHoja, cerrarPantalla };
    React.useEffect(() => {
      let nuestra = true;
      window.history.pushState({ inovaMultimedia: true }, '');
      const alVolver = () => {
        nuestra = false;
        const s = ref.current;
        if (s.hayHoja) {
          s.cerrarHoja();
          nuestra = true;
          window.history.pushState({ inovaMultimedia: true }, '');
        } else {
          s.cerrarPantalla();
        }
      };
      window.addEventListener('popstate', alVolver);
      return () => {
        window.removeEventListener('popstate', alVolver);
        if (nuestra) window.history.back();
      };
    }, []);
  }

  function MultimediaScreen({ vendedora, campanaId, onClose }) {
    const T = window.T;
    const [videos, setVideos]   = React.useState(null);  // null = cargando
    const [campana, setCampana] = React.useState(campanaId || null);
    const [abierto, setAbierto] = React.useState(null);
    const [fallo, setFallo]     = React.useState('');
    const [marca, setMarca]     = React.useState(null);  // null = todas

    useBotonAtras(!!abierto, () => setAbierto(null), onClose);

    React.useEffect(() => {
      let vivo = true;
      (async () => {
        try {
          const sb = await window.getSupabase();
          if (!sb) throw new Error('Sin conexión');

          // 20-ago-2026: NO se confía en campanaId. Viene de catalogCampaign en
          // index.html, que arranca con el literal 'C12' y sólo se corrige
          // cuando termina de cargar la configuración de campañas.
          //
          // Medido hoy en la app corriendo: en el arranque en frío
          // getCatalogCampaignId() devuelve 'C12', y esta pantalla pedía los
          // videos de C12 — mostraba "Todavía no hay videos de C12" con 19
          // videos cargados en C13. La vendedora lee eso como que no hay, y se
          // va. Se curaba sola al cargar la configuración, pero para entonces
          // ya se fue.
          //
          // Cuál campaña tiene el catálogo a la vista es un dato de la base, no
          // del estado de React. Se pregunta. El prop queda de respaldo por si
          // la consulta falla — mejor una campaña dudosa que ninguna.
          let camp = null;
          const { data: visibles } = await sb.from('campanas')
            .select('id').eq('catalogo_visible', true).eq('cerrada', false)
            .order('id', { ascending: false }).limit(1);
          camp = (visibles && visibles[0]) ? visibles[0].id : (campanaId || null);
          if (!vivo) return;
          setCampana(camp);

          let q = sb.from(TABLA).select('*').eq('activo', true).order('orden', { ascending: true });
          if (camp) q = q.eq('campana_id', camp);
          const { data, error } = await q;
          if (error) throw error;
          if (!vivo) return;
          setVideos(data || []);
        } catch (e) {
          if (!vivo) return;
          setFallo(e.message || 'No se pudieron cargar los videos');
          setVideos([]);
        }
      })();
      return () => { vivo = false; };
    }, [campanaId]);

    // 20-ago-2026: pestañas por marca. Con 19 videos se podía barrer la
    // cuadrícula entera; con ~96 no. La vendedora que hoy va a publicar Ésika
    // no quiere scrollear 60 videos de otras marcas para llegar.
    // Sólo aparece la marca que tiene videos.
    const marcas = React.useMemo(() => {
      if (!videos) return [];
      const hay = new Set(videos.map(v => v.marca).filter(Boolean));
      const conocidas = ORDEN_MARCAS.filter(m => hay.has(m));
      const otras = [...hay].filter(m => !ORDEN_MARCAS.includes(m)).sort();
      return [...conocidas, ...otras];
    }, [videos]);

    // Si la marca elegida se queda sin videos (cambió la campaña), se vuelve a
    // "todas" en lugar de mostrar una cuadrícula vacía con una pestaña marcada.
    React.useEffect(() => {
      if (marca && !marcas.includes(marca)) setMarca(null);
    }, [marcas, marca]);

    const enPantalla = (videos && marca)
      ? videos.filter(v => v.marca === marca)
      : videos;

    const cuentaDe = m => (videos || []).filter(v => v.marca === m).length;

    const pastilla = (activa) => ({
      padding: '9px 15px', borderRadius: 999, cursor: 'pointer',
      border: `1px solid ${activa ? T.ink : T.hairlineStrong}`,
      background: activa ? T.ink : 'transparent',
      color: activa ? T.paper : T.inkSoft,
      fontFamily: T.mono, fontSize: 10.5, letterSpacing: 1.2,
      textTransform: 'uppercase', whiteSpace: 'nowrap',
      flex: '0 0 auto',
    });

    return (
      <div style={{ background: T.paper, minHeight: '100vh', paddingBottom: 40 }}>
        <div style={{
          position: 'sticky', top: 0, zIndex: 40, background: T.paper,
          borderBottom: `1px solid ${T.hairline || T.hairlineStrong}`,
          padding: '10px 24px', display: 'flex',
          alignItems: 'center', justifyContent: 'space-between',
        }}>
          <button onClick={onClose} style={{
            background: 'none', cursor: 'pointer',
            border: `1px solid ${T.hairlineStrong}`, borderRadius: 999,
            padding: '10px 16px', minHeight: 40,
            display: 'inline-flex', alignItems: 'center', gap: 6,
            fontFamily: window.T.mono, fontSize: 11, letterSpacing: 1.4,
            textTransform: 'uppercase', color: T.ink,
          }}>
            <window.Icon name="chevronL" size={14} color={T.ink} /> Volver
          </button>
          <div style={{
            fontFamily: T.mono, fontSize: 10, letterSpacing: 1.5,
            textTransform: 'uppercase', color: T.inkMute,
          }}>{campana || ''}</div>
        </div>

        <div style={{ padding: '0 24px 20px' }}>
          <div style={{
            fontFamily: T.serif, fontSize: 34, color: T.ink,
            letterSpacing: -0.9, lineHeight: 1.05,
          }}>Para tu estado</div>
          <div style={{
            fontFamily: T.sans, fontSize: 14, color: T.inkSoft,
            marginTop: 7, lineHeight: 1.5, maxWidth: '34ch',
          }}>Videos listos para subir a tu Estado de WhatsApp. Un toque y el video pasa a tu teléfono.</div>
        </div>

        {marcas.length > 1 && (
          <div style={{
            display: 'flex', gap: 8, padding: '12px 24px 14px',
            position: 'sticky', top: 61, zIndex: 39, background: T.paper,
            overflowX: 'auto', WebkitOverflowScrolling: 'touch',
          }}>
            <button onClick={() => setMarca(null)} style={pastilla(marca === null)}>
              Todas {videos ? videos.length : ''}
            </button>
            {marcas.map(m => (
              <button key={m} onClick={() => setMarca(m)} style={pastilla(marca === m)}>
                {nombreMarca(m)} {cuentaDe(m)}
              </button>
            ))}
          </div>
        )}

        {videos === null && (
          <div style={{
            padding: '50px 24px', textAlign: 'center',
            fontFamily: T.mono, fontSize: 11, letterSpacing: 1.3,
            textTransform: 'uppercase', color: T.inkMute,
          }}>Cargando…</div>
        )}

        {videos && videos.length === 0 && (
          <div style={{ padding: '10px 24px' }}>
            <div style={{
              border: `1px dashed ${T.hairlineStrong}`, borderRadius: T.r2,
              padding: '34px 22px', textAlign: 'center',
            }}>
              <div style={{ fontFamily: T.serif, fontSize: 20, color: T.ink, marginBottom: 6 }}>
                Todavía no hay videos {campana ? `de ${campana}` : ''}
              </div>
              <div style={{ fontFamily: T.sans, fontSize: 13.5, color: T.inkSoft, lineHeight: 1.5 }}>
                {fallo || 'Cuando se carguen los de esta campaña, aparecen acá.'}
              </div>
            </div>
          </div>
        )}

        {videos && videos.length > 0 && (
          <div style={{
            display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(150px, 1fr))',
            gap: 14, padding: '0 24px',
          }}>
            {enPantalla.map(v => (
              <button key={v.id} onClick={() => setAbierto(v)} style={{
                padding: 0, border: 'none', background: 'transparent',
                cursor: 'pointer', textAlign: 'left',
                display: 'flex', flexDirection: 'column', gap: 8,
              }}>
                <div style={{
                  width: '100%', aspectRatio: '9/16', borderRadius: 14,
                  overflow: 'hidden', background: '#0a0a0a', position: 'relative',
                  boxShadow: '0 10px 24px rgba(0,0,0,0.16)',
                }}>
                  {v.portada_url
                    ? <img src={v.portada_url} alt={v.titulo} loading="lazy"
                        style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
                    : <video src={v.video_url} preload="metadata" muted playsInline
                        style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />}

                  <div style={{
                    position: 'absolute', inset: 0,
                    background: 'linear-gradient(to top, rgba(0,0,0,0.55), transparent 52%)',
                    pointerEvents: 'none',
                  }} />
                  <div style={{
                    position: 'absolute', top: '50%', left: '50%',
                    transform: 'translate(-50%,-50%)',
                    width: 42, height: 42, borderRadius: '50%',
                    background: 'rgba(255,255,255,0.92)',
                    display: 'flex', alignItems: 'center', justifyContent: 'center',
                    boxShadow: '0 3px 12px rgba(0,0,0,0.3)',
                  }}>
                    <div style={{
                      width: 0, height: 0, marginLeft: 3,
                      borderTop: '8px solid transparent',
                      borderBottom: '8px solid transparent',
                      borderLeft: `13px solid ${T.accentDeep}`,
                    }} />
                  </div>
                  {v.duracion_seg ? (
                    <div style={{
                      position: 'absolute', bottom: 7, right: 7,
                      fontFamily: T.mono, fontSize: 10, color: '#fff',
                      background: 'rgba(0,0,0,0.6)', padding: '2px 6px', borderRadius: 5,
                    }}>{fmtDuracion(v.duracion_seg)}</div>
                  ) : null}
                </div>
                <div style={{
                  fontFamily: T.sans, fontSize: 13.5, color: T.ink,
                  lineHeight: 1.3, paddingLeft: 2,
                }}>{v.titulo}</div>
              </button>
            ))}
          </div>
        )}

        {abierto && (
          <VideoSheet video={abierto} vendedora={vendedora} onClose={() => setAbierto(null)} />
        )}
      </div>
    );
  }

  Object.assign(window, { MultimediaScreen, MultimediaVideoSheet: VideoSheet });
})();
