"use client";

import { useEffect, useRef, useState } from "react";
import { ArrowDown, ArrowUp, FileText, FolderOpen, Link2, Loader2, Pencil, Trash2, UploadCloud, X } from "lucide-react";

import { pedirDigitais } from "@/components/digitais/comum";
import { enviarArquivo, type ProgressoDoEnvio } from "@/components/digitais/enviar-arquivo";
import { SeloDoArquivo } from "@/components/digitais/selo-do-arquivo";
import CaixaDeConfirmacao, { type Confirmacao } from "@/components/ui/caixa-de-confirmacao";
import { AreaDeTexto, FIO_DA_LINHA } from "@/components/ui/folha-de-ajustes";
import { Input } from "@/components/ui/input";

export type Entregavel = {
  id: string;
  tipo: "arquivo" | "link" | "texto" | "codigos" | "curso" | "encomenda";
  titulo: string;
  descricao: string | null;
  url: string | null;
  instrucoes: string | null;
  valePara: string | null;
  posicao: number;
  ativo: boolean;
  arquivo: { id: string; nome: string; extensao: string; categoria: string; tamanho: number; tamanhoLegivel: string; status: string } | null;
};

type ArquivoDaBiblioteca = {
  id: string;
  nome: string;
  extensao: string;
  categoria: string;
  tamanhoLegivel: string;
  status: string;
  usadoEm: string[];
};

type Formulario =
  | { tipo: "link"; id?: string; titulo: string; url: string; instrucoes: string }
  | { tipo: "texto"; id?: string; titulo: string; instrucoes: string }
  | { tipo: "arquivo"; id: string; titulo: string; descricao: string }
  /* O item do código ou da encomenda: só o nome e a descrição mudam. */
  | { tipo: "item"; id: string; titulo: string; descricao: string };

/* Os itens que são o jeito de entregar (não saem da lista por aqui). */
const DO_SISTEMA = new Set(["codigos", "encomenda", "curso"]);

function hostDoLink(url: string | null) {
  if (!url) return "";
  try {
    return new URL(url).host;
  } catch {
    return url;
  }
}

