"use client";

import { useEffect, useRef, useState } from "react";
import {
  Broadcast,
  Camera,
  Check,
  HandWaving,
  Link as IconeDeLink,
  Microphone,
  PaperPlaneTilt,
  PushPin,
  ShoppingBag,
  Ticket,
  Trash,
  X,
} from "@phosphor-icons/react";

import type { MensagemDaSala, Oferta } from "@/lib/live/evento";
import { iniciais } from "@/lib/live/regras";

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

export type Aba = "chat" | "pessoas" | "aovivo";

type PessoaDaLista = {
  id: string;
  nome: string;
  papel: string;
  foto: string | null;
  mao: string | null;
  podeFalar: boolean;
  camera: boolean;
  microfone: boolean;
  tela?: boolean;
  eu?: boolean;
};

function hora(iso: string) {
  try {
    return new Intl.DateTimeFormat("pt-BR", { hour: "2-digit", minute: "2-digit", timeZone: "America/Sao_Paulo" }).format(new Date(iso));
  } catch {
    return "";
  }
}

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

/* O texto da mensagem com os links clicáveis (só https). */
function TextoComLinks({ texto }: { texto: string }) {
  const partes = texto.split(/(https:\/\/[^\s]+)/g);
  return (
    <>
      {partes.map((parte, i) =>
        /^https:\/\//.test(parte) ? (
          <a key={i} href={parte} target="_blank" rel="noopener noreferrer nofollow" style={{ color: "var(--m-acento)", fontWeight: 700 }}>
            {parte.length > 48 ? `${parte.slice(0, 45)}…` : parte}
          </a>
        ) : (
          <span key={i}>{parte}</span>
        ),
      )}
    </>
  );
}

const TITULOS: Record<Aba, string> = { chat: "Mensagens na chamada", pessoas: "Pessoas", aovivo: "Ferramentas da live" };

/* O painel do lado (como no Meet): um de cada vez, com o título e o fechar. */
export default function LadoDaLive({
  s,
  entrada,
  aba,
  aoFechar,
}: {
  s: SalaAoVivo;
  entrada: Entrada;
  aba: Aba;
  aoTrocar?: (aba: Aba) => void;
  aoFechar: () => void;
}) {
  const { equipe } = s;
  const reuniao = entrada.sala.categoria === "reuniao";

  return (
    <aside className="lv-lado" aria-label={TITULOS[aba]}>
      <div className="lv-lado-topo">
        <h2>{aba === "aovivo" && reuniao ? "Links e recados" : TITULOS[aba]}</h2>
        <button type="button" className="lv-fechar" onClick={aoFechar} aria-label="Fechar o painel">
          <X />
        </button>
      </div>
      {aba === "chat" ? <BatePapo s={s} livre={entrada.sala.participacao === "livre"} /> : null}
      {aba === "pessoas" ? <Pessoas s={s} reuniao={reuniao} /> : null}
      {aba === "aovivo" && equipe ? <PainelAoVivo s={s} entrada={entrada} /> : null}
    </aside>
  );
}

/* Mãos levantadas. Na reunião todo mundo já pode falar: a mão é só um aviso, e quem organiza só baixa. */
function PedidosParaFalar({ s, livre }: { s: SalaAoVivo; livre: boolean }) {
  const [ocupado, setOcupado] = useState<string | null>(null);
  if (!s.estado.maos.length) return null;
  const agir = async (id: string, acao: "fala" | "baixar_mao", pode?: boolean) => {
    setOcupado(id);
    try {
      await s.moderar(acao, { participante: id, ...(acao === "fala" ? { pode } : {}) });
    } catch (erro) {
      s.setAviso({ texto: erro instanceof Error ? erro.message : "Não deu agora.", tom: "ruim" });
    } finally {
      setOcupado(null);
    }
  };
  return (
    <div className="lv-pedidos">
      <h4>
        <HandWaving weight="fill" /> Mãos levantadas · {s.estado.maos.length}
      </h4>
      {s.estado.maos.map((m) => (
        <div className="lv-pedido" key={m.id}>
          <b>{m.nome}</b>
          {livre ? null : (
            <button type="button" className="lv-sim" disabled={ocupado === m.id} onClick={() => void agir(m.id, "fala", true)}>
              <Check weight="bold" /> Liberar
            </button>
          )}
          <button type="button" className="lv-nao" aria-label="Baixar a mão" disabled={ocupado === m.id} onClick={() => void agir(m.id, "baixar_mao")}>
            <X weight="bold" />
          </button>
        </div>
      ))}
    </div>
  );
}

