import { pendenciasDoServidor } from "@/lib/fiscal/ambiente";
import { notaParaTela, planoParaTela } from "@/lib/fiscal/servidor/apresentacao";
import { contextoDaEmissao, emitirNotaAvulsa, formularioDaNotaGuardada, lerNotaAvulsa, planejarNotaAvulsa } from "@/lib/fiscal/servidor/avulsa";
import { servidorPronto } from "@/lib/fiscal/servidor/base";
import { acordarFila } from "@/lib/fiscal/servidor/fila";
import { carregarNota, ErroFiscal } from "@/lib/fiscal/servidor/notas";
import { exigirUuid, lerCorpo, rotaFiscal } from "@/lib/fiscal/servidor/rota";

export const runtime = "nodejs";
export const dynamic = "force-dynamic";

/**
 * O que a tela "Emitir nota fiscal" precisa para começar: tipos de nota
 * ligados, pacote do mês, preferências e tributações. Com `?nota=` (editar) ou
 * `?copiar=`, traz também o formulário guardado de uma nota sem pedido.
 */
export async function GET(req: Request) {
  return rotaFiscal("fiscal.emitir", async ({ admin, empresaId, ambiente, ctx }) => {
    const busca = new URL(req.url).searchParams;
    const contexto = await contextoDaEmissao(admin, { empresaId, ambiente });
    const base = { ambiente, servidorPronto: pendenciasDoServidor().length === 0, ...contexto };

    const notaId = busca.get("nota") || busca.get("copiar");
    if (!notaId) return base;
    const guardada = await formularioDaNotaGuardada(admin, { empresaId, tenantIds: ctx.tenantIds, notaId: exigirUuid(notaId, "Nota") });
    return { ...base, formulario: { dados: guardada.dados, cliente: guardada.cliente, fotos: guardada.fotos }, nota: notaParaTela(guardada.nota) };
  });
}

/** `acao`: "planejar" confere enquanto a pessoa preenche; "previa" gera o PDF sem emitir; "emitir" emite. */
export async function POST(req: Request) {
  return rotaFiscal("fiscal.emitir", async ({ admin, empresaId, ambiente, user, ctx }) => {
    const corpo = await lerCorpo(req);
    const acao = corpo.acao === "emitir" ? "emitir" : corpo.acao === "previa" ? "previa" : "planejar";
    const { dados, problemas } = lerNotaAvulsa(corpo.dados);

    if (acao === "planejar") {
      const plano = await planejarNotaAvulsa(admin, { empresaId, tenantIds: ctx.tenantIds, ambiente, dados, problemas });
      return { plano: planoParaTela(plano) };
    }

    const bloqueio = servidorPronto();
    if (bloqueio) throw new ErroFiscal(bloqueio, 503);
    if (!dados.chave) throw new ErroFiscal("A tela ficou desatualizada. Recarregue a página e tente de novo.", 400);

    const resultado = await emitirNotaAvulsa(admin, {
      empresaId,
      tenantIds: ctx.tenantIds,
      ambiente,
      usuarioId: user.id,
      dados,
      problemas,
      previa: acao === "previa",
    });
    acordarFila();
    if (resultado.bloqueado) {
      return Response.json({ error: "Há o que resolver antes de emitir.", pendencias: resultado.pendencias }, { status: 422 });
    }
    const notas = await Promise.all(resultado.notas.map((nota) => carregarNota(admin, nota.id)));
    return { plano: planoParaTela(resultado.plano), notas: notas.map((nota) => notaParaTela(nota)) };
  });
}