export function EntregaveisDoProduto({
  produtoId,
  entregaveis,
  podeEditar,
  aoMudar,
  aoAvisar,
}: {
  produtoId: string;
  entregaveis: Entregavel[];
  podeEditar: boolean;
  aoMudar: () => Promise<void> | void;
  aoAvisar: (tom: "bom" | "ruim", texto: string) => void;
}) {
  const [formulario, setFormulario] = useState<Formulario | null>(null);
  const [salvando, setSalvando] = useState(false);
  const [envio, setEnvio] = useState<{ nome: string; progresso: ProgressoDoEnvio | null; controle: AbortController } | null>(null);
  const [biblioteca, setBiblioteca] = useState<ArquivoDaBiblioteca[] | null>(null);
  const [abrindoBiblioteca, setAbrindoBiblioteca] = useState(false);
  const [confirmacao, setConfirmacao] = useState<Confirmacao | null>(null);
  const [ocupado, setOcupado] = useState(false);
  const escolherRef = useRef<HTMLInputElement>(null);

  /* Arquivo subindo ou sendo conferido: a lista se atualiza sozinha. */
  const algumEnviando = entregaveis.some((e) => e.arquivo && e.arquivo.status !== "pronto");
  useEffect(() => {
    if (!algumEnviando || envio) return;
    const relogio = setInterval(() => void aoMudar(), 8000);
    return () => clearInterval(relogio);
  }, [algumEnviando, envio, aoMudar]);

  const guardar = async () => {
    if (!formulario) return;
    setSalvando(true);
    try {
      if (formulario.tipo === "arquivo" || formulario.tipo === "item") {
        await pedirDigitais(`/api/digitais/produtos/${produtoId}/entregaveis/${formulario.id}`, {
          method: "PUT",
          body: JSON.stringify({ titulo: formulario.titulo, descricao: formulario.descricao }),
        });
      } else if (formulario.id) {
        await pedirDigitais(`/api/digitais/produtos/${produtoId}/entregaveis/${formulario.id}`, {
          method: "PUT",
          body: JSON.stringify(
            formulario.tipo === "link"
              ? { titulo: formulario.titulo, url: formulario.url, instrucoes: formulario.instrucoes }
              : { titulo: formulario.titulo, instrucoes: formulario.instrucoes }
          ),
        });
      } else {
        await pedirDigitais(`/api/digitais/produtos/${produtoId}/entregaveis`, {
          method: "POST",
          body: JSON.stringify(formulario),
        });
      }
      setFormulario(null);
      await aoMudar();
    } catch (e) {
      aoAvisar("ruim", e instanceof Error ? e.message : "Não foi possível guardar.");
    } finally {
      setSalvando(false);
    }
  };

  const mover = async (item: Entregavel, para: "cima" | "baixo") => {
    try {
      await pedirDigitais(`/api/digitais/produtos/${produtoId}/entregaveis/${item.id}`, { method: "PUT", body: JSON.stringify({ mover: para }) });
      await aoMudar();
    } catch (e) {
      aoAvisar("ruim", e instanceof Error ? e.message : "Não foi possível mudar a ordem.");
    }
  };

  const pedirParaTirar = (item: Entregavel) => {
    setConfirmacao({
      titulo: "Tirar este item do produto?",
      texto: "Quem já comprou continua recebendo. As compras novas não levam mais este item.",
      confirmar: "Tirar",
      cancelar: "Voltar",
      tom: "perigo",
      aoConfirmar: async () => {
        setOcupado(true);
        try {
          await pedirDigitais(`/api/digitais/produtos/${produtoId}/entregaveis/${item.id}`, { method: "DELETE" });
          await aoMudar();
        } catch (e) {
          aoAvisar("ruim", e instanceof Error ? e.message : "Não foi possível tirar.");
        } finally {
          setOcupado(false);
          setConfirmacao(null);
        }
      },
    });
  };

  const enviar = (arquivo: File) => {
    const controle = new AbortController();
    setEnvio({ nome: arquivo.name, progresso: null, controle });
    /* A ligação com o produto corre junto com o envio; o fim espera por ela
       antes de reler, para a lista mostrar o estado final de verdade. */
    let ligacao: Promise<unknown> = Promise.resolve();
    void enviarArquivo(
      arquivo,
      (progresso) => setEnvio((atual) => (atual ? { ...atual, progresso } : atual)),
      controle.signal,
      (arquivoId) => {
        /* Já entra no produto enquanto sobe: se a pessoa sair da tela, o
           arquivo continua ligado ao produto (e o produto só vai para a loja
           quando o arquivo estiver pronto). */
        ligacao = pedirDigitais(`/api/digitais/produtos/${produtoId}/entregaveis`, {
          method: "POST",
          body: JSON.stringify({ tipo: "arquivo", fileId: arquivoId }),
        })
          .then(() => aoMudar())
          .catch((e: unknown) => aoAvisar("ruim", e instanceof Error ? e.message : "Não foi possível ligar o arquivo ao produto."));
      }
    )
      .then(async () => {
        await ligacao;
        setEnvio(null);
        aoAvisar("bom", `${arquivo.name} chegou e está pronto.`);
        await aoMudar();
      })
      .catch(async (falha: unknown) => {
        await ligacao;
        setEnvio(null);
        if (!(falha instanceof DOMException && falha.name === "AbortError")) {
          aoAvisar("ruim", falha instanceof Error ? falha.message : "O envio não deu certo.");
        }
        await aoMudar();
      });
  };

  const abrirBiblioteca = async () => {
    setAbrindoBiblioteca(true);
    try {
      const resposta = await pedirDigitais<{ arquivos: ArquivoDaBiblioteca[] }>("/api/digitais/arquivos");
      const jaNoProduto = new Set(entregaveis.map((e) => e.arquivo?.id).filter(Boolean));
      setBiblioteca(resposta.arquivos.filter((a) => (a.status === "pronto" || a.status === "enviando") && !jaNoProduto.has(a.id)));
    } catch (e) {
      aoAvisar("ruim", e instanceof Error ? e.message : "Não foi possível abrir a biblioteca.");
    } finally {
      setAbrindoBiblioteca(false);
    }
  };

  const escolherDaBiblioteca = async (arquivo: ArquivoDaBiblioteca) => {
    setBiblioteca(null);
    try {
      await pedirDigitais(`/api/digitais/produtos/${produtoId}/entregaveis`, {
        method: "POST",
        body: JSON.stringify({ tipo: "arquivo", fileId: arquivo.id }),
      });
      await aoMudar();
    } catch (e) {
      aoAvisar("ruim", e instanceof Error ? e.message : "Não foi possível ligar o arquivo.");
    }
  };

  /* O item de encomenda desligado (o produto voltou a ser "na hora") some da lista. */
  const ordenados = [...entregaveis].filter((e) => e.ativo || !DO_SISTEMA.has(e.tipo)).sort((a, b) => a.posicao - b.posicao);

  return (
    <div>
      {ordenados.length === 0 && !envio ? (
        <p className="py-4 text-sm text-[var(--ks-color-text-muted)]">
          Nada ainda. Envie o arquivo, cole o link ou escreva as instruções que o comprador recebe na hora da compra.
        </p>
      ) : (
        <ul>
          {ordenados.map((item, indice) => {
            const categoria =
              item.tipo === "arquivo" ? item.arquivo?.categoria ?? "outro" : item.tipo === "link" ? "link" : item.tipo === "texto" ? "texto" : "outro";
            const selo =
              item.tipo === "arquivo"
                ? item.arquivo?.extensao || "arq"
                : item.tipo === "link"
                  ? "link"
                  : item.tipo === "codigos"
                    ? "cód"
                    : item.tipo === "encomenda"
                      ? "sob"
                      : "txt";
            const detalhe =
              item.tipo === "arquivo"
                ? item.arquivo
                  ? `${item.arquivo.nome} · ${item.arquivo.tamanhoLegivel}${item.arquivo.status !== "pronto" ? (item.arquivo.status === "recusado" ? " · recusado" : " · enviando...") : ""}`
                  : "Arquivo"
                : item.tipo === "link"
                  ? hostDoLink(item.url)
                  : item.tipo === "codigos"
                    ? "Um código diferente para cada unidade comprada (a lista fica em Códigos)"
                    : item.tipo === "encomenda"
                      ? "Você anexa o arquivo no pedido, depois da compra"
                      : (item.instrucoes ?? "").slice(0, 90);
            return (
              <li key={item.id} className={`flex items-center gap-3 py-3 ${FIO_DA_LINHA}`}>
                <SeloDoArquivo categoria={categoria} texto={selo} />
                <div className="min-w-0 flex-1">
                  <p className="truncate text-sm font-semibold text-[var(--ks-color-text-primary)]">{item.titulo}</p>
                  <p
                    className={`truncate text-xs ${
                      item.arquivo?.status === "recusado" ? "font-semibold text-[var(--ks-color-status-danger)]" : "text-[var(--ks-color-text-muted)]"
                    }`}
                  >
                    {detalhe}
                  </p>
                </div>
                {podeEditar ? (
                  <div className="flex shrink-0 items-center">
                    <button
                      type="button"
                      aria-label="Subir"
                      disabled={indice === 0}
                      onClick={() => void mover(item, "cima")}
                      className="hidden h-8 w-8 items-center justify-center rounded-full text-[var(--ks-color-text-soft)] hover:bg-[var(--ks-color-bg-hover)] disabled:opacity-30 sm:flex"
                    >
                      <ArrowUp size={15} />
                    </button>
                    <button
                      type="button"
                      aria-label="Descer"
                      disabled={indice === ordenados.length - 1}
                      onClick={() => void mover(item, "baixo")}
                      className="hidden h-8 w-8 items-center justify-center rounded-full text-[var(--ks-color-text-soft)] hover:bg-[var(--ks-color-bg-hover)] disabled:opacity-30 sm:flex"
                    >
                      <ArrowDown size={15} />
                    </button>
                    <button
                      type="button"
                      aria-label="Editar"
                      onClick={() =>
                        setFormulario(
                          item.tipo === "link"
                            ? { tipo: "link", id: item.id, titulo: item.titulo, url: item.url ?? "", instrucoes: item.instrucoes ?? "" }
                            : item.tipo === "texto"
                              ? { tipo: "texto", id: item.id, titulo: item.titulo, instrucoes: item.instrucoes ?? "" }
                              : DO_SISTEMA.has(item.tipo)
                                ? { tipo: "item", id: item.id, titulo: item.titulo, descricao: item.descricao ?? "" }
                                : { tipo: "arquivo", id: item.id, titulo: item.titulo, descricao: item.descricao ?? "" }
                        )
                      }
                      className="flex h-8 w-8 items-center justify-center rounded-full text-[var(--ks-color-text-soft)] hover:bg-[var(--ks-color-bg-hover)]"
                    >
                      <Pencil size={15} />
                    </button>
                    {DO_SISTEMA.has(item.tipo) ? (
                      <span className="h-8 w-8" aria-hidden />
                    ) : (
                      <button
                        type="button"
                        aria-label="Tirar do produto"
                        onClick={() => pedirParaTirar(item)}
                        className="flex h-8 w-8 items-center justify-center rounded-full text-[var(--ks-color-text-soft)] hover:bg-[color:rgba(214,48,76,0.08)] hover:text-[var(--ks-color-status-danger)]"
                      >
                        <Trash2 size={15} />
                      </button>
                    )}
                  </div>
                ) : null}
              </li>
            );
          })}
        </ul>
      )}

      {envio ? (
        <div className={`flex items-center gap-3 py-3 ${FIO_DA_LINHA}`}>
          <Loader2 className="h-5 w-5 shrink-0 animate-spin text-[var(--ks-brand-600)]" />
          <div className="min-w-0 flex-1">
            <p className="truncate text-sm font-semibold text-[var(--ks-color-text-primary)]">{envio.nome}</p>
            <div className="mt-1.5 h-1.5 overflow-hidden rounded-full bg-[var(--ks-color-bg-inset)]">
              <div
                className="h-full rounded-full bg-gradient-to-r from-violet-500 to-purple-600 transition-[width] duration-300"
                style={{ width: `${envio.progresso ? (envio.progresso.enviados / Math.max(1, envio.progresso.total)) * 100 : 0}%` }}
              />
            </div>
          </div>
          <span className="ks-num shrink-0 text-xs font-bold text-[var(--ks-brand-600)]">
            {envio.progresso?.fase === "conferindo"
              ? "conferindo..."
              : `${Math.floor(envio.progresso ? (envio.progresso.enviados / Math.max(1, envio.progresso.total)) * 100 : 0)}%`}
          </span>
          <button
            type="button"
            aria-label="Cancelar envio"
            onClick={() => envio.controle.abort()}
            className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-[var(--ks-color-text-soft)] hover:bg-[var(--ks-color-bg-hover)]"
          >
            <X size={16} />
          </button>
        </div>
      ) : null}

      {formulario ? (
        <div className="my-3 space-y-3 rounded-2xl bg-[var(--ks-color-bg-subtle)] p-4">
          <p className="text-sm font-bold text-[var(--ks-color-text-primary)]">
            {formulario.tipo === "link" ? "Link de acesso" : formulario.tipo === "texto" ? "Texto com instruções" : formulario.tipo === "item" ? "Item" : "Arquivo"}
          </p>
          <Input
            label="Nome do item"
            value={formulario.titulo}
            maxLength={160}
            placeholder={formulario.tipo === "link" ? "Ex.: Grupo VIP no WhatsApp" : formulario.tipo === "texto" ? "Ex.: Como usar o modelo" : ""}
            onChange={(e) => setFormulario({ ...formulario, titulo: e.target.value })}
          />
          {formulario.tipo === "link" ? (
            <>
              <Input
                label="Link (só quem comprou recebe)"
                value={formulario.url}
                placeholder="https://"
                onChange={(e) => setFormulario({ ...formulario, url: e.target.value })}
              />
              <div>
                <label className="ks-input-label">Instruções (opcional)</label>
                <AreaDeTexto
                  value={formulario.instrucoes}
                  maxLength={4000}
                  rows={3}
                  placeholder="Ex.: Entre com o mesmo e-mail da compra."
                  onChange={(e) => setFormulario({ ...formulario, instrucoes: e.target.value })}
                />
              </div>
            </>
          ) : formulario.tipo === "texto" ? (
            <div>
              <label className="ks-input-label">Texto que o comprador recebe</label>
              <AreaDeTexto
                value={formulario.instrucoes}
                maxLength={4000}
                rows={5}
                onChange={(e) => setFormulario({ ...formulario, instrucoes: e.target.value })}
              />
            </div>
          ) : (
            <Input
              label="Descrição (opcional)"
              value={formulario.descricao}
              maxLength={300}
              placeholder={formulario.tipo === "item" ? "Ex.: Ativa em até 3 computadores" : "Ex.: 12 páginas em A4, prontas para imprimir"}
              onChange={(e) => setFormulario({ ...formulario, descricao: e.target.value })}
            />
          )}
          <div className="flex justify-end gap-2">
            <button type="button" className="ks-button ks-button-soft" onClick={() => setFormulario(null)} disabled={salvando}>
              Cancelar
            </button>
            <button type="button" className="ks-button ks-button-primary" onClick={() => void guardar()} disabled={salvando}>
              {salvando ? <Loader2 size={16} className="animate-spin" /> : null}
              Guardar
            </button>
          </div>
        </div>
      ) : null}

      {biblioteca ? (
        <div className="my-3 rounded-2xl bg-[var(--ks-color-bg-subtle)] p-4">
          <div className="flex items-center justify-between gap-3">
            <p className="text-sm font-bold text-[var(--ks-color-text-primary)]">Escolha um arquivo da biblioteca</p>
            <button type="button" aria-label="Fechar" onClick={() => setBiblioteca(null)} className="flex h-8 w-8 items-center justify-center rounded-full hover:bg-white">
              <X size={16} />
            </button>
          </div>
          {biblioteca.length === 0 ? (
            <p className="mt-2 text-sm text-[var(--ks-color-text-muted)]">Nenhum arquivo disponível. Envie um novo.</p>
          ) : (
            <ul className="mt-2 max-h-72 overflow-y-auto">
              {biblioteca.map((arquivo) => (
                <li key={arquivo.id} className={FIO_DA_LINHA}>
                  <button
                    type="button"
                    onClick={() => void escolherDaBiblioteca(arquivo)}
                    className="flex w-full items-center gap-3 rounded-xl px-2 py-2.5 text-left hover:bg-white"
                  >
                    <SeloDoArquivo categoria={arquivo.categoria} texto={arquivo.extensao || "arq"} tamanho={34} />
                    <span className="min-w-0 flex-1">
                      <span className="block truncate text-sm font-semibold text-[var(--ks-color-text-primary)]">{arquivo.nome}</span>
                      <span className="block truncate text-xs text-[var(--ks-color-text-muted)]">
                        {arquivo.tamanhoLegivel}
                        {arquivo.usadoEm.length ? ` · também em ${arquivo.usadoEm.join(", ")}` : ""}
                      </span>
                    </span>
                  </button>
                </li>
              ))}
            </ul>
          )}
        </div>
      ) : null}

      {podeEditar && !formulario ? (
        <div className="flex flex-wrap gap-2 py-3">
          <button type="button" className="ks-button ks-button-soft ks-button-sm" disabled={Boolean(envio)} onClick={() => escolherRef.current?.click()}>
            <UploadCloud size={15} />
            Enviar arquivo
          </button>
          <button type="button" className="ks-button ks-button-soft ks-button-sm" disabled={abrindoBiblioteca} onClick={() => void abrirBiblioteca()}>
            {abrindoBiblioteca ? <Loader2 size={15} className="animate-spin" /> : <FolderOpen size={15} />}
            Da biblioteca
          </button>
          <button type="button" className="ks-button ks-button-soft ks-button-sm" onClick={() => setFormulario({ tipo: "link", titulo: "", url: "", instrucoes: "" })}>
            <Link2 size={15} />
            Link de acesso
          </button>
          <button type="button" className="ks-button ks-button-soft ks-button-sm" onClick={() => setFormulario({ tipo: "texto", titulo: "", instrucoes: "" })}>
            <FileText size={15} />
            Texto com instruções
          </button>
          <input
            ref={escolherRef}
            type="file"
            className="hidden"
            onChange={(evento) => {
              const arquivo = evento.target.files?.[0];
              evento.target.value = "";
              if (arquivo) enviar(arquivo);
            }}
          />
        </div>
      ) : null}

      <CaixaDeConfirmacao pedido={confirmacao} ocupado={ocupado} aoFechar={() => (ocupado ? undefined : setConfirmacao(null))} />
    </div>
  );
}
