/**
 * A montra dos vídeos do Criar: a capa de cada vídeo, na proporção do formato.
 *
 * O Início e a lista das criações só tinham texto — o que a plataforma produz não se via sem abrir
 * cada criação (crítica visual, 3 Nov). A capa é o `poster-<formato>.png` que o worker já guarda; ao
 * passar o rato (ou com o foco) o vídeo corre sem som, a não ser com «reduzir movimento».
 */

const ESTADO_DO_VIDEO = {
  aprovado: { texto: 'Aprovado', cor: 'bg-primary' },
  video_por_rever: { texto: 'Para rever', cor: 'bg-accent' },
};

/** O primeiro resultado vertical (o 9:16 das redes), ou o primeiro que houver. */
function resultadoDaCapa(v) {
  const rs = (v && v.resultados) || [];
  const proporcao = (r) => { const [w, h] = String(r.formato || '').split('x').map(Number); return w && h ? w / h : 1; };
  return rs.find((r) => r.formato === '1080x1920') || rs.find((r) => proporcao(r) < 1) || rs[0] || null;
}

/** O vídeo aprovado mais recente que tem esta medida, para mostrar no painel dela. */
function videoNaMedida(videos, formato) {
  // Pela data de aprovação, não pela de criação: a lista vem por criação (revisor, 3 Nov).
  const tempo = (v) => new Date(v.aprovadoEm || v.criadoEm || 0).getTime();
  return (Array.isArray(videos) ? videos : [])
    .filter((v) => v.estado === 'aprovado' && (v.resultados || []).some((r) => r.formato === formato))
    .sort((a, b) => tempo(b) - tempo(a))[0] || null;
}

/** Só os vídeos que já têm o que mostrar. */
function videosComCapa(videos) {
  return (Array.isArray(videos) ? videos : []).filter((v) => ESTADO_DO_VIDEO[v.estado] && resultadoDaCapa(v));
}

function CapaDeVideo({ slug, video, className = '', reservar = false, formato = null, activo = false }) {
  const r = formato ? ((video && video.resultados) || []).find((x) => x.formato === formato) || null : resultadoDaCapa(video);
  const [aCorrer, setACorrer] = React.useState(false);
  // Numa lista, um vídeo sem capa guarda o lugar, para as linhas ficarem alinhadas.
  if (!r) return reservar ? <span aria-hidden="true" className={`block bg-muted ${className}`} style={{ aspectRatio: '9 / 16' }} /> : null;
  const base = `/api/${slug}/criar/video/${encodeURIComponent(video.id)}/ficheiros/`;
  const [w, h] = String(r.formato).split('x').map(Number);
  const calmo = typeof window !== 'undefined' && window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  const mp4 = r.ficheiro || `${r.formato}.mp4`;
  const ligar = () => { if (!calmo) setACorrer(true); };
  const corre = !calmo && (aCorrer || activo);
  return (
    <span
      className={`relative block overflow-hidden bg-muted ${className}`}
      style={{ aspectRatio: w && h ? `${w} / ${h}` : '9 / 16' }}
      onMouseEnter={ligar}
      onMouseLeave={() => setACorrer(false)}
    >
      <img
        src={base + (r.poster || `final-${r.formato}.png`)}
        alt=""
        loading="lazy"
        className="absolute inset-0 h-full w-full object-cover"
      />
      {corre && (
        <video
          src={base + mp4}
          muted
          autoPlay
          loop
          playsInline
          className="absolute inset-0 h-full w-full object-cover"
        />
      )}
    </span>
  );
}

function MontraVideos({ slug, videos, onAbrir, max = 5 }) {
  const lista = videosComCapa(videos).slice(0, max);
  if (!lista.length) return null;
  return (
    <ul className="grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-5">
      {lista.map((v) => <CartaoMontra key={v.id} slug={slug} v={v} onAbrir={onAbrir} />)}
    </ul>
  );
}

