"use client";

import { useEffect, useImperativeHandle, useRef, useState, useSyncExternalStore, type Ref } from "react";
import {
  ArrowClockwise as RotateCw,
  ArrowCounterClockwise as RotateCcw,
  CircleNotch as Loader2,
  ClosedCaptioning as Captions,
  CornersIn as Minimize,
  CornersOut as Maximize,
  Pause,
  PictureInPicture as PictureInPicture2,
  Play,
  SpeakerHigh as Volume2,
  SpeakerX as VolumeX,
} from "@phosphor-icons/react";

import { getReadableTextColor } from "@/lib/color-contrast";
import { capituloNoTempo, relogio, type Capitulo } from "@/lib/digitais/curso";

/*
 * O player dos cursos.
 *
 * Vídeo enviado para a loja: player próprio (o endereço assinado vale horas;
 * se vencer no meio, ele pede outro sozinho e volta no mesmo segundo).
 * Vídeo do YouTube, Vimeo ou Panda: o player deles, num quadro.
 *
 * Atalhos: espaço ou K (tocar/pausar), ← → ou J L (10 s), F (tela cheia),
 * M (mudo), C (legenda). A velocidade, o volume e a legenda ficam lembrados
 * neste navegador.
 *
 * A legenda (WebVTT da rota da aula) é desenhada pelo próprio player, acima
 * dos controles; os capítulos marcam a linha do tempo e dão nome ao trecho.
 */

export type FonteDoVideo = { tipo: "arquivo"; url: string } | { tipo: "link"; provedor: "youtube" | "vimeo" | "panda"; url: string };

/* O que a página pode pedir ao player: pular para um trecho (capítulos), e
   pausar ou tocar (outro aparelho começou a tocar o curso). */
export type ControleDoPlayer = { irPara: (segundos: number) => void; pausar: () => void; tocar: () => void };

/* Os cantos por onde a marca d'água passeia (troca a cada 20 s). */
const CANTOS_DA_MARCA = ["left-[6%] top-[8%]", "right-[6%] top-[24%]", "left-[9%] bottom-[30%]", "right-[8%] bottom-[18%]"];

const LEMBRAR_VELOCIDADE = "ks_player_velocidade";
const LEMBRAR_VOLUME = "ks_player_volume";
const LEMBRAR_LEGENDA = "ks_player_legenda";

/* A fala que está na tela agora (texto puro, sem as marcações do arquivo). */
function falaDaFaixa(faixa: TextTrack): string {
  const ativas = faixa.activeCues;
  if (!ativas?.length) return "";
  const falas: string[] = [];
  for (let i = 0; i < ativas.length; i += 1) {
    const deixa = ativas[i] as VTTCue;
    const texto = typeof deixa.getCueAsHTML === "function" ? deixa.getCueAsHTML().textContent ?? "" : String(deixa.text ?? "").replace(/<[^>]+>/g, "");
    if (texto.trim()) falas.push(texto.trim());
  }
  return falas.join("\n");
}

function lembrar(chave: string, valor: string) {
  try {
    window.localStorage.setItem(chave, valor);
  } catch {
    /* Sem armazenamento (aba anônima): só não lembra. */
  }
}

function lembrado(chave: string): string | null {
  try {
    return window.localStorage.getItem(chave);
  } catch {
    return null;
  }
}

const nada = () => () => undefined;

function useNoNavegador<T>(ler: () => T, noServidor: T): T {
  return useSyncExternalStore(nada, ler, () => noServidor);
}

function assinarTelaCheia(avisar: () => void) {
  document.addEventListener("fullscreenchange", avisar);
  document.addEventListener("webkitfullscreenchange", avisar);
  return () => {
    document.removeEventListener("fullscreenchange", avisar);
    document.removeEventListener("webkitfullscreenchange", avisar);
  };
}

