"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import ClientPortalFavoriteButton from "@/components/ClientPortalFavoriteButton";
import { ArrowRight, ChevronLeft, ChevronRight, Pause, Play, Volume2, VolumeX, X } from "lucide-react";
import { useVisaoDaLoja } from "@/components/VisaoDaLojaContext";
import { precoDoCartao } from "@/lib/widgets-da-home";
import { miniatura } from "@/lib/foto";
import { fotoDoProduto, type BoutiqueProduto } from "./BoutiqueCardDoProduto";
import { useArrastoComMouse, useJanela } from "./ganchos-da-home";

/*
  "Compre pelo vídeo" da Boutique (referência, seção 9.2).

  O carrossel: cards verticais 2:3 (200 × 300, raio 15) em fila, arrastáveis
  com o mouse e com o dedo, sem setas. Os cards que estão na tela tocam
  sozinhos, MUDOS e em loop (IntersectionObserver; os que saem pausam; nada
  é baixado antes de aparecer: preload none). Por cima, o play central
  pulsando; embaixo, o cartãozinho branco do produto, que leva à página dele.

  O player: abre por cima de tudo, fundo escuro, vídeo 9:16 no meio no
  computador e a tela inteira no celular, COM SOM (o clique libera o áudio;
  se o navegador recusar, começa mudo e o botão de som avisa). Quando o vídeo
  acaba vai para o próximo; uma barrinha por vídeo no topo mostra o
  andamento. Pausa, som e fechar no canto; setas laterais no computador; na
  lateral direita, embaixo, o coração do favorito (o MESMO do card do
  produto) e o WhatsApp, que compartilha o link do produto (wa.me: a pessoa
  escolhe para quem manda);
  toque (lados = anterior/próximo, meio = pausa) e deslize no celular
  (para o lado troca, para baixo fecha). O cartão do produto escurecido leva
  à página do produto (e pausa o vídeo). Fecha com X, Esc e clique fora;
  trava a rolagem do fundo e prende o foco dentro dele.

  Os dados vêm do vídeo do produto que a loja já cadastra (servidor:
  videos-da-boutique.server.ts). O preço obedece às regras da loja.
*/

export type BoutiqueVideoDaVitrine = { produto: BoutiqueProduto; endereco: string };

function usePrecoDoVideo() {
  const visao = useVisaoDaLoja();
  return useCallback(
    (produto: BoutiqueProduto) => {
      if (!visao.mostrarPreco) return visao.textoNoLugarDoPreco || "";
      return precoDoCartao(produto, visao.textoNoLugarDoPreco).texto;
    },
    [visao.mostrarPreco, visao.textoNoLugarDoPreco]
  );
}

