"use client";

import Image from "next/image";
import { useCallback, useEffect, useRef, useState } from "react";
import { ArrowLeft, ExternalLink, MessageCircle, Send, User, X } from "lucide-react";
import { getSupabaseClient } from "@/lib/supabase";

/*
  O Chats sem sair da tela.

  O módulo mora numa aba separada, e isso resolve o dia de quem senta para
  atender. Mas quem está dentro de um pedido não vê a conversa chegar: o sino
  avisa, o clique joga para outra aba e o lugar se perde. Na prática, deixa-se
  para depois — e "depois" é o cliente perguntando no WhatsApp.

  Aqui é o essencial e nada mais: quem está esperando, o fio da conversa e o
  campo de responder. Anexo, arte, produto, cupom e o resto continuam no módulo,
  a um clique de distância. A régua foi essa: cabe o que se faz de pé, entre uma
  tela e outra.
*/

type Conversa = {
  id: string;
  kind: string;
  nome: string;
  detalhe: string;
  avatar: string | null;
  ultimaMensagem: string | null;
  ultimaMensagemEm: string | null;
  ultimoAutor: string | null;
  naoLidas: number;
};

type Mensagem = {
  id: string;
  author_type: string;
  sender_name: string | null;
  body: string | null;
  attachment_kind: string | null;
  internal?: boolean;
  created_at: string;
};

function iniciais(nome?: string | null) {
  const partes = String(nome || "").trim().split(/\s+/).filter(Boolean);
  if (!partes.length) return "?";
  if (partes.length === 1) return partes[0].slice(0, 2).toUpperCase();
  return (partes[0][0] + partes[partes.length - 1][0]).toUpperCase();
}

function hora(iso: string) {
  return new Date(iso).toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" });
}

/* Há quanto tempo a pessoa espera. "há 40 min" cobra; "18:42" não. */
function espera(iso?: string | null) {
  if (!iso) return "";
  const minutos = Math.floor((Date.now() - new Date(iso).getTime()) / 60000);
  if (Number.isNaN(minutos) || minutos < 1) return "agora";
  if (minutos < 60) return `há ${minutos} min`;
  const horas = Math.floor(minutos / 60);
  if (horas < 24) return `há ${horas}h`;
  return `há ${Math.floor(horas / 24)} d`;
}