/** Um cartão da montra: o vídeo corre com o rato e com o foco do teclado (revisor, 3 Nov). */
function CartaoMontra({ slug, v, onAbrir }) {
  const [foco, setFoco] = React.useState(false);
  const e = ESTADO_DO_VIDEO[v.estado];
  return (
          <li>
            <button
              type="button"
              onClick={() => onAbrir(v)}
              onFocus={() => setFoco(true)}
              onBlur={() => setFoco(false)}
              className="group block w-full text-left outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background"
            >
              <CapaDeVideo
                slug={slug}
                video={v}
                activo={foco}
                className="rounded-md border border-border transition-[border-color,transform] duration-200 ease-out group-hover:-translate-y-0.5 group-hover:border-primary"
              />
              <span className="mt-2.5 block truncate text-sm text-foreground">{v.tema}</span>
              <span className="mt-1 flex items-center gap-1.5 text-xs text-muted-foreground">
                <span className={`h-1.5 w-1.5 rounded-full ${e.cor}`} aria-hidden="true" />
                {e.texto}
                {v.criadoEm && <span>· {formatData(v.criadoEm)}</span>}
              </span>
            </button>
          </li>
  );
}

/**
 * Os formatos de um vídeo lado a lado, à mesma altura, com o destino por baixo. Na campanha nascida do
 * Criar só havia texto e uma ligação; o vídeo aprovado não se via (crítica visual, 3 Nov).
 */
function VideosLadoALado({ slug, videoId, altura = 'h-[22rem]' }) {
  const [video, setVideo] = React.useState(null);
  const [falhou, setFalhou] = React.useState(false);
  const [vez, setVez] = React.useState(0);
  React.useEffect(() => {
    let vivo = true;
    setFalhou(false);
    fetch(`/api/${slug}/criar/video/${encodeURIComponent(videoId)}`, { headers: { 'X-Requested-With': 'NetScreenCriar' } })
      .then((r) => { if (!r.ok) throw Error(String(r.status)); return r.json(); })
      .then((v) => { if (vivo) setVideo(v); })
      .catch(() => { if (vivo) setFalhou(true); });
    return () => { vivo = false; };
  }, [slug, videoId, vez]);
  // Uma leitura falhada diz-se, com como tentar outra vez; não some calada (Codex X-47).
  if (falhou) {
    return (
      <p role="status" className="text-sm text-muted-foreground">
        Não deu para mostrar o vídeo agora.{' '}
        <button type="button" onClick={() => setVez((n) => n + 1)} className="underline underline-offset-2 hover:text-foreground">Tentar outra vez</button>
      </p>
    );
  }
  if (!video) return <div className={`${altura} w-40 animate-pulse rounded-md bg-muted`} aria-hidden="true" />;
  const rs = video.resultados || [];
  if (!rs.length) return null;
  const base = `/api/${slug}/criar/video/${encodeURIComponent(videoId)}/ficheiros/`;
  return (
    <div className="flex flex-wrap items-end gap-x-6 gap-y-4">
      {rs.map((r) => {
        const [w, h] = String(r.formato).split('x').map(Number);
        const deitado = w > h;
        return (
          <figure key={r.formato + (r.rotuloDestino || '')} className={deitado ? 'basis-full space-y-2' : 'space-y-2'}>
            <video
              controls
              playsInline
              preload="metadata"
              className={`${deitado ? 'h-auto w-full max-w-2xl' : `${altura} w-auto max-w-full`} rounded-md border border-border bg-black`}
              src={base + (r.ficheiro || `${r.formato}.mp4`)}
              poster={base + (r.poster || `final-${r.formato}.png`)}
              onPlay={(e) => document.querySelectorAll('video').forEach((v) => { if (v !== e.target) v.pause(); })}
            />
            <figcaption className="text-xs text-muted-foreground">
              <span className="block text-sm text-foreground">{r.rotuloDestino || (r.som ? 'Com som' : 'Sem som')}</span>
              <span className="tabular-nums">{w} × {h}</span>
            </figcaption>
          </figure>
        );
      })}
    </div>
  );
}