function BatePapo({ s, livre }: { s: SalaAoVivo; livre: boolean }) {
  const [texto, setTexto] = useState("");
  const [mandando, setMandando] = useState(false);
  const lista = useRef<HTMLDivElement | null>(null);
  const colado = useRef(true);
  const { estado, equipe } = s;
  const fechado = !equipe && estado.chat === "desligado";
  const encerrada = estado.status === "encerrada" || estado.status === "cancelada";

  useEffect(() => {
    const el = lista.current;
    if (el && colado.current) el.scrollTop = el.scrollHeight;
  }, [s.mensagens.length]);

  const mandar = async () => {
    const limpo = texto.trim();
    if (!limpo || mandando) return;
    /* O campo esvazia na hora (a mensagem já aparece); se falhar, o texto volta. */
    setMandando(true);
    setTexto("");
    colado.current = true;
    try {
      await s.mandarMensagem(limpo);
    } catch (erro) {
      setTexto((atual) => atual || limpo);
      s.setAviso({ texto: erro instanceof Error ? erro.message : "A mensagem não foi.", tom: "ruim" });
    } finally {
      setMandando(false);
    }
  };

  const apagar = async (m: MensagemDaSala) => {
    try {
      await s.moderar("apagar", { mensagem: m.id });
    } catch (erro) {
      s.setAviso({ texto: erro instanceof Error ? erro.message : "Não deu para apagar.", tom: "ruim" });
    }
  };

  return (
    <>
      {equipe ? <PedidosParaFalar s={s} livre={livre} /> : null}
      {estado.fixado ? (
        <div className="lv-fixado">
          <small>
            <PushPin weight="fill" /> Fixado
          </small>
          {estado.fixado.texto}{" "}
          {estado.fixado.link ? (
            <a href={estado.fixado.link} target="_blank" rel="noopener noreferrer nofollow">
              {estado.fixado.rotuloDoLink || "Abrir"}
            </a>
          ) : null}
        </div>
      ) : null}
      <div
        className="lv-mensagens"
        ref={lista}
        onScroll={(e) => {
          const el = e.currentTarget;
          colado.current = el.scrollHeight - el.scrollTop - el.clientHeight < 60;
        }}
      >
        {!s.mensagens.length ? (
          <div className="lv-aviso-chat">
            {estado.chat === "perguntas" && !equipe
              ? "Mande a sua pergunta: ela vai direto para quem apresenta."
              : fechado
                ? "Só quem apresenta escreve aqui."
                : "As mensagens aparecem aqui para todo mundo que está na sala."}
          </div>
        ) : null}
        {s.mensagens.map((m) => {
          const daLoja = m.papel === "apresentador" || m.papel === "convidado";
          return (
            <div className={`lv-msg${daLoja ? " loja" : ""}${m.pendente ? " pendente" : ""}`} key={m.id}>
              <span className={`lv-av${m.foto ? " lv-av-logo" : ""}`} style={m.foto ? { backgroundImage: `url("${m.foto}")` } : undefined}>
                {m.foto ? "" : iniciais(m.nome)}
              </span>
              <div style={{ minWidth: 0 }}>
                <b>
                  {m.nome}
                  {daLoja ? <span className="lv-selo">{livre && m.papel === "apresentador" ? "organiza" : "apresenta"}</span> : null}
                  {m.pergunta ? <span className="lv-selo pergunta">pergunta</span> : null}
                  <time>{m.pendente ? "enviando…" : hora(m.em)}</time>
                </b>
                <p>
                  <TextoComLinks texto={m.texto} />
                </p>
              </div>
              {equipe && !m.pendente ? (
                <button type="button" className="lv-apagar" aria-label="Apagar a mensagem" onClick={() => void apagar(m)}>
                  <Trash weight="bold" />
                </button>
              ) : null}
            </div>
          );
        })}
      </div>
      {encerrada ? null : fechado ? (
        <div className="lv-escrever" style={{ justifyContent: "center", fontSize: 12.5, color: "var(--m-texto-3)" }}>
          Só quem apresenta escreve aqui.
        </div>
      ) : (
        <div className="lv-escrever">
          <input
            value={texto}
            maxLength={500}
            placeholder={estado.chat === "perguntas" && !equipe ? "Mande a sua pergunta…" : "Enviar uma mensagem"}
            onChange={(e) => setTexto(e.target.value)}
            onKeyDown={(e) => {
              if (e.key === "Enter" && !e.shiftKey) {
                e.preventDefault();
                void mandar();
              }
            }}
            aria-label="Mensagem"
          />
          <button type="button" onClick={() => void mandar()} disabled={!texto.trim() || mandando} aria-label="Mandar">
            <PaperPlaneTilt weight="fill" />
          </button>
        </div>
      )}
    </>
  );
}

