"use client";

import { usePathname, useRouter } from "next/navigation";
import { useCallback, useEffect, useMemo, useState } from "react";
import { ArrowsOut, Broadcast, SpeakerHigh, SpeakerSlash, X } from "@phosphor-icons/react";

import { entrarNaSala } from "@/lib/live/cliente/api";
import { estaDentroDaLive } from "@/lib/live/dentro-da-live";

import { useSalaAoVivo, type Entrada } from "./useSalaAoVivo";
import VideoDaTrilha, { SomDaTrilha } from "./VideoDaTrilha";

import "./mini.css";

/*
 * Liveshop: enquanto uma live com "mostrar nas páginas dos produtos" está no
 * ar, a página de cada produto dela (e a vitrine) mostra a chamada AO VIVO.
 * Quem clica assiste ali mesmo, num player pequeno que continua tocando
 * enquanto navega pela loja (ele mora no layout da loja), e o produto que
 * quem apresenta está mostrando aparece embaixo com o botão de comprar.
 */

type LiveNaVitrine = {
  salaId: string;
  titulo: string;
  acesso: "paga" | "cadastro" | "aberta";
  produtos: string[];
  produtoDaLive: string | null;
  capa: string | null;
  foco: string | null;
};

const UUID = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i;
const CHAVE_FECHADA = "ktalogu-live:fechada";

function produtoDaPagina(caminho: string): string | null {
  const m = caminho.match(/\/p\/([0-9a-f-]{36})/i);
  return m && UUID.test(m[1]) ? m[1].toLowerCase() : null;
}

function paginaSemChamada(caminho: string) {
  return /\/(live|membros|comprar|checkout|entrega|cliente|status|o)(\/|$)/.test(caminho);
}

function lerFechada(): string | null {
  try {
    return sessionStorage.getItem(CHAVE_FECHADA);
  } catch {
    return null;
  }
}

export default function LiveDaLoja({ slug }: { slug: string }) {
  const caminho = usePathname() || "";
  const [lives, setLives] = useState<LiveNaVitrine[]>([]);
  const [assistindo, setAssistindo] = useState<{ live: LiveNaVitrine; entrada: Entrada } | null>(null);
  const [entrando, setEntrando] = useState(false);
  const [fechada, setFechada] = useState<string | null>(null);
  /* Lives que acabaram enquanto a pessoa assistia: a chamada não volta. */
  const [acabadas, setAcabadas] = useState<string[]>([]);
  const [erro, setErro] = useState<string | null>(null);

  /* Aberta por trás da própria live: não chama de novo para a mesma live. */
  const [naLive, setNaLive] = useState(false);
  useEffect(() => setNaLive(estaDentroDaLive()), []);

  useEffect(() => setFechada(lerFechada()), []);

  /* Pergunta de tempos em tempos se há live no ar (a resposta vem guardada do servidor). */
  useEffect(() => {
    if (naLive) return;
    let vivo = true;
    const ler = () =>
      fetch(`/api/live/agora?loja=${encodeURIComponent(slug)}`, { cache: "no-store" })
        .then((r) => (r.ok ? r.json() : { lives: [] }))
        .then((j: { lives?: LiveNaVitrine[] }) => {
          if (vivo) setLives(Array.isArray(j.lives) ? j.lives : []);
        })
        .catch(() => undefined);
    void ler();
    const t = setInterval(ler, 45000);
    return () => {
      vivo = false;
      clearInterval(t);
    };
  }, [slug, naLive]);

  const produto = produtoDaPagina(caminho);
  const naHome = caminho === `/${slug}` || caminho === "/" || caminho === "";
  const live = useMemo(() => {
    if (!lives.length) return null;
    const noAr = lives.filter((l) => !acabadas.includes(l.salaId));
    if (produto) return noAr.find((l) => l.produtos.includes(produto) || l.produtoDaLive === produto) ?? null;
    if (naHome) return noAr[0] ?? null;
    return null;
  }, [lives, produto, naHome, acabadas]);

  const assistir = async (alvo: LiveNaVitrine) => {
    if (alvo.acesso !== "aberta") {
      window.location.href = `/${slug}/live/${alvo.salaId}`;
      return;
    }
    setEntrando(true);
    setErro(null);
    try {
      let nome = "";
      try {
        nome = localStorage.getItem("ktalogu-live:nome") || "";
      } catch {
        nome = "";
      }
      let anterior: string | null = null;
      try {
        anterior = sessionStorage.getItem(`ktalogu-live:${alvo.salaId}`);
      } catch {
        anterior = null;
      }
      const json = (await entrarNaSala(alvo.salaId, { nome, vitrine: true, anterior })) as unknown as Entrada;
      try {
        sessionStorage.setItem(`ktalogu-live:${alvo.salaId}`, json.eu.credencial);
      } catch {
        /* sem armazenamento */
      }
      setAssistindo({ live: alvo, entrada: json });
    } catch (e) {
      setErro(e instanceof Error ? e.message : "Não deu para abrir a live agora.");
    } finally {
      setEntrando(false);
    }
  };

  const fechar = (salaId: string) => {
    try {
      sessionStorage.setItem(CHAVE_FECHADA, salaId);
    } catch {
      /* sem armazenamento */
    }
    setFechada(salaId);
  };

  if (assistindo) {
    return (
      <MiniPlayer
        slug={slug}
        live={assistindo.live}
        entrada={assistindo.entrada}
        aoFechar={(acabou) => {
          if (acabou) setAcabadas((lista) => [...lista, assistindo.live.salaId]);
          setAssistindo(null);
        }}
      />
    );
  }
  if (naLive || !live || paginaSemChamada(caminho) || fechada === live.salaId) return null;

  const mostrandoEste = produto && live.foco === produto;
  return (
    <div className="lm-chamada" role="region" aria-label="Live ao vivo agora">
      <button type="button" className="lm-fechar" aria-label="Fechar" onClick={() => fechar(live.salaId)}>
        <X weight="bold" />
      </button>
      <span className="lm-foto" style={live.capa ? { backgroundImage: `url("${live.capa}")` } : undefined} />
      <div className="lm-txt">
        <span className="lm-ao-vivo">
          <i />
          AO VIVO
        </span>
        <b>{live.titulo}</b>
        <small>{erro ?? (mostrandoEste ? "Mostrando este produto agora!" : "A loja está ao vivo agora")}</small>
      </div>
      <button type="button" className="lm-botao" onClick={() => void assistir(live)} disabled={entrando}>
        <Broadcast weight="fill" />
        {entrando ? "Abrindo…" : "Assistir"}
      </button>
    </div>
  );
}

