"use client";

import type { Pendencia } from "@/lib/fiscal/montar";
import type { TomDoStatus } from "@/lib/fiscal/status";

/* ------------------------------------------------------------------ */
/* Chamada à API fiscal                                                */
/* ------------------------------------------------------------------ */

export class ErroDaTela extends Error {
  status: number;
  pendencias: Pendencia[];
  constructor(mensagem: string, status: number, pendencias: Pendencia[] = []) {
    super(mensagem);
    this.name = "ErroDaTela";
    this.status = status;
    this.pendencias = pendencias;
  }
}

export async function pedirFiscal<T>(url: string, init?: RequestInit & { json?: unknown }): Promise<T> {
  const { json, ...resto } = init ?? {};
  const resposta = await fetch(url, {
    ...resto,
    headers: json !== undefined ? { "Content-Type": "application/json", ...(resto.headers ?? {}) } : resto.headers,
    body: json !== undefined ? JSON.stringify(json) : resto.body,
    cache: "no-store",
  });
  const corpo = (await resposta.json().catch(() => null)) as (T & { error?: string; pendencias?: Pendencia[] }) | null;
  if (!resposta.ok) {
    throw new ErroDaTela(corpo?.error || "Não foi possível concluir agora.", resposta.status, corpo?.pendencias ?? []);
  }
  return corpo as T;
}

/* ------------------------------------------------------------------ */
/* Formatos                                                            */
/* ------------------------------------------------------------------ */

const MOEDA = new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL" });

export function moeda(valorEmReais: number | null | undefined) {
  return MOEDA.format(Number(valorEmReais) || 0);
}

export function moedaDeCentavos(centavos: number | null | undefined) {
  return MOEDA.format((Number(centavos) || 0) / 100);
}

export function dataCurta(iso: string | null | undefined) {
  if (!iso) return "";
  const data = new Date(iso);
  if (!Number.isFinite(data.getTime())) return "";
  return data.toLocaleDateString("pt-BR", { day: "2-digit", month: "2-digit", year: "numeric" });
}

export function dataEHora(iso: string | null | undefined) {
  if (!iso) return "";
  const data = new Date(iso);
  if (!Number.isFinite(data.getTime())) return "";
  return data.toLocaleString("pt-BR", { day: "2-digit", month: "2-digit", year: "numeric", hour: "2-digit", minute: "2-digit" });
}

/** "há 3 min", "há 2 h", "ontem"... para a linha do tempo. */
export function haQuantoTempo(iso: string | null | undefined) {
  if (!iso) return "";
  const segundos = Math.round((Date.now() - new Date(iso).getTime()) / 1000);
  if (!Number.isFinite(segundos)) return "";
  if (segundos < 45) return "agora";
  if (segundos < 3600) return `há ${Math.max(1, Math.round(segundos / 60))} min`;
  if (segundos < 86400) return `há ${Math.round(segundos / 3600)} h`;
  if (segundos < 172800) return "ontem";
  return dataCurta(iso);
}

export function chaveEmBlocos(chave: string | null | undefined) {
  const digitos = String(chave || "").replace(/\D/g, "");
  return digitos.replace(/(\d{4})(?=\d)/g, "$1 ");
}

export function documentoFormatado(documento: string | null | undefined) {
  const d = String(documento || "").replace(/\D/g, "");
  if (d.length === 11) return d.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, "$1.$2.$3-$4");
  if (d.length === 14) return d.replace(/(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})/, "$1.$2.$3/$4-$5");
  return documento || "";
}

export function mesPorExtenso(competencia: string | null | undefined) {
  if (!competencia) return "";
  const [ano, mes] = competencia.split("-").map(Number);
  if (!ano || !mes) return "";
  const nome = new Date(Date.UTC(ano, mes - 1, 15)).toLocaleDateString("pt-BR", { month: "long", timeZone: "UTC" });
  return `${nome} de ${ano}`;
}