/* O endereço do quadro com o que deixa o player de fora mais limpo. */
export function enderecoDoQuadro(fonte: Extract<FonteDoVideo, { tipo: "link" }>, autoplay: boolean): string {
  try {
    const url = new URL(fonte.url);
    if (fonte.provedor === "youtube") {
      url.searchParams.set("rel", "0");
      url.searchParams.set("modestbranding", "1");
      url.searchParams.set("playsinline", "1");
      if (autoplay) url.searchParams.set("autoplay", "1");
    } else if (fonte.provedor === "vimeo") {
      url.searchParams.set("dnt", "1");
      if (autoplay) url.searchParams.set("autoplay", "1");
    }
    return url.toString();
  } catch {
    return fonte.url;
  }
}

async function buscarFonte(endereco: string): Promise<FonteDoVideo> {
  const resposta = await fetch(endereco, { cache: "no-store" });
  const corpo = (await resposta.json().catch(() => null)) as { tipo?: string; url?: string; provedor?: string; error?: string } | null;
  if (!resposta.ok || !corpo?.url) throw new Error(corpo?.error || "Não foi possível abrir o vídeo agora.");
  if (corpo.tipo === "link") return { tipo: "link", provedor: (corpo.provedor as "youtube" | "vimeo" | "panda") || "youtube", url: corpo.url };
  return { tipo: "arquivo", url: corpo.url };
}