function CardDoVideo({
  video,
  indice,
  aoAbrir,
  pausarTodos,
  slug,
}: {
  video: BoutiqueVideoDaVitrine;
  indice: number;
  aoAbrir: (indice: number) => void;
  pausarTodos: boolean;
  slug: string;
}) {
  const elemento = useRef<HTMLVideoElement | null>(null);
  const [naTela, setNaTela] = useState(false);
  const preco = usePrecoDoVideo();
  const foto = fotoDoProduto(video.produto);

  useEffect(() => {
    const alvo = elemento.current;
    if (!alvo || typeof IntersectionObserver === "undefined") return;
    const observador = new IntersectionObserver(([entrada]) => setNaTela(Boolean(entrada?.isIntersecting)), { threshold: 0.6 });
    observador.observe(alvo);
    return () => observador.disconnect();
  }, []);

  useEffect(() => {
    const alvo = elemento.current;
    if (!alvo) return;
    const calmo = window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
    if (naTela && !pausarTodos && !calmo) {
      alvo.muted = true;
      void alvo.play().catch(() => {});
    } else {
      alvo.pause();
    }
  }, [naTela, pausarTodos]);

  const texto = preco(video.produto);
  return (
    /* O tamanho acompanha a tela como na referência: 200 × 300 no celular e
       até 300 × 450 numa tela de 1920 (--bq-video-l, theme.css). */
    <div className="bq-video-item relative shrink-0 snap-start">
      <button
        type="button"
        onClick={() => aoAbrir(indice)}
        aria-label={`Assistir ao vídeo: ${video.produto.name}`}
        className="bq-video-card group relative block w-full overflow-hidden rounded-[15px] bg-[#ebe7e2] text-left"
      >
        <video
          ref={elemento}
          src={video.endereco}
          poster={foto ? miniatura(foto, 480) : undefined}
          muted
          loop
          playsInline
          preload="none"
          aria-hidden="true"
          tabIndex={-1}
          className="pointer-events-none absolute inset-0 h-full w-full scale-[1.08] object-cover"
        />
        <span className="bq-video-play absolute left-1/2 top-1/2 flex h-[60px] w-[60px] -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full">
          <Play className="ml-1 h-6 w-6 text-white" fill="currentColor" strokeWidth={0} />
        </span>
        {/* O cartãozinho do produto: sobe 20 px por cima do vídeo. */}
        <span className="sr-only">{texto}</span>
      </button>
      {/* O cartãozinho do produto leva direto à página do produto, sem
          passar pelo vídeo. O nome na fonte de revista (Georgia) e o preço na
          fonte do texto (Montserrat), as duas do tema. */}
      <Link
        href={`/${slug}/p/${encodeURIComponent(String(video.produto.id))}`}
        aria-label={`Ver o produto: ${video.produto.name}`}
        className="bq-video-produto group/produto relative z-[1] -mt-5 mx-2.5 flex w-[calc(100%-20px)] items-center gap-2 rounded-[10px] px-2 py-2 text-left lg:mx-5 lg:w-[calc(100%-40px)] lg:gap-2.5 lg:px-3 lg:py-2.5"
      >
        <span className="h-10 w-10 shrink-0 overflow-hidden rounded-lg bg-white lg:h-[52px] lg:w-[52px]">
          {foto ? (
            /* eslint-disable-next-line @next/next/no-img-element */
            <img src={miniatura(foto, 120)} alt="" loading="lazy" draggable={false} className="h-full w-full object-contain" />
          ) : null}
        </span>
        <span className="min-w-0 flex-1">
          <span className="block truncate text-[13px] leading-tight text-[#2d2d2d] lg:text-[15px]" style={{ fontFamily: "var(--bq-fonte-revista)" }}>
            {video.produto.name}
          </span>
          {texto ? (
            <span className="mt-1 line-clamp-2 text-[11px] font-semibold leading-tight text-black lg:mt-1.5 lg:line-clamp-1 lg:text-[12.5px]" style={{ fontFamily: "var(--bq-fonte-texto)" }}>
              {texto}
            </span>
          ) : null}
        </span>
        <ArrowRight className="h-3.5 w-3.5 shrink-0 lg:h-4 lg:w-4 text-[#2d2d2d] transition-transform duration-200 group-hover/produto:translate-x-0.5" strokeWidth={1.6} aria-hidden="true" />
      </Link>
    </div>
  );
}

/* ------------------------------------------------------------- player */

/* O logotipo do WhatsApp (o lucide não tem). */
function IconeDoWhatsApp({ className }: { className?: string }) {
  return (
    <svg viewBox="0 0 24 24" className={className} fill="currentColor" aria-hidden="true">
      <path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413Z" />
    </svg>
  );
}

/* O link do WhatsApp que compartilha o produto: só o texto, sem número (a
   pessoa escolhe a conversa). O endereço é o da página do produto nesta loja. */
function linkParaCompartilhar(nome: string, slug: string, produtoId: string) {
  const origem = typeof window !== "undefined" ? window.location.origin : "";
  const endereco = `${origem}/${slug}/p/${encodeURIComponent(produtoId)}`;
  return `https://wa.me/?text=${encodeURIComponent(`${nome}\n${endereco}`)}`;
}

