"use client";

import { useEffect, useRef, useState, type CSSProperties, type SyntheticEvent } from "react";
import "@videojs/react/video/skin.css";
import { VideoPlayer, VideoSkin, Video } from "@videojs/react/video";
import { HlsJsVideo } from "@videojs/react/media/hlsjs-video";
import type { HlsJsAdapter } from "@videojs/hlsjs-video";
import { I18nProvider } from "@videojs/react/i18n";
import "@videojs/react/i18n/locales/pt-BR/register";
import { ArrowUpRight, RotateCcw, Volume2, CircleAlert, Play } from "lucide-react";
import { accentText, MAX_POSITION, type PublicVideo, type PlaybackEvent } from "@/lib/player/validation";
import { PlaybackTelemetry } from "@/lib/player/telemetry-client";

function positionOf(media: HTMLVideoElement) {
  return {
    position: Math.min(MAX_POSITION, Math.max(0, media.currentTime || 0)),
    duration: Number.isFinite(media.duration) ? Math.min(MAX_POSITION, media.duration) : 0,
    rate: Math.max(0.25, Math.min(4, media.playbackRate || 1)),
  };
}
function formatTime(seconds: number) {
  return `${Math.floor(seconds / 60)}:${String(Math.floor(seconds % 60)).padStart(2, "0")}`;
}
export function PublicPlayer({ video, ticket = "", preview = false, onDuration }: { video: PublicVideo; ticket?: string; preview?: boolean; onDuration?: (duration: number) => void }) {
  const media = useRef<HTMLVideoElement>(null);
  const hlsAdapter = useRef<HlsJsAdapter | null>(null);
  const telemetry = useRef<PlaybackTelemetry | null>(null);
  const ctaReported = useRef(false);
  const lastSaved = useRef(0);
  const hasStarted = useRef(false);
  const [ready, setReady] = useState(false);
  const [resumeAt, setResumeAt] = useState<number | null>(null);
  const [muted, setMuted] = useState(video.autoplay);
  const [ctaVisible, setCtaVisible] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const key = `arkvideo:position:${video.publicId}`;

  useEffect(() => {
    telemetry.current = preview ? null : new PlaybackTelemetry(video.publicId, ticket);
    telemetry.current?.start(0); // Count a loaded session before play for a meaningful play rate.
    let saved = 0;
    if (video.resume && !preview) {
      try { saved = Number(localStorage.getItem(key) || 0); } catch { /* Storage may be blocked in an iframe. */ }
    }
    if (Number.isFinite(saved) && saved > 5 && saved <= MAX_POSITION) setResumeAt(saved);
    setReady(true);
    const interval = setInterval(() => {
      const element = media.current;
      if (!element || element.paused || element.seeking || element.readyState < 3) return;
      telemetry.current?.start(element.currentTime);
      telemetry.current?.send("heartbeat", positionOf(element));
    }, 15_000);
    const flush = () => {
      const element = media.current;
      if (!element || !hasStarted.current) return;
      telemetry.current?.send(element.paused ? "pause" : "heartbeat", positionOf(element));
      if (video.resume && !preview) try { localStorage.setItem(key, String(element.currentTime)); } catch { /* optional */ }
    };
    const hidden = () => { if (document.visibilityState === "hidden") flush(); };
    window.addEventListener("pagehide", flush);
    document.addEventListener("visibilitychange", hidden);
    return () => {
      clearInterval(interval);
      window.removeEventListener("pagehide", flush);
      document.removeEventListener("visibilitychange", hidden);
    };
  }, [key, ticket, video.publicId, video.resume, preview]);

  useEffect(() => {
    const adapter = hlsAdapter.current;
    if (!adapter) return;
    const handleError = () => setError(adapter.error?.code === 3
      ? "Não foi possível reproduzir este formato. Confira o arquivo ou tente outro navegador."
      : "Não foi possível carregar o vídeo. O link pode ter expirado ou o servidor do vídeo pode estar bloqueando o acesso (CORS).");
    adapter.addEventListener("error", handleError);
    if (adapter.error) handleError();
    return () => adapter.removeEventListener("error", handleError);
  }, [ready]);

  function send(kind: PlaybackEvent["kind"], element = media.current) {
    if (element) telemetry.current?.send(kind, positionOf(element));
  }
  function updateCta(element: HTMLVideoElement) {
    if (!video.cta || !hasStarted.current || element.currentTime < video.cta.at) return;
    setCtaVisible(true);
    if (!ctaReported.current) { ctaReported.current = true; send("cta_show", element); }
  }
  function onTimeUpdate(event: SyntheticEvent<HTMLVideoElement>) {
    const element = event.currentTarget;
    updateCta(element);
    if (video.resume && !preview && !element.seeking && Date.now() - lastSaved.current > 2000) {
      lastSaved.current = Date.now();
      try { localStorage.setItem(key, String(element.currentTime)); } catch { /* optional */ }
    }
  }
  function chooseResume(resume: boolean) {
    const element = media.current;
    if (!element) return;
    const target = resume && resumeAt !== null && (!Number.isFinite(element.duration) || resumeAt < element.duration - 2) ? resumeAt : 0;
    element.currentTime = target;
    setResumeAt(null);
    void element.play().catch(() => setError("Toque em reproduzir para iniciar o vídeo."));
  }
  function onMediaError() {
    const code = media.current?.error?.code;
    setError(code === 3 || code === 4
      ? "Não foi possível reproduzir este formato. Confira o arquivo ou tente outro navegador."
      : video.format === "HLS"
        ? "Não foi possível carregar o vídeo. O link pode ter expirado ou o servidor do vídeo pode estar bloqueando o acesso (CORS)."
        : "Não foi possível carregar o vídeo. O link pode estar indisponível ou expirado. Tente novamente.");
  }
  const common = {
    ref: media, playsInline: true, preload: "metadata" as const,
    muted, autoPlay: ready && video.autoplay && resumeAt === null,
    className: "h-full w-full object-contain",
    onPlay: (event: SyntheticEvent<HTMLVideoElement>) => {
      if (resumeAt !== null) { event.currentTarget.pause(); return; }
      hasStarted.current = true;
      setError(null);
      telemetry.current?.start(event.currentTarget.currentTime);
    },
    onPlaying: (event: SyntheticEvent<HTMLVideoElement>) => {
      send("play", event.currentTarget);
      updateCta(event.currentTarget);
    },
    onPause: (event: SyntheticEvent<HTMLVideoElement>) => send("pause", event.currentTarget),
    onWaiting: (event: SyntheticEvent<HTMLVideoElement>) => send("waiting", event.currentTarget),
    onSeeking: (event: SyntheticEvent<HTMLVideoElement>) => send("seek", event.currentTarget),
    onSeeked: (event: SyntheticEvent<HTMLVideoElement>) => {
      if (!event.currentTarget.paused) send("play", event.currentTarget);
      updateCta(event.currentTarget);
    },
    onRateChange: (event: SyntheticEvent<HTMLVideoElement>) => {
      send("seek", event.currentTarget);
      if (!event.currentTarget.paused) send("play", event.currentTarget);
    },
    onVolumeChange: (event: SyntheticEvent<HTMLVideoElement>) => setMuted(event.currentTarget.muted),
    onLoadedMetadata: (event: SyntheticEvent<HTMLVideoElement>) => {
      const duration = event.currentTarget.duration;
      if (Number.isFinite(duration) && duration > 0 && duration <= MAX_POSITION) onDuration?.(Math.round(duration * 100) / 100);
    },
    onTimeUpdate,
    onEnded: (event: SyntheticEvent<HTMLVideoElement>) => {
      send("ended", event.currentTarget);
      if (video.resume && !preview) try { localStorage.removeItem(key); } catch { /* optional */ }
    },
    onError: onMediaError,
  };
  const style = {
    "--media-accent-color": video.color,
    "--media-accent-text-color": accentText(video.color),
    "--media-border-radius": "0px",
    "--media-border-color": "transparent",
  } as CSSProperties;

  return (
    <div className={`flex w-full flex-col justify-center bg-transparent text-zinc-100 [color-scheme:dark] ${preview ? "" : "min-h-dvh"}`} style={style}>
      <div className="w-full">
        <div className={`relative aspect-video w-full bg-black ${preview ? "" : "max-h-[calc(100dvh-88px)]"}`}>
          <I18nProvider locale="pt-BR">
            <VideoPlayer poster={video.poster ?? undefined}>
              <VideoSkin className="h-full w-full">
                {ready && (video.format === "HLS"
                  ? <HlsJsVideo {...common} mediaRef={hlsAdapter} source={{ src: video.src, type: "application/vnd.apple.mpegurl" }} />
                  : <Video {...common} src={video.src} />)}
              </VideoSkin>
            </VideoPlayer>
          </I18nProvider>
          {resumeAt !== null && (
            <div className="absolute inset-x-4 top-4 z-20 mx-auto flex max-w-md flex-wrap items-center justify-center gap-3 rounded-xl border border-white/10 bg-zinc-950/95 p-4 shadow-xl" role="group" aria-label="Retomar reprodução">
              <p className="w-full text-center text-sm text-zinc-200">Continuar de {formatTime(resumeAt)}?</p>
              <button onClick={() => chooseResume(true)} className="inline-flex min-h-11 items-center gap-2 rounded-lg bg-white px-4 text-sm font-medium text-zinc-950 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-lime-300"><Play className="size-4" />Continuar</button>
              <button onClick={() => chooseResume(false)} className="inline-flex min-h-11 items-center gap-2 rounded-lg px-4 text-sm text-zinc-300 hover:bg-white/10 focus-visible:outline-2 focus-visible:outline-lime-300"><RotateCcw className="size-4" />Do início</button>
            </div>
          )}
        </div>
        {error && (
          <div role="alert" className="flex flex-wrap items-center justify-center gap-3 border-t border-white/10 bg-zinc-950 px-4 py-4 text-sm text-zinc-300">
            <CircleAlert className="size-4 shrink-0" /><p className="max-w-xl">{error}</p>
            <button className="min-h-10 rounded-lg border border-white/15 px-4 text-white hover:bg-white/10" onClick={() => { setError(null); if (hlsAdapter.current) void hlsAdapter.current.load().catch(onMediaError); else media.current?.load(); }}>Tentar novamente</button>
          </div>
        )}
        <div className="flex flex-wrap items-center justify-between gap-3 bg-zinc-950 px-4 py-3">
          <span className="text-xs font-medium tracking-wide text-zinc-400">{video.brand}</span>
          {muted && video.autoplay && <button onClick={() => { if (media.current) media.current.muted = false; setMuted(false); }} className="inline-flex min-h-10 items-center gap-2 rounded-lg border border-white/15 px-3 text-xs text-zinc-100 hover:bg-white/10 focus-visible:outline-2 focus-visible:outline-lime-300"><Volume2 className="size-4" />Ativar som</button>}
          {ctaVisible && video.cta && <a href={video.cta.href} target="_blank" rel="noopener noreferrer" onClick={() => send("cta_click")} className="inline-flex min-h-11 max-w-full items-center justify-center gap-2 rounded-lg bg-[var(--media-accent-color)] px-5 py-2.5 text-center text-sm font-semibold break-words text-[var(--media-accent-text-color)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white">{video.cta.text}<ArrowUpRight className="size-4 shrink-0" /></a>}
        </div>
      </div>
    </div>
  );
}
