"use client";

import { useCallback, useEffect, useState } from "react";
import Link from "next/link";
import { ChevronDown, ImageOff, Loader2, PackagePlus, Store, Trash2 } from "lucide-react";

import { CabecalhoDoPainel, Painel } from "@/components/assinatura/primitivos";
import { Aviso } from "@/components/ui/aviso";
import { Button } from "@/components/ui/button";
import CaixaDeConfirmacao, { type Confirmacao } from "@/components/ui/caixa-de-confirmacao";
import type { ImportacaoNaLista } from "@/lib/assistentes/importacao/servidor";

/**
 * As importações de produtos feitas pelos assistentes (a loja antiga trazida
 * para a Ktalogu), na aba Assistentes e Apps.
 *
 * Cada lote numa linha: quantos produtos, de onde, e o andamento das fotos,
 * que se atualiza sozinho enquanto elas chegam. Os produtos entram fora da
 * loja virtual; daqui a pessoa publica o lote inteiro ou apaga o lote (pela
 * exclusão de produtos do painel, que não apaga produto já usado em orçamento
 * ou pedido). Só aparece quando há o que mostrar.
 */

type Resposta = { importacoes: ImportacaoNaLista[]; podePublicar: boolean; podeApagar: boolean };

const reais = (valor: number) => valor.toLocaleString("pt-BR", { style: "currency", currency: "BRL" });

function quandoFoi(iso: string, agora: number) {
  const minutos = Math.round((agora - new Date(iso).getTime()) / 60_000);
  if (minutos < 1) return "agora";
  if (minutos < 60) return `há ${minutos} min`;
  const horas = Math.round(minutos / 60);
  if (horas < 24) return `há ${horas} h`;
  return new Date(iso).toLocaleDateString("pt-BR", { day: "2-digit", month: "2-digit" });
}

function textoDasFotos(fotos: ImportacaoNaLista["fotos"]) {
  const total = fotos.prontas + fotos.naFila + fotos.falharam;
  if (!total) return "Sem fotos";
  if (fotos.naFila) return `Fotos chegando: ${fotos.prontas} de ${total}`;
  if (fotos.falharam) return `${fotos.prontas} ${fotos.prontas === 1 ? "foto pronta" : "fotos prontas"} · ${fotos.falharam} não ${fotos.falharam === 1 ? "veio" : "vieram"}`;
  return `${fotos.prontas} ${fotos.prontas === 1 ? "foto pronta" : "fotos prontas"}`;
}