function moeda(valor: number) {
  return valor.toLocaleString("pt-BR", { style: "currency", currency: "BRL" });
}

function MiniPlayer({ slug, live, entrada, aoFechar }: { slug: string; live: LiveNaVitrine; entrada: Entrada; aoFechar: (acabou: boolean) => void }) {
  const s = useSalaAoVivo(entrada, { compacta: true });
  const router = useRouter();
  const [mudo, setMudo] = useState(false);
  const { estado } = s;

  const daEquipe = estado.palco.filter((p) => p.papel === "apresentador" || p.papel === "convidado");
  const recebida = useCallback(
    (participante: string, tipo: string) => s.recebidas.find((r) => r.participante === participante && r.tipo === tipo)?.track ?? null,
    [s.recebidas],
  );
  const quemMostraTela = daEquipe.find((p) => p.trilhas.tela) ?? null;
  const tela = quemMostraTela ? recebida(quemMostraTela.id, "tela") : null;
  const cam = (() => {
    for (const p of daEquipe) {
      const t = recebida(p.id, "cam");
      if (t) return t;
    }
    return null;
  })();
  const principal = tela ?? cam;
  const encerrada = estado.status === "encerrada" || estado.status === "cancelada";

  useEffect(() => {
    if (s.saida || encerrada) {
      const t = setTimeout(() => aoFechar(encerrada), encerrada ? 6000 : 0);
      return () => clearTimeout(t);
    }
  }, [s.saida, encerrada, aoFechar]);

  const sair = () => {
    s.sair();
    aoFechar(false);
  };

  const foco = estado.foco;
  return (
    <div className={`lm-player${tela ? " paisagem grande" : ""}`} role="region" aria-label={`Live: ${live.titulo}`}>
      {s.recebidas
        .filter((r) => r.tipo === "mic" || r.tipo === "tela-audio")
        .map((r) => (
          <SomDaTrilha key={`${r.participante}:${r.tipo}:${r.nome}`} track={r.track} mudo={mudo} />
        ))}
      <div className="lm-video">
        {principal ? (
          <VideoDaTrilha track={principal} className={tela ? "contida" : ""} />
        ) : (
          <div className="lm-vazio">
            {encerrada
              ? "A live terminou. Obrigado por assistir!"
              : !entrada.sfu
                ? "O vídeo desta live ainda não está ligado. O produto em destaque aparece aqui embaixo."
                : s.situacao === "conectada"
                  ? "Quem apresenta está sem câmera agora."
                  : "Conectando à live…"}
          </div>
        )}
        <div className="lm-topo">
          <span className="lm-ao-vivo">
            <i />
            AO VIVO
          </span>
          <span className="lm-pessoas">{estado.pessoas} assistindo</span>
          <span className="lm-acoes">
            <button type="button" aria-label={mudo ? "Ligar o som" : "Tirar o som"} onClick={() => setMudo((m) => !m)}>
              {mudo ? <SpeakerSlash weight="fill" /> : <SpeakerHigh weight="fill" />}
            </button>
            <a href={`/${slug}/live/${live.salaId}`} aria-label="Abrir a live inteira" title="Abrir a live inteira (com bate-papo)">
              <ArrowsOut weight="bold" />
            </a>
            <button type="button" aria-label="Fechar" onClick={sair}>
              <X weight="bold" />
            </button>
          </span>
        </div>
        <span className="lm-titulo">{live.titulo}</span>
      </div>
      {foco && !encerrada ? (
        <div className="lm-produto">
          {foco.imagem ? <img src={foco.imagem} alt="" /> : null}
          <div className="lm-txt">
            <small>Mostrando agora</small>
            <b>{foco.titulo}</b>
            {foco.preco ? <span>{moeda(foco.preco)}</span> : null}
          </div>
          <button type="button" className="lm-botao" onClick={() => foco.destino && router.push(foco.destino)}>
            Comprar
          </button>
        </div>
      ) : null}
      {s.aviso ? <div className="lm-aviso">{s.aviso.texto}</div> : null}
    </div>
  );
}