function PlayerDosVideos({
  videos,
  inicio,
  slug,
  aoFechar,
  clienteId,
  favoritos,
  corDaMarca,
}: {
  videos: BoutiqueVideoDaVitrine[];
  inicio: number;
  slug: string;
  aoFechar: () => void;
  clienteId?: string | null;
  favoritos?: string[] | null;
  corDaMarca?: string;
}) {
  const router = useRouter();
  const [indice, setIndice] = useState(inicio);
  const [pausado, setPausado] = useState(false);
  const [mudo, setMudo] = useState(false);
  const [andamento, setAndamento] = useState(0);
  const elemento = useRef<HTMLVideoElement | null>(null);
  const caixa = useRef<HTMLDivElement | null>(null);
  const botaoFechar = useRef<HTMLButtonElement | null>(null);
  const toque = useRef<{ x: number; y: number; t: number } | null>(null);
  const preco = usePrecoDoVideo();
  const total = videos.length;
  const atual = videos[Math.min(indice, total - 1)];

  useJanela(true, aoFechar, caixa, botaoFechar);

  const ir = useCallback(
    (passo: number) => {
      setIndice((i) => {
        const proximo = i + passo;
        if (proximo < 0 || proximo >= total) return i;
        return proximo;
      });
    },
    [total]
  );

  /* Troca de vídeo: começa do zero, com som (o clique de quem abriu libera
     o áudio). O navegador que não deixar começa mudo. */
  useEffect(() => {
    const alvo = elemento.current;
    if (!alvo) return;
    setAndamento(0);
    setPausado(false);
    alvo.currentTime = 0;
    alvo.muted = mudo;
    alvo.play().catch(() => {
      alvo.muted = true;
      setMudo(true);
      void alvo.play().catch(() => setPausado(true));
    });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [indice]);

  /* A barrinha anda lisa (a cada quadro), não aos pulos do timeupdate. */
  useEffect(() => {
    let quadro = 0;
    const passo = () => {
      const alvo = elemento.current;
      if (alvo && alvo.duration > 0) setAndamento(Math.min(1, alvo.currentTime / alvo.duration));
      quadro = window.requestAnimationFrame(passo);
    };
    quadro = window.requestAnimationFrame(passo);
    return () => window.cancelAnimationFrame(quadro);
  }, []);

  useEffect(() => {
    const aoTeclar = (e: KeyboardEvent) => {
      if (e.key === "ArrowRight") ir(1);
      else if (e.key === "ArrowLeft") ir(-1);
    };
    document.addEventListener("keydown", aoTeclar);
    return () => document.removeEventListener("keydown", aoTeclar);
  }, [ir]);

  const alternarPausa = () => {
    const alvo = elemento.current;
    if (!alvo) return;
    if (alvo.paused) {
      void alvo.play().catch(() => {});
      setPausado(false);
    } else {
      alvo.pause();
      setPausado(true);
    }
  };

  const alternarSom = () => {
    const alvo = elemento.current;
    const novo = !mudo;
    setMudo(novo);
    if (alvo) {
      alvo.muted = novo;
      if (!novo && alvo.paused) void alvo.play().catch(() => {});
    }
  };

  const aoAcabar = () => {
    if (indice < total - 1) ir(1);
    else {
      setPausado(true);
      setAndamento(1);
    }
  };

  if (!atual) return null;
  const foto = fotoDoProduto(atual.produto);
  const texto = preco(atual.produto);

  return (
    <div
      className="bq-player fixed inset-0 z-[95] flex items-center justify-center"
      onClick={(e) => {
        if (e.target === e.currentTarget) aoFechar();
      }}
    >
      <div
        ref={caixa}
        role="dialog"
        aria-modal="true"
        aria-label={`Vídeos dos produtos: ${indice + 1} de ${total}`}
        tabIndex={-1}
        className="bq-player-quadro relative bg-black outline-none"
        onTouchStart={(e) => {
          const t = e.touches[0];
          toque.current = t ? { x: t.clientX, y: t.clientY, t: Date.now() } : null;
        }}
        onTouchEnd={(e) => {
          const inicioDoToque = toque.current;
          toque.current = null;
          const t = e.changedTouches[0];
          if (!inicioDoToque || !t) return;
          if ((e.target as Element).closest("button, a")) return;
          const dx = t.clientX - inicioDoToque.x;
          const dy = t.clientY - inicioDoToque.y;
          if (Math.abs(dx) > 50 && Math.abs(dx) > Math.abs(dy)) {
            ir(dx < 0 ? 1 : -1);
            return;
          }
          if (dy > 90 && Math.abs(dy) > Math.abs(dx)) {
            aoFechar();
            return;
          }
          if (Math.abs(dx) < 12 && Math.abs(dy) < 12) {
            e.preventDefault();
            const caixaDoQuadro = (e.currentTarget as HTMLElement).getBoundingClientRect();
            const posicao = (t.clientX - caixaDoQuadro.left) / caixaDoQuadro.width;
            if (posicao < 0.3) ir(-1);
            else if (posicao > 0.7) ir(1);
            else alternarPausa();
          }
        }}
      >
        <video
          key={atual.endereco}
          ref={elemento}
          src={atual.endereco}
          poster={foto ? miniatura(foto, 720) : undefined}
          playsInline
          autoPlay
          preload="auto"
          onEnded={aoAcabar}
          onClick={alternarPausa}
          className="absolute inset-0 h-full w-full object-cover"
        />

        {/* Uma barrinha por vídeo: as de antes cheias, a atual andando. */}
        <div className="pointer-events-none absolute inset-x-2 top-2 z-10 flex gap-1" aria-hidden="true">
          {videos.map((video, i) => (
            <span key={`${video.endereco}-${i}`} className="h-[2px] flex-1 overflow-hidden rounded-full bg-white/35">
              <span
                className="block h-full origin-left bg-white"
                data-bq-andamento={i === indice ? "" : undefined}
                style={{ transform: `scaleX(${i < indice ? 1 : i === indice ? andamento : 0})` }}
              />
            </span>
          ))}
        </div>

        <div className="absolute right-2.5 top-6 z-10 flex gap-2.5">
          <button type="button" onClick={alternarPausa} aria-label={pausado ? "Tocar" : "Pausar"} className="bq-player-botao">
            {pausado ? <Play className="ml-0.5 h-4 w-4" fill="currentColor" /> : <Pause className="h-4 w-4" fill="currentColor" />}
          </button>
          <button type="button" onClick={alternarSom} aria-label={mudo ? "Ligar o som" : "Tirar o som"} aria-pressed={!mudo} className="bq-player-botao">
            {mudo ? <VolumeX className="h-[18px] w-[18px]" /> : <Volume2 className="h-[18px] w-[18px]" />}
          </button>
          <button ref={botaoFechar} type="button" onClick={aoFechar} aria-label="Fechar os vídeos" className="bq-player-botao">
            <X className="h-[18px] w-[18px]" />
          </button>
        </div>

        {/* Setas fora do vídeo, só no computador. */}
        <button
          type="button"
          onClick={() => ir(-1)}
          disabled={indice === 0}
          aria-label="Vídeo anterior"
          className="bq-player-seta absolute -left-[62px] top-1/2 hidden h-12 w-12 -translate-y-1/2 items-center justify-center text-white md:flex"
        >
          <ChevronLeft className="h-9 w-9" strokeWidth={2.4} />
        </button>
        <button
          type="button"
          onClick={() => ir(1)}
          disabled={indice >= total - 1}
          aria-label="Próximo vídeo"
          className="bq-player-seta absolute -right-[62px] top-1/2 hidden h-12 w-12 -translate-y-1/2 items-center justify-center text-white md:flex"
        >
          <ChevronRight className="h-9 w-9" strokeWidth={2.4} />
        </button>

        {/* Na lateral, ao lado do cartão: o favorito (o mesmo botão do card,
            que leva ao login quem não entrou) e o WhatsApp. */}
        <div className="absolute bottom-[30px] right-2.5 z-10 flex flex-col items-center gap-2.5">
          <span className="bq-player-favorito relative block h-10 w-10">
            <ClientPortalFavoriteButton
              productId={String(atual.produto.id)}
              clientId={clienteId || null}
              initialFavorites={favoritos || null}
              primaryColor={corDaMarca || "#111111"}
              onRequireLogin={() => {
                elemento.current?.pause();
                router.push(`/${slug}/cliente/login`);
              }}
            />
          </span>
          <a
            href={linkParaCompartilhar(atual.produto.name, slug, String(atual.produto.id))}
            target="_blank"
            rel="noopener noreferrer"
            onClick={() => elemento.current?.pause()}
            aria-label={`Compartilhar ${atual.produto.name} pelo WhatsApp`}
            className="bq-player-whats flex h-10 w-10 items-center justify-center rounded-full text-white"
          >
            <IconeDoWhatsApp className="h-[22px] w-[22px]" />
          </a>
        </div>

        <Link
          href={`/${slug}/p/${encodeURIComponent(String(atual.produto.id))}`}
          onClick={() => elemento.current?.pause()}
          className="bq-player-produto absolute bottom-[30px] left-2.5 right-[62px] z-10 flex items-center gap-3 rounded-[10px] p-3 text-white"
        >
          <span className="h-[52px] w-[52px] shrink-0 overflow-hidden rounded-md bg-white">
            {foto ? (
              /* eslint-disable-next-line @next/next/no-img-element */
              <img src={miniatura(foto, 120)} alt="" className="h-full w-full object-contain" />
            ) : null}
          </span>
          <span className="min-w-0 flex-1">
            <span className="block truncate text-[14px] font-medium leading-tight">{atual.produto.name}</span>
            {texto ? <span className="mt-1 block truncate text-[13px] leading-tight text-white/85">{texto}</span> : null}
          </span>
          <ArrowRight className="h-3.5 w-3.5 shrink-0 lg:h-4 lg:w-4 opacity-80" aria-hidden="true" />
          <span className="sr-only">Ver o produto</span>
        </Link>

        <p className="sr-only" aria-live="polite">
          {`Vídeo ${indice + 1} de ${total}: ${atual.produto.name}`}
        </p>
      </div>
    </div>
  );
}

/* ---------------------------------------------------------- o bloco */

export function BoutiqueComprePeloVideo({
  videos,
  slug,
  clienteId,
  favoritos,
  corDaMarca,
}: {
  videos?: BoutiqueVideoDaVitrine[] | null;
  slug: string;
  /* O favorito do player é o mesmo do card: quem entrou marca; quem não
     entrou vai para o login. */
  clienteId?: string | null;
  favoritos?: string[] | null;
  corDaMarca?: string;
}) {
  const lista = (videos || []).filter((v) => v?.produto?.id && v.endereco);
  const trilho = useRef<HTMLDivElement | null>(null);
  const [aberto, setAberto] = useState<number | null>(null);
  useArrastoComMouse(trilho);
  const fechar = useCallback(() => setAberto(null), []);

  if (!lista.length) return null;
  return (
    <section data-bq-videos="" aria-label="Compre pelo vídeo" className="w-full pb-4 pt-5 md:pb-8">
      {/* pb-8: o trilho rola na horizontal e por isso corta o que passa da
          borda de baixo; sem esse respiro, a sombra do cartão do produto
          (0 6px 20px) era comida e o card parecia cortado. */}
      <div ref={trilho} className="bq-sem-barra bq-arrastavel flex snap-x snap-proximity gap-5 overflow-x-auto scroll-px-5 px-5 pb-8">
        {lista.map((video, i) => (
          <CardDoVideo key={`${video.produto.id}-${i}`} video={video} indice={i} aoAbrir={setAberto} pausarTodos={aberto !== null} slug={slug} />
        ))}
      </div>
      {aberto !== null ? (
        <PlayerDosVideos
          videos={lista}
          inicio={aberto}
          slug={slug}
          aoFechar={fechar}
          clienteId={clienteId}
          favoritos={favoritos}
          corDaMarca={corDaMarca}
        />
      ) : null}
    </section>
  );
}