function Pessoas({ s, reuniao }: { s: SalaAoVivo; reuniao: boolean }) {
  const [pessoas, setPessoas] = useState<PessoaDaLista[] | null>(null);
  const { equipe } = s;

  useEffect(() => {
    let vivo = true;
    const ler = () =>
      s.api
        .pedir<{ pessoas: PessoaDaLista[] }>("pessoas", undefined, { metodo: "GET" })
        .then((r) => {
          if (vivo) setPessoas(r.pessoas);
        })
        .catch(() => undefined);
    void ler();
    const t = setInterval(ler, 20000);
    return () => {
      vivo = false;
      clearInterval(t);
    };
  }, [s.api]);

  const tirar = async (p: PessoaDaLista) => {
    try {
      await s.moderar("tirar", { participante: p.id });
      setPessoas((lista) => (lista ?? []).filter((x) => x.id !== p.id));
      s.setAviso({ texto: `${p.nome} saiu da sala.` });
    } catch (erro) {
      s.setAviso({ texto: erro instanceof Error ? erro.message : "Não deu agora.", tom: "ruim" });
    }
  };

  const pararTela = async (p: PessoaDaLista) => {
    try {
      await s.moderar("parar_tela", { participante: p.id });
      setPessoas((lista) => (lista ?? []).map((x) => (x.id === p.id ? { ...x, tela: false } : x)));
    } catch (erro) {
      s.setAviso({ texto: erro instanceof Error ? erro.message : "Não deu agora.", tom: "ruim" });
    }
  };

  const silenciar = async (p: PessoaDaLista) => {
    try {
      await s.moderar("silenciar", { participante: p.id });
      setPessoas((lista) => (lista ?? []).map((x) => (x.id === p.id ? { ...x, microfone: false } : x)));
    } catch (erro) {
      s.setAviso({ texto: erro instanceof Error ? erro.message : "Não deu agora.", tom: "ruim" });
    }
  };

  const fala = async (p: PessoaDaLista, pode: boolean) => {
    try {
      await s.moderar("fala", { participante: p.id, pode });
      setPessoas((lista) => (lista ?? []).map((x) => (x.id === p.id ? { ...x, podeFalar: pode, mao: null } : x)));
    } catch (erro) {
      s.setAviso({ texto: erro instanceof Error ? erro.message : "Não deu agora.", tom: "ruim" });
    }
  };

  return (
    <div className="lv-painel" style={{ gap: 0 }}>
      {pessoas === null ? <div className="lv-aviso-chat">Carregando…</div> : null}
      {pessoas ? (
        <h4 className="lv-pessoas-titulo">
          {reuniao ? "Na chamada" : "Na sala"} · {pessoas.length}
        </h4>
      ) : null}
      {(pessoas ?? []).map((p) => {
        const daLoja = p.papel === "apresentador" || p.papel === "convidado";
        return (
          <div className="lv-pessoa" key={p.id}>
            <span className={`lv-av${p.foto ? " lv-av-logo" : ""}`} style={p.foto ? { backgroundImage: `url("${p.foto}")` } : undefined}>
              {p.foto ? "" : iniciais(p.nome)}
            </span>
            <div style={{ flex: 1, minWidth: 0 }}>
              <b style={{ display: "block" }}>
                {p.nome}
                {p.eu ? " (você)" : ""}
              </b>
              {daLoja || p.tela ? (
                <span className="lv-papel">
                  {[daLoja ? (p.papel === "apresentador" ? (reuniao ? "Organiza" : "Apresenta") : "Apresenta junto") : null, p.tela ? "Mostrando a tela" : null]
                    .filter(Boolean)
                    .join(" · ")}
                </span>
              ) : null}
            </div>
            <span className="lv-icones">
              {p.mao ? <HandWaving weight="fill" style={{ color: "#ffc21a" }} /> : null}
              {p.microfone ? <Microphone weight="fill" /> : null}
              {p.camera ? <Camera weight="fill" /> : null}
            </span>
            {equipe && p.tela && !p.eu ? (
              <button type="button" className="lv-bt leve" onClick={() => void pararTela(p)} title="Parar a apresentação desta pessoa">
                Parar a tela
              </button>
            ) : null}
            {equipe && !daLoja ? (
              <>
                {p.microfone ? (
                  <button type="button" className="lv-bt leve" onClick={() => void silenciar(p)} title="Fechar o microfone desta pessoa">
                    Silenciar
                  </button>
                ) : null}
                {p.podeFalar ? (
                  <button type="button" className="lv-bt leve" onClick={() => void fala(p, false)}>
                    Tirar fala
                  </button>
                ) : null}
                <button type="button" className="lv-nao" aria-label={`Tirar ${p.nome} da sala`} title="Tirar da sala" onClick={() => void tirar(p)}>
                  <X weight="bold" />
                </button>
              </>
            ) : null}
          </div>
        );
      })}
    </div>
  );
}