export default function PainelDoChats({
  aberto,
  aoFechar,
  aoMudarPendentes,
}: {
  aberto: boolean;
  aoFechar: () => void;
  /* O contador do botão vive aqui dentro, mas quem o mostra é a barra. */
  aoMudarPendentes: (quantas: number) => void;
}) {
  const [conversas, setConversas] = useState<Conversa[]>([]);
  const [abertaId, setAbertaId] = useState<string | null>(null);
  const [cabecalho, setCabecalho] = useState<{ contato: string; detalhe: string; podeResponder: boolean } | null>(null);
  const [mensagens, setMensagens] = useState<Mensagem[]>([]);
  const [texto, setTexto] = useState("");
  const [enviando, setEnviando] = useState(false);
  const [erro, setErro] = useState<string | null>(null);
  const [lojaIds, setLojaIds] = useState<string[]>([]);

  const fim = useRef<HTMLDivElement | null>(null);
  const abertaRef = useRef<string | null>(null);
  abertaRef.current = abertaId;

  const carregarLista = useCallback(async () => {
    try {
      const resposta = await fetch("/api/chats/threads?aba=loja&situacao=esperando", { cache: "no-store" });
      const dados = (await resposta.json().catch(() => null)) as
        | { conversas?: Conversa[]; esperando?: number; lojaIds?: string[] }
        | null;
      setConversas(Array.isArray(dados?.conversas) ? dados.conversas : []);
      if (Array.isArray(dados?.lojaIds)) setLojaIds(dados.lojaIds);
      aoMudarPendentes(Number(dados?.esperando || 0));
    } catch {
      /* Fica o que já estava: sumir com a lista por uma consulta que falhou é
         pior do que mostrar algo de um minuto atrás. */
    }
  }, [aoMudarPendentes]);

  /*
    O contador roda mesmo com o painel fechado — é ele que avisa que tem gente
    esperando. Devagar, porque não é o painel principal: de dois em dois
    minutos fechado, de vinte em vinte segundos aberto.
  */
  useEffect(() => {
    void carregarLista();
    const relogio = window.setInterval(() => void carregarLista(), aberto ? 20000 : 120000);
    return () => window.clearInterval(relogio);
  }, [carregarLista, aberto]);

  /* Mensagem nova em qualquer conversa da loja: a lista se corrige na hora. */
  useEffect(() => {
    if (!lojaIds.length) return;
    const supabase = getSupabaseClient();
    const canais = lojaIds.map((id) => {
      const canal = supabase.channel(`chat-loja-${id}`);
      canal.on("broadcast", { event: "novidade" }, () => {
        void carregarLista();
        if (abertaRef.current) void carregarFio(abertaRef.current);
      });
      canal.subscribe();
      return canal;
    });
    return () => {
      canais.forEach((canal) => void supabase.removeChannel(canal));
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [lojaIds, carregarLista]);

  const carregarFio = useCallback(async (threadId: string) => {
    try {
      const resposta = await fetch(`/api/chats/threads/${threadId}/mensagens`, { cache: "no-store" });
      const dados = (await resposta.json().catch(() => null)) as
        | { conversa?: { contato: string; detalhe: string; podeResponder: boolean }; mensagens?: Mensagem[] }
        | null;
      if (abertaRef.current !== threadId) return;
      setMensagens(Array.isArray(dados?.mensagens) ? dados.mensagens : []);
      if (dados?.conversa) setCabecalho(dados.conversa);
      window.setTimeout(() => fim.current?.scrollIntoView({ block: "end" }), 40);
    } catch {
      setErro("Não consegui abrir a conversa.");
    }
  }, []);

  function abrir(threadId: string) {
    setErro(null);
    setTexto("");
    setMensagens([]);
    setCabecalho(null);
    abertaRef.current = threadId;
    setAbertaId(threadId);
    void carregarFio(threadId);
  }

  async function enviar() {
    const corpo = texto.trim();
    if (!abertaId || !corpo || enviando) return;

    setEnviando(true);
    setErro(null);
    setTexto("");
    try {
      const dados = new FormData();
      dados.set("body", corpo);
      const resposta = await fetch(`/api/chats/threads/${abertaId}/mensagens`, { method: "POST", body: dados });
      if (!resposta.ok) {
        throw new Error((await resposta.json().catch(() => null))?.error || "Não foi possível enviar.");
      }
      await carregarFio(abertaId);
      void carregarLista();
    } catch (falha) {
      setTexto(corpo);
      setErro(falha instanceof Error ? falha.message : "Não foi possível enviar.");
    } finally {
      setEnviando(false);
    }
  }

  if (!aberto) return null;

  return (
    <>
      {/* A cortina existe para fechar clicando fora — e para dizer que o resto
          da tela está esperando. */}
      <div className="fixed inset-0 z-[75] bg-black/20" onClick={aoFechar} aria-hidden="true" />

      <aside className="ks-chat-painel">
        <header className="ks-chat-painel-topo">
          {abertaId ? (
            <button
              type="button"
              className="ks-icon-button"
              onClick={() => {
                setAbertaId(null);
                abertaRef.current = null;
              }}
              aria-label="Voltar"
            >
              <ArrowLeft size={16} />
            </button>
          ) : null}

          <div className="min-w-0 flex-1">
            <p className="truncate text-[13.5px] font-semibold text-[var(--ks-color-text-primary)]">
              {abertaId ? cabecalho?.contato || "Conversa" : "Esperando você"}
            </p>
            <p className="truncate text-[11.5px] text-[var(--ks-color-text-soft)]">
              {abertaId
                ? cabecalho?.detalhe || ""
                : conversas.length
                  ? `${conversas.length} ${conversas.length === 1 ? "conversa sem resposta" : "conversas sem resposta"}`
                  : "Ninguém esperando agora"}
            </p>
          </div>

          <a
            href={abertaId ? `/chats?conversa=${abertaId}` : "/chats"}
            target="_blank"
            rel="noreferrer"
            className="ks-icon-button"
            title="Abrir no Chats"
          >
            <ExternalLink size={15} />
          </a>
          <button type="button" className="ks-icon-button" onClick={aoFechar} aria-label="Fechar">
            <X size={16} />
          </button>
        </header>

        {!abertaId ? (
          <div className="ks-chat-painel-lista">
            {conversas.length === 0 ? (
              <p className="ks-chat-painel-vazio">
                Nenhuma conversa esperando resposta. Quando alguém escrever, aparece aqui.
              </p>
            ) : (
              conversas.map((conversa) => (
                <button key={conversa.id} type="button" className="ks-chat-painel-item" onClick={() => abrir(conversa.id)}>
                  <span className="ks-chat-painel-avatar">
                    {conversa.avatar ? (
                      <Image src={conversa.avatar} alt={conversa.nome} width={34} height={34} unoptimized />
                    ) : conversa.kind === "visitor" ? (
                      <User size={16} />
                    ) : (
                      iniciais(conversa.nome)
                    )}
                  </span>
                  <span className="min-w-0 flex-1">
                    <span className="flex items-baseline justify-between gap-2">
                      <span className="truncate text-[13px] font-semibold text-[var(--ks-color-text-primary)]">
                        {conversa.nome}
                      </span>
                      <span className="shrink-0 text-[11px] font-bold text-rose-600">
                        {espera(conversa.ultimaMensagemEm)}
                      </span>
                    </span>
                    <span className="mt-0.5 block truncate text-[12px] text-[var(--ks-color-text-soft)]">
                      {conversa.ultimaMensagem || conversa.detalhe}
                    </span>
                  </span>
                </button>
              ))
            )}
          </div>
        ) : (
          <>
            <div className="ks-chat-painel-fio">
              {mensagens.length === 0 ? (
                <p className="ks-chat-painel-vazio">Abrindo a conversa...</p>
              ) : (
                mensagens.map((mensagem) => {
                  const minha = mensagem.author_type !== "client";
                  return (
                    <div key={mensagem.id} className={`ks-chat-balao ${minha ? "ks-chat-balao-meu" : ""}`}>
                      {mensagem.internal ? <span className="ks-chat-interno">Só a equipe vê</span> : null}
                      <p>
                        {mensagem.body ||
                          (mensagem.attachment_kind === "image"
                            ? "Imagem"
                            : mensagem.attachment_kind
                              ? "Arquivo"
                              : "")}
                      </p>
                      <span>{hora(mensagem.created_at)}</span>
                    </div>
                  );
                })
              )}
              <div ref={fim} />
            </div>

            {cabecalho && !cabecalho.podeResponder ? (
              <p className="ks-chat-painel-vazio">Você pode ler, mas não tem permissão para responder.</p>
            ) : (
              <div className="ks-chat-painel-escrever">
                {erro ? <p className="text-[11.5px] font-semibold text-rose-600">{erro}</p> : null}
                <div className="flex items-end gap-2">
                  <textarea
                    value={texto}
                    onChange={(evento) => setTexto(evento.target.value)}
                    onKeyDown={(evento) => {
                      if (evento.key === "Enter" && !evento.shiftKey) {
                        evento.preventDefault();
                        void enviar();
                      }
                    }}
                    rows={1}
                    placeholder="Responder"
                  />
                  <button
                    type="button"
                    onClick={() => void enviar()}
                    disabled={enviando || !texto.trim()}
                    aria-label="Enviar"
                  >
                    <Send size={15} />
                  </button>
                </div>
                <p className="ks-chat-painel-dica">
                  <MessageCircle size={11} />
                  Produto, cupom, anexo e as ações rápidas ficam no Chats.
                </p>
              </div>
            )}
          </>
        )}
      </aside>
    </>
  );
}