export default function PlayerDoCurso({
  fonteEm,
  inicio = null,
  velocidades = [0.75, 1, 1.25, 1.5, 2],
  cor,
  capa = null,
  autoplay = false,
  aoTempo,
  aoPausar,
  aoTerminar,
  aoTocar,
  aoCarregar,
  legendaEm = null,
  capitulos = [],
  marca = null,
  ref,
}: {
  /* A rota que devolve o vídeo (aula ou prévia grátis). */
  fonteEm: string;
  /* O segundo em que o aluno parou (volta nele). */
  inicio?: number | null;
  velocidades?: number[];
  cor: string;
  capa?: string | null;
  autoplay?: boolean;
  aoTempo?: (posicao: number, duracao: number) => void;
  aoPausar?: (posicao: number, duracao: number) => void;
  aoTerminar?: (duracao: number) => void;
  aoTocar?: () => void;
  /* Avisa se o vídeo é do player próprio ou de um quadro de fora. */
  aoCarregar?: (tipo: FonteDoVideo["tipo"]) => void;
  /* A rota da legenda desta aula (WebVTT), quando tem. */
  legendaEm?: string | null;
  /* Os capítulos: marcas na linha do tempo e o nome do trecho atual. */
  capitulos?: Capitulo[];
  /* A marca d'água (o e-mail do aluno) por cima do vídeo. */
  marca?: string | null;
  ref?: Ref<ControleDoPlayer>;
}) {
  const caixa = useRef<HTMLDivElement | null>(null);
  const video = useRef<HTMLVideoElement | null>(null);
  const barra = useRef<HTMLDivElement | null>(null);
  const retomarEm = useRef<number | null>(inicio && inicio > 0 ? inicio : null);
  const tocarAoVoltar = useRef(false);
  const tentativas = useRef(0);
  const esconder = useRef<number | null>(null);
  const arrastando = useRef(false);
  const jaTocou = useRef(false);

  const [carga, setCarga] = useState<{ de: string; fonte: FonteDoVideo | null; erro: string | null }>({ de: "", fonte: null, erro: null });
  const [tocando, setTocando] = useState(false);
  const [esperando, setEsperando] = useState(false);
  const [tempo, setTempo] = useState(0);
  const [duracao, setDuracao] = useState(0);
  const [carregado, setCarregado] = useState(0);
  const [volume, setVolume] = useState(1);
  const [mudo, setMudo] = useState(false);
  const [velocidade, setVelocidade] = useState(1);
  const [menuDaVelocidade, setMenuDaVelocidade] = useState(false);
  const [controles, setControles] = useState(true);
  const [retomado, setRetomado] = useState<number | null>(null);
  const [legendaLigada, setLegendaLigada] = useState(false);
  const [fala, setFala] = useState("");
  /* A fração da linha do tempo sob o mouse (a dica com o tempo e o capítulo). */
  const [dica, setDica] = useState<number | null>(null);
  const [cantoDaMarca, setCantoDaMarca] = useState(0);

  useEffect(() => {
    if (!marca) return;
    const troca = window.setInterval(() => setCantoDaMarca((c) => (c + 1) % CANTOS_DA_MARCA.length), 20_000);
    return () => window.clearInterval(troca);
  }, [marca]);

  const temPip = useNoNavegador(() => typeof document !== "undefined" && Boolean(document.pictureInPictureEnabled), false);
  const telaCheia = useSyncExternalStore(
    assinarTelaCheia,
    () => Boolean(document.fullscreenElement || (document as Document & { webkitFullscreenElement?: Element }).webkitFullscreenElement),
    () => false
  );

  /* Pede o vídeo à rota (de novo quando a aula muda). */
  useEffect(() => {
    let vivo = true;
    buscarFonte(fonteEm)
      .then((fonte) => {
        if (!vivo) return;
        setCarga({ de: fonteEm, fonte, erro: null });
        aoCarregar?.(fonte.tipo);
      })
      .catch((e: unknown) => {
        if (vivo) setCarga({ de: fonteEm, fonte: null, erro: e instanceof Error ? e.message : "Não foi possível abrir o vídeo agora." });
      });
    return () => {
      vivo = false;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps -- aoCarregar só avisa; a busca depende do endereço
  }, [fonteEm]);

  /* O aviso "continuando de 12:34" some sozinho. */
  useEffect(() => {
    if (retomado === null) return;
    const t = window.setTimeout(() => setRetomado(null), 6000);
    return () => window.clearTimeout(t);
  }, [retomado]);

  /* Atalhos do teclado (fora dos campos de texto). */
  useEffect(() => {
    function tecla(e: KeyboardEvent) {
      const v = video.current;
      if (!v || e.metaKey || e.ctrlKey || e.altKey) return;
      const alvo = e.target as HTMLElement | null;
      if (alvo && (alvo.tagName === "INPUT" || alvo.tagName === "TEXTAREA" || alvo.tagName === "SELECT" || alvo.isContentEditable)) return;
      const tecla = e.key.toLowerCase();
      if ((tecla === " " || tecla === "enter") && alvo && (alvo.tagName === "BUTTON" || alvo.tagName === "A")) return;
      if (tecla === " " || tecla === "k") {
        e.preventDefault();
        if (v.paused) void v.play().catch(() => undefined);
        else v.pause();
      } else if (tecla === "arrowleft" || tecla === "j") {
        e.preventDefault();
        v.currentTime = Math.max(0, v.currentTime - 10);
      } else if (tecla === "arrowright" || tecla === "l") {
        e.preventDefault();
        v.currentTime = Math.min(v.duration || v.currentTime + 10, v.currentTime + 10);
      } else if (tecla === "m") {
        v.muted = !v.muted;
      } else if (tecla === "f") {
        void alternarTelaCheia();
      } else if (tecla === "c" && legendaEm) {
        alternarLegenda();
      } else {
        return;
      }
      mostrarControles();
    }
    window.addEventListener("keydown", tecla);
    return () => window.removeEventListener("keydown", tecla);
  });

  useEffect(
    () => () => {
      if (esconder.current) window.clearTimeout(esconder.current);
    },
    []
  );

  useImperativeHandle(ref, () => ({
    irPara(segundos: number) {
      const v = video.current;
      if (!v) return;
      v.currentTime = Math.min(Math.max(0, segundos), v.duration || segundos);
      setTempo(v.currentTime);
      if (v.paused) void v.play().catch(() => undefined);
      mostrarControles();
    },
    pausar() {
      video.current?.pause();
    },
    tocar() {
      const v = video.current;
      if (v?.paused) void v.play().catch(() => undefined);
    },
  }));

  const marcaDagua = marca ? (
    <span
      aria-hidden
      className={`pointer-events-none absolute z-[2] max-w-[60%] select-none truncate text-[11px] font-semibold text-white/40 transition-all duration-1000 sm:text-[13px] ${CANTOS_DA_MARCA[cantoDaMarca]}`}
      style={{ textShadow: "0 1px 2px rgba(0,0,0,0.45)" }}
    >
      {marca}
    </span>
  ) : null;

  /* Liga ou desliga a legenda no vídeo: "hidden" carrega as falas e o player desenha. */
  function aplicarLegenda(v: HTMLVideoElement, ligada: boolean) {
    const faixa = v.textTracks?.[0];
    if (!faixa) return;
    faixa.mode = ligada ? "hidden" : "disabled";
    faixa.oncuechange = ligada ? () => setFala(falaDaFaixa(faixa)) : null;
    setFala(ligada ? falaDaFaixa(faixa) : "");
  }

  function alternarLegenda() {
    const v = video.current;
    if (!v || !legendaEm) return;
    const nova = !legendaLigada;
    setLegendaLigada(nova);
    aplicarLegenda(v, nova);
    lembrar(LEMBRAR_LEGENDA, nova ? "1" : "0");
    mostrarControles();
  }

  function mostrarControles() {
    setControles(true);
    if (esconder.current) window.clearTimeout(esconder.current);
    esconder.current = window.setTimeout(() => {
      if (video.current && !video.current.paused && !arrastando.current) {
        setControles(false);
        setMenuDaVelocidade(false);
      }
    }, 2600);
  }

  function alternar() {
    const v = video.current;
    if (!v) return;
    if (v.paused) void v.play().catch(() => undefined);
    else v.pause();
  }

  function pular(segundos: number) {
    const v = video.current;
    if (!v) return;
    v.currentTime = Math.min(Math.max(0, v.currentTime + segundos), v.duration || v.currentTime + segundos);
    mostrarControles();
  }

  async function alternarTelaCheia() {
    const elemento = caixa.current;
    const v = video.current;
    const doc = document as Document & { webkitExitFullscreen?: () => Promise<void>; webkitFullscreenElement?: Element };
    try {
      if (document.fullscreenElement || doc.webkitFullscreenElement) {
        if (document.exitFullscreen) await document.exitFullscreen();
        else await doc.webkitExitFullscreen?.();
        return;
      }
      const el = elemento as (HTMLDivElement & { webkitRequestFullscreen?: () => Promise<void> }) | null;
      if (el?.requestFullscreen) await el.requestFullscreen();
      else if (el?.webkitRequestFullscreen) await el.webkitRequestFullscreen();
      /* iPhone: só o vídeo vai para a tela cheia. */
      else (v as (HTMLVideoElement & { webkitEnterFullscreen?: () => void }) | null)?.webkitEnterFullscreen?.();
    } catch {
      (v as (HTMLVideoElement & { webkitEnterFullscreen?: () => void }) | null)?.webkitEnterFullscreen?.();
    }
  }

  async function alternarPip() {
    const v = video.current;
    if (!v) return;
    try {
      if (document.pictureInPictureElement) await document.exitPictureInPicture();
      else await v.requestPictureInPicture();
    } catch {
      /* O navegador recusou: segue no player. */
    }
  }

  function mudarVelocidade(nova: number) {
    const v = video.current;
    if (v) v.playbackRate = nova;
    lembrar(LEMBRAR_VELOCIDADE, String(nova));
    setMenuDaVelocidade(false);
    mostrarControles();
  }

  function mudarVolume(novo: number) {
    const v = video.current;
    if (!v) return;
    v.volume = Math.min(1, Math.max(0, novo));
    v.muted = novo <= 0;
    lembrar(LEMBRAR_VOLUME, String(v.volume));
  }

  function fracaoNaBarra(clientX: number): number | null {
    const el = barra.current;
    if (!el) return null;
    const caixaDaBarra = el.getBoundingClientRect();
    if (!caixaDaBarra.width) return null;
    return Math.min(1, Math.max(0, (clientX - caixaDaBarra.left) / caixaDaBarra.width));
  }

  function posicaoNaBarra(clientX: number) {
    const v = video.current;
    const fracao = fracaoNaBarra(clientX);
    if (!v || !v.duration || fracao === null) return;
    v.currentTime = fracao * v.duration;
    setTempo(v.currentTime);
  }

  /* O endereço venceu (ou a rede caiu): pede outro e volta no mesmo segundo. */
  async function renovar() {
    const v = video.current;
    if (!v || tentativas.current >= 2) {
      const motivo = jaTocou.current
        ? "O vídeo parou de carregar. Confira a internet e tente de novo."
        : "Este vídeo não abriu neste navegador. Tente de novo ou avise a loja.";
      setCarga((atual) => ({ ...atual, fonte: null, erro: motivo }));
      return;
    }
    tentativas.current += 1;
    retomarEm.current = v.currentTime || retomarEm.current;
    tocarAoVoltar.current = !v.paused || tocando;
    try {
      const fonte = await buscarFonte(fonteEm);
      setCarga({ de: fonteEm, fonte, erro: null });
    } catch (e) {
      setCarga({ de: fonteEm, fonte: null, erro: e instanceof Error ? e.message : "Não foi possível abrir o vídeo agora." });
    }
  }

  function tentarDeNovo() {
    tentativas.current = 0;
    setCarga({ de: "", fonte: null, erro: null });
    buscarFonte(fonteEm)
      .then((fonte) => setCarga({ de: fonteEm, fonte, erro: null }))
      .catch((e: unknown) => setCarga({ de: fonteEm, fonte: null, erro: e instanceof Error ? e.message : "Não foi possível abrir o vídeo agora." }));
  }

  const fonte = carga.de === fonteEm ? carga.fonte : null;
  const erro = carga.de === fonteEm ? carga.erro : null;
  const carregando = !fonte && !erro;
  const porcento = duracao ? (tempo / duracao) * 100 : 0;
  const corDoTexto = getReadableTextColor(cor);
  const capituloAtual = capitulos.length ? capituloNoTempo(capitulos, tempo) : null;
  const capituloDaDica = dica !== null && capitulos.length ? capituloNoTempo(capitulos, dica * duracao) : null;
  const marcas = duracao ? capitulos.filter((c) => c.inicioS > 0 && c.inicioS < duracao) : [];

  if (fonte?.tipo === "link") {
    return (
      <div className="relative aspect-video w-full overflow-hidden bg-black sm:rounded-[18px]">
        <iframe
          src={enderecoDoQuadro(fonte, autoplay)}
          title="Vídeo"
          className="absolute inset-0 h-full w-full"
          allow="autoplay; fullscreen; picture-in-picture; encrypted-media"
          allowFullScreen
          referrerPolicy="strict-origin-when-cross-origin"
        />
        {marcaDagua}
      </div>
    );
  }

  return (
    <div
      ref={caixa}
      className={`group/player relative aspect-video w-full select-none overflow-hidden bg-black sm:rounded-[18px] ${controles || !tocando ? "" : "cursor-none"}`}
      onMouseMove={mostrarControles}
      onMouseLeave={() => {
        if (tocando && !arrastando.current) setControles(false);
      }}
      onContextMenu={(e) => e.preventDefault()}
    >
      {fonte ? (
        <video
          ref={video}
          key={fonte.url}
          src={fonte.url}
          poster={capa || undefined}
          preload="metadata"
          playsInline
          autoPlay={autoplay}
          controlsList="nodownload noplaybackrate"
          disableRemotePlayback
          className="absolute inset-0 h-full w-full object-contain"
          onClick={() => {
            alternar();
            mostrarControles();
          }}
          onDoubleClick={() => void alternarTelaCheia()}
          onLoadedMetadata={(e) => {
            const v = e.currentTarget;
            setDuracao(Number.isFinite(v.duration) ? v.duration : 0);
            if (legendaEm) {
              const ligada = legendaLigada || lembrado(LEMBRAR_LEGENDA) === "1";
              if (ligada !== legendaLigada) setLegendaLigada(ligada);
              aplicarLegenda(v, ligada);
            }
            const velocidadeLembrada = Number(lembrado(LEMBRAR_VELOCIDADE));
            if (velocidades.includes(velocidadeLembrada)) v.playbackRate = velocidadeLembrada;
            const volumeLembrado = Number(lembrado(LEMBRAR_VOLUME) ?? "");
            if (Number.isFinite(volumeLembrado) && volumeLembrado > 0 && volumeLembrado <= 1) v.volume = volumeLembrado;
            const alvo = retomarEm.current;
            retomarEm.current = null;
            if (alvo && alvo > 5 && Number.isFinite(v.duration) && alvo < v.duration - 5) {
              v.currentTime = alvo;
              setTempo(alvo);
              if (tentativas.current === 0) setRetomado(alvo);
            }
            if (tocarAoVoltar.current) {
              tocarAoVoltar.current = false;
              void v.play().catch(() => undefined);
            }
          }}
          onDurationChange={(e) => {
            const d = e.currentTarget.duration;
            if (Number.isFinite(d)) setDuracao(d);
          }}
          onTimeUpdate={(e) => {
            const v = e.currentTarget;
            if (!arrastando.current) setTempo(v.currentTime);
            if (v.duration && Number.isFinite(v.duration)) aoTempo?.(v.currentTime, v.duration);
          }}
          onProgress={(e) => {
            const v = e.currentTarget;
            if (v.buffered.length && v.duration) setCarregado((v.buffered.end(v.buffered.length - 1) / v.duration) * 100);
          }}
          onPlay={() => {
            setTocando(true);
            aoTocar?.();
            mostrarControles();
          }}
          onPause={(e) => {
            setTocando(false);
            setControles(true);
            const v = e.currentTarget;
            if (v.duration && Number.isFinite(v.duration) && !v.ended) aoPausar?.(v.currentTime, v.duration);
          }}
          onWaiting={() => setEsperando(true)}
          onPlaying={() => {
            setEsperando(false);
            tentativas.current = 0;
            jaTocou.current = true;
          }}
          onCanPlay={() => setEsperando(false)}
          onEnded={(e) => {
            setTocando(false);
            setControles(true);
            aoTerminar?.(e.currentTarget.duration);
          }}
          onVolumeChange={(e) => {
            setVolume(e.currentTarget.volume);
            setMudo(e.currentTarget.muted);
          }}
          onRateChange={(e) => setVelocidade(e.currentTarget.playbackRate)}
          onError={() => void renovar()}
        >
          {legendaEm ? <track kind="subtitles" src={legendaEm} srcLang="pt-BR" label="Português" /> : null}
        </video>
      ) : null}

      {fonte ? marcaDagua : null}

      {fonte && legendaLigada && fala ? (
        <div
          className={`pointer-events-none absolute inset-x-0 z-[1] flex justify-center px-4 transition-[bottom] duration-200 ${
            controles || !tocando ? "bottom-[78px] sm:bottom-[88px]" : "bottom-4 sm:bottom-7"
          }`}
        >
          <span
            className={`max-w-[90%] whitespace-pre-line rounded-md bg-black/75 px-2.5 py-1 text-center font-semibold leading-snug text-white ${
              telaCheia ? "text-[22px] sm:text-[30px]" : "text-[14px] sm:text-[18px]"
            }`}
          >
            {fala}
          </span>
        </div>
      ) : null}

      {carregando || (esperando && tocando) ? (
        <div className="pointer-events-none absolute inset-0 flex items-center justify-center">
          <Loader2 className="h-10 w-10 animate-spin text-white/80" />
        </div>
      ) : null}

      {erro ? (
        <div className="absolute inset-0 flex flex-col items-center justify-center gap-3 px-6 text-center text-white">
          <p className="max-w-[420px] text-[14px] leading-6 text-white/85">{erro}</p>
          <button type="button" onClick={tentarDeNovo} className="h-10 rounded-xl px-4 text-[13px] font-bold" style={{ backgroundColor: cor, color: corDoTexto }}>
            Tentar de novo
          </button>
        </div>
      ) : null}

      {fonte && !tocando && !esperando ? (
        <button
          type="button"
          aria-label="Tocar"
          onClick={alternar}
          className="absolute left-1/2 top-1/2 flex h-16 w-16 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full shadow-lg transition hover:scale-105 sm:h-20 sm:w-20"
          style={{ backgroundColor: cor, color: corDoTexto }}
        >
          <Play weight="fill" className="ml-1 h-7 w-7 fill-current sm:h-8 sm:w-8" />
        </button>
      ) : null}

      {retomado !== null ? (
        <div className="absolute left-3 top-3 flex items-center gap-2 rounded-xl bg-black/75 px-3 py-2 text-[12.5px] text-white backdrop-blur">
          Continuando de {relogio(retomado)}
          <button
            type="button"
            className="font-bold underline-offset-2 hover:underline"
            onClick={() => {
              if (video.current) video.current.currentTime = 0;
              setRetomado(null);
            }}
          >
            Começar do início
          </button>
        </div>
      ) : null}

      {fonte ? (
        <div
          className={`absolute inset-x-0 bottom-0 bg-gradient-to-t from-black/85 via-black/40 to-transparent px-3 pb-2 pt-10 text-white transition-opacity duration-200 sm:px-4 sm:pb-3 ${
            controles || !tocando ? "opacity-100" : "pointer-events-none opacity-0"
          }`}
        >
          <div
            ref={barra}
            role="slider"
            tabIndex={0}
            aria-label="Posição do vídeo"
            aria-valuemin={0}
            aria-valuemax={Math.round(duracao)}
            aria-valuenow={Math.round(tempo)}
            aria-valuetext={`${relogio(tempo)} de ${relogio(duracao)}`}
            className="group/barra relative flex h-4 cursor-pointer items-center"
            onPointerDown={(e) => {
              arrastando.current = true;
              e.currentTarget.setPointerCapture(e.pointerId);
              posicaoNaBarra(e.clientX);
            }}
            onPointerMove={(e) => {
              if (arrastando.current) posicaoNaBarra(e.clientX);
              if (e.pointerType === "mouse" || arrastando.current) setDica(fracaoNaBarra(e.clientX));
            }}
            onPointerLeave={() => setDica(null)}
            onPointerUp={(e) => {
              arrastando.current = false;
              e.currentTarget.releasePointerCapture(e.pointerId);
              if (e.pointerType !== "mouse") setDica(null);
              mostrarControles();
            }}
            onKeyDown={(e) => {
              if (e.key === "ArrowLeft" || e.key === "ArrowRight") {
                e.preventDefault();
                e.stopPropagation();
                pular(e.key === "ArrowLeft" ? -5 : 5);
              }
            }}
          >
            <div className="relative h-1 w-full overflow-hidden rounded-full bg-white/25 transition-all group-hover/barra:h-1.5">
              <div className="absolute inset-y-0 left-0 bg-white/35" style={{ width: `${carregado}%` }} />
              <div className="absolute inset-y-0 left-0" style={{ width: `${porcento}%`, backgroundColor: cor }} />
              {marcas.map((c) => (
                <span key={c.inicioS} className="absolute inset-y-0 w-[3px] -translate-x-1/2 bg-black/80" style={{ left: `${(c.inicioS / duracao) * 100}%` }} />
              ))}
            </div>
            {dica !== null && duracao ? (
              <div
                className="pointer-events-none absolute bottom-5 max-w-[70%] -translate-x-1/2 truncate whitespace-nowrap rounded-md bg-black/85 px-2 py-1 text-[11.5px] font-semibold tabular-nums"
                style={{ left: `${Math.min(88, Math.max(12, dica * 100))}%` }}
              >
                {capituloDaDica ? <span className="mr-1.5 font-normal text-white/75">{capituloDaDica.titulo}</span> : null}
                {relogio(dica * duracao)}
              </div>
            ) : null}
            <div
              className="absolute top-1/2 h-3.5 w-3.5 -translate-x-1/2 -translate-y-1/2 rounded-full opacity-0 shadow transition group-hover/barra:opacity-100"
              style={{ left: `${porcento}%`, backgroundColor: cor }}
            />
          </div>

          <div className="mt-1.5 flex items-center gap-1 sm:gap-2">
            <button type="button" aria-label={tocando ? "Pausar" : "Tocar"} onClick={alternar} className="flex h-9 w-9 items-center justify-center rounded-lg hover:bg-white/10">
              {tocando ? <Pause weight="fill" className="h-5 w-5 fill-current" /> : <Play weight="fill" className="h-5 w-5 fill-current" />}
            </button>
            <button type="button" aria-label="Voltar 10 segundos" onClick={() => pular(-10)} className="relative flex h-9 w-9 items-center justify-center rounded-lg hover:bg-white/10">
              <RotateCcw className="h-5 w-5" />
              <span className="absolute text-[7.5px] font-bold">10</span>
            </button>
            <button type="button" aria-label="Avançar 10 segundos" onClick={() => pular(10)} className="relative flex h-9 w-9 items-center justify-center rounded-lg hover:bg-white/10">
              <RotateCw className="h-5 w-5" />
              <span className="absolute text-[7.5px] font-bold">10</span>
            </button>
            <div className="group/volume flex items-center">
              <button
                type="button"
                aria-label={mudo || volume === 0 ? "Ligar o som" : "Tirar o som"}
                onClick={() => {
                  const v = video.current;
                  if (!v) return;
                  v.muted = !v.muted;
                  if (!v.muted && v.volume === 0) v.volume = 0.6;
                }}
                className="flex h-9 w-9 items-center justify-center rounded-lg hover:bg-white/10"
              >
                {mudo || volume === 0 ? <VolumeX className="h-5 w-5" /> : <Volume2 className="h-5 w-5" />}
              </button>
              <input
                type="range"
                min={0}
                max={1}
                step={0.05}
                value={mudo ? 0 : volume}
                aria-label="Volume"
                onChange={(e) => mudarVolume(Number(e.target.value))}
                className="hidden h-1 w-0 cursor-pointer opacity-0 transition-all group-hover/volume:w-20 group-hover/volume:opacity-100 sm:block"
                style={{ accentColor: cor }}
              />
            </div>
            <span className="ml-1 whitespace-nowrap text-[12px] tabular-nums text-white/85">
              {relogio(tempo)} <span className="text-white/50">/ {relogio(duracao)}</span>
            </span>
            {capituloAtual ? <span className="ml-1 hidden min-w-0 truncate text-[12px] text-white/75 sm:block">· {capituloAtual.titulo}</span> : null}
            <div className="flex-1" />
            {legendaEm ? (
              <button
                type="button"
                aria-label={legendaLigada ? "Desligar a legenda" : "Ligar a legenda"}
                aria-pressed={legendaLigada}
                title="Legenda (C)"
                onClick={alternarLegenda}
                className="relative flex h-9 w-9 shrink-0 items-center justify-center rounded-lg hover:bg-white/10"
              >
                <Captions className="h-5 w-5" />
                {legendaLigada ? <span className="absolute bottom-1 left-2 right-2 h-0.5 rounded-full" style={{ backgroundColor: cor }} /> : null}
              </button>
            ) : null}
            {velocidades.length > 1 ? (
              <div className="relative">
                <button
                  type="button"
                  aria-label="Velocidade"
                  aria-expanded={menuDaVelocidade}
                  onClick={() => setMenuDaVelocidade((aberto) => !aberto)}
                  className="h-9 min-w-[44px] rounded-lg px-2 text-[12.5px] font-bold hover:bg-white/10"
                >
                  {String(velocidade).replace(".", ",")}x
                </button>
                {menuDaVelocidade ? (
                  <div className="absolute bottom-11 right-0 z-10 min-w-[96px] overflow-hidden rounded-xl bg-black/90 py-1 shadow-xl backdrop-blur">
                    {velocidades.map((opcao) => (
                      <button
                        key={opcao}
                        type="button"
                        onClick={() => mudarVelocidade(opcao)}
                        className={`block w-full px-4 py-2 text-left text-[13px] hover:bg-white/10 ${opcao === velocidade ? "font-bold text-white" : "text-white/75"}`}
                      >
                        {opcao === 1 ? "Normal" : `${String(opcao).replace(".", ",")}x`}
                      </button>
                    ))}
                  </div>
                ) : null}
              </div>
            ) : null}
            {temPip ? (
              <button type="button" aria-label="Janela flutuante" onClick={() => void alternarPip()} className="hidden h-9 w-9 items-center justify-center rounded-lg hover:bg-white/10 sm:flex">
                <PictureInPicture2 className="h-5 w-5" />
              </button>
            ) : null}
            <button type="button" aria-label={telaCheia ? "Sair da tela cheia" : "Tela cheia"} onClick={() => void alternarTelaCheia()} className="flex h-9 w-9 items-center justify-center rounded-lg hover:bg-white/10">
              {telaCheia ? <Minimize className="h-5 w-5" /> : <Maximize className="h-5 w-5" />}
            </button>
          </div>
        </div>
      ) : null}
    </div>
  );
}