function IconeDoItem({ oferta }: { oferta: Oferta }) {
  if (oferta.imagem) return <span className="lv-ic" style={{ backgroundImage: `url("${oferta.imagem}")` }} />;
  if (oferta.tipo === "cupom")
    return (
      <span className="lv-ic cup">
        <Ticket weight="fill" />
      </span>
    );
  if (oferta.tipo === "link")
    return (
      <span className="lv-ic lnk">
        <IconeDeLink weight="bold" />
      </span>
    );
  return (
    <span className="lv-ic prd">
      <ShoppingBag weight="fill" />
    </span>
  );
}

function PainelAoVivo({ s, entrada }: { s: SalaAoVivo; entrada: Entrada }) {
  const { estado } = s;
  const [ocupado, setOcupado] = useState<string | null>(null);
  const [recado, setRecado] = useState(estado.fixado?.texto ?? "");
  const [link, setLink] = useState(estado.fixado?.link ?? "");

  const agir = async (chave: string, acao: string, dados: Record<string, unknown> = {}) => {
    setOcupado(chave);
    try {
      await s.moderar(acao, dados);
    } catch (erro) {
      s.setAviso({ texto: erro instanceof Error ? erro.message : "Não deu agora.", tom: "ruim" });
    } finally {
      setOcupado(null);
    }
  };

  if (estado.status === "encerrada" || estado.status === "cancelada") {
    return (
      <div className="lv-painel">
        <p className="lv-aviso-chat">A live terminou. Os cupons, produtos e recados ficam guardados no painel para a próxima.</p>
      </div>
    );
  }

  return (
    <div className="lv-painel">
      <PedidosParaFalar s={s} livre={entrada.sala.participacao === "livre"} />

      <section>
        <h4>Para mostrar na tela</h4>
        {entrada.itens.length ? (
          <div className="lv-itens">
            {entrada.itens.map((item) => {
              const noAr = estado.oferta?.id === item.id;
              return (
                <div className="lv-it" key={item.id}>
                  <IconeDoItem oferta={item} />
                  <div className="lv-t">
                    <b>{item.titulo}</b>
                    <span>
                      {item.tipo === "cupom" ? `Cupom ${item.codigo ?? ""}` : item.tipo === "link" ? "Link · fica fixado no bate-papo" : item.preco ? moeda(item.preco) : "Produto"}
                    </span>
                  </div>
                  <button
                    type="button"
                    className={`lv-bt${noAr ? " no-ar" : ""}`}
                    disabled={ocupado === item.id}
                    onClick={() => void agir(item.id, noAr ? "tirar_oferta" : "soltar", noAr ? {} : { item: item.id })}
                  >
                    {noAr ? (
                      <>
                        <Broadcast weight="fill" /> No ar
                      </>
                    ) : (
                      "Soltar"
                    )}
                  </button>
                </div>
              );
            })}
          </div>
        ) : (
          <p className="lv-aviso-chat" style={{ padding: "6px 0", textAlign: "left" }}>
            Nada pronto. No painel, em Lives e reuniões, abra esta transmissão e cadastre cupons, produtos e links em Para soltar.
          </p>
        )}
        {estado.oferta && !entrada.itens.some((i) => i.id === estado.oferta?.id) ? (
          <button type="button" className="lv-bt leve" style={{ marginTop: 8 }} onClick={() => void agir("tirar", "tirar_oferta")}>
            Tirar a oferta da tela
          </button>
        ) : null}
      </section>

      {entrada.vitrine.length ? (
        <section>
          <h4>Liveshop · mostrar produto</h4>
          <div className="lv-itens">
            {entrada.vitrine.map((produto) => {
              const emFoco = estado.foco?.id === produto.id;
              const id = produto.id.replace(/^p-/, "");
              return (
                <div className="lv-it" key={produto.id}>
                  <IconeDoItem oferta={produto} />
                  <div className="lv-t">
                    <b>{produto.titulo}</b>
                    <span>{produto.preco ? moeda(produto.preco) : "Ver na loja"}</span>
                  </div>
                  <button
                    type="button"
                    className={`lv-bt${emFoco ? " no-ar" : ""}`}
                    disabled={ocupado === produto.id}
                    onClick={() => void agir(produto.id, "foco", { produto: emFoco ? null : id })}
                  >
                    {emFoco ? (
                      <>
                        <Broadcast weight="fill" /> Mostrando
                      </>
                    ) : (
                      "Mostrar"
                    )}
                  </button>
                </div>
              );
            })}
          </div>
        </section>
      ) : null}

      <section>
        <h4>Recado fixado nas mensagens</h4>
        <div style={{ display: "grid", gap: 8 }}>
          <input className="lv-campo" value={recado} maxLength={240} placeholder="Ex.: A planilha está no link abaixo" onChange={(e) => setRecado(e.target.value)} />
          <input className="lv-campo" value={link} maxLength={1000} placeholder="Link (https://…) — opcional" onChange={(e) => setLink(e.target.value)} />
          <div style={{ display: "flex", gap: 8 }}>
            <button type="button" className="lv-bt" disabled={ocupado === "fixar" || !recado.trim()} onClick={() => void agir("fixar", "fixar", { texto: recado, link: link.trim() || null, rotuloDoLink: "Abrir" })}>
              <PushPin weight="fill" /> Fixar
            </button>
            {estado.fixado ? (
              <button
                type="button"
                className="lv-bt leve"
                disabled={ocupado === "fixar"}
                onClick={() => {
                  setRecado("");
                  setLink("");
                  void agir("fixar", "fixar", { texto: "" });
                }}
              >
                Tirar
              </button>
            ) : null}
          </div>
        </div>
      </section>

      {estado.maos.length ? (
        <button type="button" className="lv-bt leve" onClick={() => void agir("todas", "baixar_todas")}>
          Baixar todas as mãos
        </button>
      ) : null}
    </div>
  );
}