/** Quantos dias faltam para o mês virar (o pacote zera na virada). */
export function diasParaVirarOMes(agora = new Date()) {
  const partes = new Intl.DateTimeFormat("en-CA", { timeZone: "America/Sao_Paulo", year: "numeric", month: "2-digit", day: "2-digit" })
    .format(agora)
    .split("-")
    .map(Number);
  const ultimoDia = new Date(Date.UTC(partes[0], partes[1], 0)).getUTCDate();
  return ultimoDia - partes[2];
}

/* ------------------------------------------------------------------ */
/* Selos                                                               */
/* ------------------------------------------------------------------ */

const CORES_DO_TOM: Record<TomDoStatus, { texto: string; fundo: string; bolinha: string }> = {
  bom: { texto: "text-emerald-700", fundo: "bg-emerald-500/10", bolinha: "bg-emerald-500" },
  ruim: { texto: "text-rose-700", fundo: "bg-rose-500/10", bolinha: "bg-rose-500" },
  andamento: { texto: "text-violet-700", fundo: "bg-violet-500/10", bolinha: "bg-violet-500 animate-pulse" },
  neutro: { texto: "text-slate-600", fundo: "bg-slate-500/10", bolinha: "bg-slate-400" },
  atencao: { texto: "text-sky-700", fundo: "bg-sky-500/10", bolinha: "bg-sky-500" },
};

export function SeloDoStatus({ tom, rotulo, titulo }: { tom: TomDoStatus; rotulo: string; titulo?: string }) {
  const cores = CORES_DO_TOM[tom] ?? CORES_DO_TOM.neutro;
  return (
    <span
      title={titulo}
      className={`inline-flex items-center gap-1.5 whitespace-nowrap rounded-full px-2.5 py-1 text-[11px] font-bold ${cores.fundo} ${cores.texto}`}
    >
      <span className={`h-1.5 w-1.5 rounded-full ${cores.bolinha}`} />
      {rotulo}
    </span>
  );
}

const CORES_DO_MODELO: Record<string, string> = {
  nfe: "from-violet-500 to-purple-600",
  nfce: "from-fuchsia-500 to-pink-600",
  nfse: "from-sky-500 to-indigo-600",
};

/** O quadradinho com a sigla do modelo, no lugar do avatar da linha. */
export function MarcaDoModelo({ modelo, tamanho = "md" }: { modelo: string; tamanho?: "sm" | "md" }) {
  const sigla = modelo === "nfce" ? "NFC" : modelo === "nfse" ? "NFS" : "NF";
  const classe = tamanho === "sm" ? "h-8 w-8 rounded-lg text-[9px]" : "h-10 w-10 rounded-xl text-[10px]";
  return (
    <span
      aria-hidden
      className={`flex shrink-0 flex-col items-center justify-center bg-gradient-to-br font-black leading-none tracking-tight text-white shadow-sm ${classe} ${CORES_DO_MODELO[modelo] ?? CORES_DO_MODELO.nfe}`}
    >
      <span>{sigla}</span>
      <span className="mt-0.5 opacity-80">-e</span>
    </span>
  );
}

export function SeloSemValorFiscal() {
  return (
    <span className="inline-flex items-center rounded-full bg-slate-900/[0.06] px-2 py-0.5 text-[10px] font-bold uppercase tracking-[0.08em] text-slate-500">
      Teste
    </span>
  );
}

/* ------------------------------------------------------------------ */
/* Pendências                                                          */
/* ------------------------------------------------------------------ */

const ONDE_RESOLVER: Record<string, string> = {
  cliente: "No cadastro do cliente",
  produto: "No cadastro do produto",
  servico: "No serviço",
  empresa: "Na configuração das notas",
  perfil: "Na tributação",
  pedido: "No pedido",
  pagamento: "Nos pagamentos do pedido",
};

/* Na nota sem pedido, "pedido" e "pagamento" são a própria tela de emissão. */
const ONDE_RESOLVER_SEM_PEDIDO: Record<string, string> = {
  pedido: "Nesta nota",
  pagamento: "No pagamento desta nota",
};