export default function ImportacoesDosAssistentes({ atraso }: { atraso?: number }) {
  const [dados, setDados] = useState<Resposta | null>(null);
  const [aberta, setAberta] = useState<string | null>(null);
  const [ocupada, setOcupada] = useState<string | null>(null);
  const [pedido, setPedido] = useState<Confirmacao | null>(null);
  const [aviso, setAviso] = useState<{ tom: "bom" | "ruim" | "atencao"; texto: string } | null>(null);
  const [agora, setAgora] = useState(() => Date.now());

  const carregar = useCallback(async () => {
    try {
      const resposta = await fetch("/api/assistentes/importacoes", { cache: "no-store" });
      const json = (await resposta.json().catch(() => null)) as Resposta | null;
      if (resposta.ok && json && Array.isArray(json.importacoes)) setDados(json);
      setAgora(Date.now());
    } catch {
      /* Fica o que já estava na tela. */
    }
  }, []);

  /* Enquanto há fotos chegando, a lista se atualiza sozinha (com a aba à vista). */
  const chegando = Boolean(dados?.importacoes.some((importacao) => importacao.fotos.naFila > 0));
  useEffect(() => {
    void carregar();
  }, [carregar]);
  useEffect(() => {
    if (!chegando) return;
    const relogio = window.setInterval(() => {
      if (document.visibilityState === "visible") void carregar();
    }, 8000);
    return () => window.clearInterval(relogio);
  }, [chegando, carregar]);

  const publicar = async (importacao: ImportacaoNaLista) => {
    setOcupada(importacao.id);
    setAviso(null);
    try {
      const resposta = await fetch(`/api/assistentes/importacoes/${importacao.id}`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ acao: "publicar" }),
      });
      const json = (await resposta.json().catch(() => null)) as { publicados?: number; error?: unknown } | null;
      if (!resposta.ok) throw new Error(typeof json?.error === "string" ? json.error : "Não foi possível publicar.");
      const quantos = json?.publicados ?? 0;
      setAviso({ tom: "bom", texto: quantos ? `${quantos} ${quantos === 1 ? "produto publicado" : "produtos publicados"} na loja virtual.` : "Os produtos deste lote já estavam na loja." });
      /* A tela muda na hora; a lista confirmada chega logo depois. */
      setDados((atual) =>
        atual
          ? {
              ...atual,
              importacoes: atual.importacoes.map((lote) =>
                lote.id === importacao.id ? { ...lote, produtos: lote.produtos.map((produto) => ({ ...produto, naLoja: true })) } : lote
              ),
            }
          : atual
      );
      await carregar();
    } catch (falha) {
      setAviso({ tom: "ruim", texto: falha instanceof Error ? falha.message : "Não foi possível publicar." });
    } finally {
      setOcupada(null);
      setPedido(null);
    }
  };

  const apagar = async (importacao: ImportacaoNaLista) => {
    setOcupada(importacao.id);
    setAviso(null);
    try {
      const resposta = await fetch("/api/products/bulk-delete", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ productIds: importacao.produtos.map((produto) => produto.id) }),
      });
      const json = (await resposta.json().catch(() => null)) as {
        deletedCount?: number;
        results?: Array<{ productId?: string; success?: boolean }>;
        linkedProducts?: Array<{ name?: string }>;
        error?: unknown;
      } | null;
      if (!resposta.ok) throw new Error(typeof json?.error === "string" ? json.error : "Não foi possível apagar.");
      const apagados = json?.deletedCount ?? 0;
      const presos = (json?.linkedProducts ?? []).map((produto) => produto.name).filter(Boolean);
      setAviso({
        tom: presos.length ? "atencao" : "bom",
        texto: `${apagados} ${apagados === 1 ? "produto apagado" : "produtos apagados"}.${presos.length ? ` ${presos.length} ${presos.length === 1 ? "ficou porque já está" : "ficaram porque já estão"} em orçamentos ou pedidos: ${presos.slice(0, 3).join(", ")}${presos.length > 3 ? "…" : ""}.` : ""}`,
      });
      /* O que saiu some da tela na hora; o lote que ficou sem produto, junto. */
      const saiu = new Set((json?.results ?? []).filter((linha) => linha.success && linha.productId).map((linha) => String(linha.productId)));
      setDados((atual) =>
        atual
          ? {
              ...atual,
              importacoes: atual.importacoes
                .map((lote) => (lote.id === importacao.id ? { ...lote, produtos: lote.produtos.filter((produto) => !saiu.has(produto.id)) } : lote))
                .filter((lote) => lote.produtos.length > 0),
            }
          : atual
      );
      await carregar();
    } catch (falha) {
      setAviso({ tom: "ruim", texto: falha instanceof Error ? falha.message : "Não foi possível apagar." });
    } finally {
      setOcupada(null);
      setPedido(null);
    }
  };

  /* Sem lote nenhum a seção some, a não ser que haja um aviso a dar ("3 produtos apagados"). */
  if (!dados || (!dados.importacoes.length && !aviso)) return null;

  return (
    <Painel atraso={atraso}>
      <CabecalhoDoPainel titulo="Importações" texto="Produtos que os assistentes trouxeram de outra loja. Eles entram fora da loja virtual: revise e publique." />
      {aviso ? (
        <div className="border-b border-[var(--ks-color-border-subtle)] px-5 py-3 sm:px-6">
          <Aviso tom={aviso.tom} aoFechar={() => setAviso(null)}>
            {aviso.texto}
          </Aviso>
        </div>
      ) : null}
      <div className="-mt-px">
        {dados.importacoes.map((importacao) => {
          const fora = importacao.produtos.filter((produto) => !produto.naLoja).length;
          const naLoja = importacao.produtos.length - fora;
          const estaAberta = aberta === importacao.id;
          const total = importacao.produtos.length;
          return (
            <div key={importacao.id} className="border-t border-slate-100/60">
              <div className="flex flex-wrap items-center gap-x-3 gap-y-2 px-5 py-3 transition-colors hover:bg-[var(--ks-color-bg-inset)] sm:flex-nowrap sm:px-6">
                <span className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-[var(--ks-color-bg-soft)] text-[var(--ks-color-primary)]">
                  <PackagePlus size={15} strokeWidth={2.3} />
                </span>
                <div className="min-w-0 flex-1">
                  <p className="truncate text-sm font-semibold text-[var(--ks-color-text-primary)]">
                    {total} {total === 1 ? "produto" : "produtos"} {importacao.origem ? `de ${importacao.origem}` : "montados pelo assistente"}
                  </p>
                  <p className="flex items-center gap-1.5 truncate text-[11px] text-slate-400">
                    {importacao.fotos.naFila ? <Loader2 size={11} className="shrink-0 animate-spin text-[var(--ks-color-primary)]" /> : null}
                    <span className="truncate">
                      {textoDasFotos(importacao.fotos)}
                      {total ? ` · ${naLoja ? `${naLoja} na loja` : "fora da loja"}` : ""}
                    </span>
                  </p>
                </div>
                <div className="hidden shrink-0 text-right md:block">
                  <p className="ks-num text-xs font-semibold text-[var(--ks-color-text-secondary)]" title={new Date(importacao.quando).toLocaleString("pt-BR")}>
                    {quandoFoi(importacao.quando, agora)}
                  </p>
                  <p className="max-w-[160px] truncate text-[11px] text-slate-400">{[importacao.por, importacao.plataforma].filter(Boolean).join(" · ")}</p>
                </div>
                <div className="flex w-full shrink-0 items-center justify-end gap-1 sm:w-auto">
                  {total ? (
                    <Button
                      variant="ghost"
                      size="sm"
                      onClick={() => setAberta(estaAberta ? null : importacao.id)}
                      aria-expanded={estaAberta}
                      iconRight={<ChevronDown size={14} className={`transition-transform ${estaAberta ? "rotate-180" : ""}`} />}
                    >
                      Ver
                    </Button>
                  ) : null}
                  {dados.podePublicar && fora > 0 ? (
                    <Button
                      variant="ghost"
                      size="sm"
                      disabled={ocupada !== null}
                      icon={ocupada === importacao.id ? <Loader2 size={14} className="animate-spin" /> : <Store size={14} />}
                      onClick={() =>
                        setPedido({
                          titulo: `Publicar ${fora} ${fora === 1 ? "produto" : "produtos"} na loja virtual?`,
                          texto: "Eles passam a aparecer na loja para os clientes. Dá para tirar da loja depois, produto por produto, no painel de produtos.",
                          confirmar: "Publicar",
                          aoConfirmar: () => publicar(importacao),
                        })
                      }
                    >
                      Publicar
                    </Button>
                  ) : null}
                  {dados.podeApagar && total > 0 ? (
                    <Button
                      variant="ghost"
                      size="sm"
                      disabled={ocupada !== null}
                      icon={<Trash2 size={14} />}
                      aria-label="Apagar lote"
                      title="Apagar os produtos deste lote"
                      onClick={() =>
                        setPedido({
                          titulo: `Apagar ${total === 1 ? "o produto" : `os ${total} produtos`} deste lote?`,
                          texto: "Os produtos e as fotos saem da Ktalogu, e não dá para desfazer. Produto que já está em algum orçamento ou pedido fica, para não quebrar o histórico.",
                          confirmar: "Apagar lote",
                          tom: "perigo",
                          aoConfirmar: () => apagar(importacao),
                        })
                      }
                    />
                  ) : null}
                </div>
              </div>
              {estaAberta ? (
                <ul className="border-t border-slate-100/60 bg-[var(--ks-color-bg-inset)] py-1">
                  {importacao.produtos.map((produto) => (
                    <li key={produto.id} className="flex items-center gap-3 px-5 py-1.5 sm:px-6 sm:pl-[68px]">
                      <span className="flex h-8 w-8 shrink-0 items-center justify-center overflow-hidden rounded-md bg-[var(--ks-color-bg-soft)] text-slate-300">
                        {produto.foto ? (
                          // eslint-disable-next-line @next/next/no-img-element
                          <img src={produto.foto} alt="" className="h-full w-full object-cover" loading="lazy" />
                        ) : (
                          <ImageOff size={13} />
                        )}
                      </span>
                      <Link href={`/dashboard/products/${produto.id}`} className="min-w-0 flex-1 truncate text-sm font-medium text-[var(--ks-color-text-primary)] hover:text-[var(--ks-color-primary)] hover:underline">
                        {produto.nome}
                      </Link>
                      <span className="ks-num hidden shrink-0 text-xs text-[var(--ks-color-text-secondary)] sm:inline">{produto.sobConsulta ? "Sob consulta" : reais(produto.preco)}</span>
                      <span className={`w-[76px] shrink-0 text-right text-[11px] font-semibold ${produto.naLoja ? "text-emerald-600" : "text-slate-400"}`}>
                        {produto.naLoja ? "Na loja" : "Fora da loja"}
                      </span>
                    </li>
                  ))}
                </ul>
              ) : null}
            </div>
          );
        })}
      </div>
      <CaixaDeConfirmacao pedido={pedido} ocupado={ocupada !== null} aoFechar={() => setPedido(null)} />
    </Painel>
  );
}
