"use client";

import { toast } from "sonner";
import { AlertTriangle, CheckCircle2, Info, RotateCcw, X, XCircle } from "lucide-react";

/**
 * Avisos da agenda.
 *
 * O `toast.success` do sonner entrega uma tarja colorida com uma linha de
 * texto. Serve para "salvo", mas nao para o que esta agenda precisa dizer:
 * quase todo aviso aqui tem um titulo curto e uma explicacao, e alguns pedem
 * uma acao imediata — desfazer um compromisso apagado sem ter de reabrir o
 * formulario.
 *
 * Por isso o cartao e desenhado aqui, e nao configurado por cima do padrao:
 * titulo e descricao em hierarquia, icone em circulo com a cor do tipo, e a
 * barra na base como unico elemento cheio de cor. A barra tambem e o relogio
 * — encolhe ate o fim do tempo, entao a pessoa ve quanto falta em vez de o
 * aviso sumir de surpresa no meio da leitura.
 */

type Tipo = "info" | "sucesso" | "erro" | "alerta" | "desfazer";

const ESTILO: Record<Tipo, { cor: string; anel: string; Icone: typeof Info }> = {
  info: { cor: "#3B82F6", anel: "rgba(59,130,246,0.14)", Icone: Info },
  sucesso: { cor: "#10B981", anel: "rgba(16,185,129,0.14)", Icone: CheckCircle2 },
  erro: { cor: "#F43F5E", anel: "rgba(244,63,94,0.14)", Icone: XCircle },
  alerta: { cor: "#F59E0B", anel: "rgba(245,158,11,0.14)", Icone: AlertTriangle },
  desfazer: { cor: "#8B5CF6", anel: "rgba(139,92,246,0.14)", Icone: RotateCcw },
};

type Opcoes = {
  descricao?: string;
  duracao?: number;
  acao?: { rotulo: string; aoClicar: () => void };
};

function mostrar(tipo: Tipo, titulo: string, opcoes: Opcoes = {}) {
  const duracao = opcoes.duracao ?? (opcoes.acao ? 8000 : tipo === "erro" ? 6000 : 4000);

  return toast.custom(
    (id) => <Cartao id={id} tipo={tipo} titulo={titulo} duracao={duracao} {...opcoes} />,
    { duration: duracao }
  );
}

function Cartao({
  id,
  tipo,
  titulo,
  descricao,
  acao,
  duracao,
}: Opcoes & { id: string | number; tipo: Tipo; titulo: string; duracao: number }) {
  const { cor, anel, Icone } = ESTILO[tipo];

  return (
    <div
      className="relative flex w-full items-start gap-3 overflow-hidden rounded-[10px] border border-[var(--ag-border)] bg-[var(--ag-surface)] py-3 pl-3.5 pr-2.5 shadow-[0_10px_28px_rgba(16,24,40,0.14)] sm:w-[380px]"
      role={tipo === "erro" ? "alert" : "status"}
    >
      <span
        aria-hidden
        className="mt-[1px] flex h-7 w-7 shrink-0 items-center justify-center rounded-full"
        style={{ background: anel }}
      >
        <Icone className="h-[15px] w-[15px]" style={{ color: cor }} />
      </span>

      <div className="min-w-0 flex-1">
        <p className="text-[13px] font-semibold leading-tight text-[var(--ag-text)]">{titulo}</p>
        {descricao && (
          <p className="mt-[3px] text-[12px] leading-snug text-[var(--ag-text-3)]">{descricao}</p>
        )}
      </div>

      {acao && (
        <button
          type="button"
          onClick={() => {
            acao.aoClicar();
            toast.dismiss(id);
          }}
          className="mt-[1px] shrink-0 rounded-[7px] border px-2.5 py-1 text-[11.5px] font-semibold transition-colors"
          style={{ borderColor: cor, color: cor }}
        >
          {acao.rotulo}
        </button>
      )}

      <button
        type="button"
        onClick={() => toast.dismiss(id)}
        aria-label="Fechar aviso"
        className="mt-[1px] flex h-6 w-6 shrink-0 items-center justify-center rounded-[6px] text-[var(--ag-text-5)] transition-colors hover:bg-[var(--ag-surface-2)] hover:text-[var(--ag-text-2)]"
      >
        <X className="h-3.5 w-3.5" />
      </button>

      {/* Barra do tempo restante. `scaleX` em vez de `width` para a animacao
          rodar no compositor — largura anima no layout e engasga quando ha
          varios avisos na tela. */}
      <span
        aria-hidden
        className="absolute inset-x-0 bottom-0 h-[3px] origin-left"
        style={{ background: cor, animation: `ks-aviso-tempo ${duracao}ms linear forwards` }}
      />
    </div>
  );
}

/** Uma peça por tipo, para a chamada ficar curta em quem usa. */
export const aviso = {
  info: (titulo: string, o?: Opcoes) => mostrar("info", titulo, o),
  sucesso: (titulo: string, o?: Opcoes) => mostrar("sucesso", titulo, o),
  erro: (titulo: string, o?: Opcoes) => mostrar("erro", titulo, o),
  alerta: (titulo: string, o?: Opcoes) => mostrar("alerta", titulo, o),
  desfazer: (titulo: string, o?: Opcoes) => mostrar("desfazer", titulo, o),
};