type ContextoDaPendencia = { clienteId?: string | null; pedidoId?: string | null; semPedido?: boolean };

export function linkParaResolver(pendencia: Pendencia, contexto: ContextoDaPendencia) {
  if (contexto.semPedido && (pendencia.onde === "pedido" || pendencia.onde === "pagamento")) return null;
  if (pendencia.onde === "cliente" && contexto.clienteId) return `/dashboard/clients/${contexto.clienteId}?editar=1`;
  if (pendencia.onde === "produto" && pendencia.alvoId) return `/dashboard/products/${pendencia.alvoId}`;
  if (pendencia.onde === "produto") return "/dashboard/notas-fiscais/configuracao?passo=notas&abrir=produtos";
  if (pendencia.onde === "perfil") return `/dashboard/notas-fiscais/configuracao?passo=notas&abrir=${pendencia.alvoId ? `ajustes:${pendencia.alvoId}` : "ajustes"}`;
  if (pendencia.onde === "empresa" && pendencia.codigo.startsWith("creditos.")) return "/dashboard/assinatura#notas";
  if (pendencia.codigo === "empresa.csc") return "/dashboard/notas-fiscais/configuracao?passo=notas";
  if (pendencia.onde === "empresa") return "/dashboard/notas-fiscais/configuracao";
  if ((pendencia.onde === "pagamento" || pendencia.onde === "pedido") && contexto.pedidoId) return `/dashboard/orders/${contexto.pedidoId}?aba=financeiro`;
  return null;
}

export function ListaDePendencias({
  pendencias,
  contexto,
  acao,
}: {
  pendencias: Pendencia[];
  contexto: ContextoDaPendencia;
  /** Uma ação na própria tela (abrir o cadastro, ir para a linha) no lugar do link. */
  acao?: (pendencia: Pendencia) => { rotulo: string; aoClicar: () => void } | null;
}) {
  if (!pendencias.length) return null;
  const ordenadas = [...pendencias].sort((a, b) => (a.nivel === b.nivel ? 0 : a.nivel === "bloqueio" ? -1 : 1));
  return (
    <ul className="divide-y divide-slate-100/60">
      {ordenadas.map((pendencia) => {
        const propria = acao?.(pendencia) ?? null;
        const link = propria ? null : linkParaResolver(pendencia, contexto);
        const bloqueio = pendencia.nivel === "bloqueio";
        return (
          <li key={`${pendencia.codigo}:${pendencia.alvoId ?? ""}`} className="flex items-start gap-3 py-2.5">
            <span
              aria-hidden
              className={`mt-1.5 h-2 w-2 shrink-0 rounded-full ${bloqueio ? "bg-rose-500 shadow-[0_0_0_3px_rgba(244,63,94,0.15)]" : "bg-sky-500"}`}
            />
            <div className="min-w-0 flex-1">
              <p className="text-[13px] font-semibold text-[var(--ks-color-text-primary)]">{pendencia.titulo}</p>
              {pendencia.detalhe ? <p className="text-xs leading-5 text-[var(--ks-color-text-muted)]">{pendencia.detalhe}</p> : null}
              <p className="text-[11px] text-[var(--ks-color-text-soft)]">
                {(contexto.semPedido ? ONDE_RESOLVER_SEM_PEDIDO[pendencia.onde] : null) ?? ONDE_RESOLVER[pendencia.onde] ?? ""}
              </p>
            </div>
            {propria ? (
              <button type="button" onClick={propria.aoClicar} className="ks-button ks-button-soft ks-button-sm shrink-0">
                {propria.rotulo}
              </button>
            ) : link ? (
              <a href={link} target="_blank" rel="noopener noreferrer" className="ks-button ks-button-soft ks-button-sm shrink-0">
                Corrigir
              </a>
            ) : null}
          </li>
        );
      })}
    </ul>
  );
}
