/**
 * Nota fiscal nas vendas da loja virtual e no link de acompanhamento.
 *
 * A loja não fala com a Spedy: ela só põe a emissão na fila das notas, que é
 * processada pelo servidor do admin do mesmo ambiente. E o link público do
 * pedido entrega o PDF e o XML já guardados no bucket privado — nada de chave
 * de nenhum sistema passa por aqui.
 *
 * O ambiente segue a mesma regra do admin (`lib/fiscal/ambiente.ts`): o banco é
 * um só para o servidor local e o de produção, e cada um só mexe no que é seu.
 */

type Banco = {
  from: (tabela: string) => any; // eslint-disable-line @typescript-eslint/no-explicit-any
  rpc: (funcao: string, parametros: Record<string, unknown>) => PromiseLike<{ data: unknown; error: { message?: string } | null }>;
};

export function ambienteFiscal(): "sandbox" | "producao" {
  const declarado = String(process.env.SPEDY_AMBIENTE || "").trim().toLowerCase();
  if (declarado === "producao" || declarado === "produção" || declarado === "production") return "producao";
  if (declarado === "sandbox") return "sandbox";
  return process.env.NODE_ENV === "production" ? "producao" : "sandbox";
}

const objeto = (valor: unknown): Record<string, unknown> =>
  valor && typeof valor === "object" && !Array.isArray(valor) ? (valor as Record<string, unknown>) : {};

/**
 * Venda paga na loja: se a empresa pediu, a nota entra na fila. A NF-e dos
 * produtos físicos (Notas fiscais › preferências) e a NFS-e dos digitais
 * (Configurações dos digitais) vão no mesmo pedido de emissão: a fila junta
 * os pedidos repetidos e a segunda escolha apagaria a primeira. Nunca derruba
 * a venda.
 */
export async function agendarNotaDaLoja(banco: Banco, empresaId: string, pedidoId: string) {
  try {
    const ambiente = ambienteFiscal();
    const { data: emissor } = await banco
      .from("fiscal_emissores")
      .select("status,nfe,nfse,preferencias")
      .eq("empresa_id", empresaId)
      .eq("ambiente", ambiente)
      .maybeSingle();
    if (!emissor || emissor.status !== "ativo") return;
    const querNfe = objeto(emissor.nfe).ativo === true && objeto(emissor.preferencias).emitirNaLoja === true;
    let querNfse = false;
    if (objeto(emissor.nfse).ativo === true) {
      const [{ data: ajustes }, { data: itens }] = await Promise.all([
        banco.from("digital_settings").select("config").eq("user_id", empresaId).maybeSingle(),
        banco.from("order_items").select("products(product_kind)").eq("order_id", pedidoId).limit(200),
      ]);
      const ligada = objeto(objeto(objeto(ajustes).config).fiscal).nfseNaLoja === true;
      const temDigital = Array.isArray(itens) && itens.some((item: unknown) => objeto(objeto(item).products).product_kind === "digital");
      querNfse = ligada && temDigital;
    }
    if (!querNfe && !querNfse) return;
    const somente = [...(querNfe ? ["nfe"] : []), ...(querNfse ? ["nfse"] : [])];
    const { error } = await banco.rpc("fiscal_agendar", {
      p_ambiente: ambiente,
      p_tipo: "emitir_pedido",
      p_empresa: empresaId,
      p_nota: null,
      p_compra: null,
      p_pedido: pedidoId,
      p_dados: { escolhas: { modeloDeMercadoria: "nfe", presenca: "internet", somente } },
      /* Um respiro para o pagamento e o frete terminarem de gravar. */
      p_executar_em: new Date(Date.now() + 20_000).toISOString(),
    });
    if (error) console.error("[fiscal] NF-e da loja não agendada", pedidoId, error.message);
  } catch (erro) {
    console.error("[fiscal] NF-e da loja não agendada", pedidoId, erro instanceof Error ? erro.message : erro);
  }
}

export type NotaPublica = {
  id: string;
  modelo: "nfe" | "nfce" | "nfse";
  numero: number | null;
  serie: string | null;
  chave: string | null;
  valor: number;
  status: "autorizada" | "cancelada";
  autorizadaEm: string | null;
  teste: boolean;
  temPdf: boolean;
  temXml: boolean;
};

/** As notas do pedido que o cliente pode baixar. Nota de teste só aparece fora da produção. */
export async function notasPublicasDoPedido(banco: Banco, pedidoId: string): Promise<NotaPublica[]> {
  const { data, error } = await banco
    .from("fiscal_notas")
    .select("id,modelo,numero,serie,chave,valor,status,autorizada_em,ambiente,ambiente_nota,pdf_path,xml_path")
    .eq("pedido_id", pedidoId)
    .in("status", ["autorizada", "cancelada"])
    .order("created_at", { ascending: true });
  if (error || !Array.isArray(data)) return [];
  const producao = process.env.NODE_ENV === "production";
  return (data as Array<Record<string, unknown>>)
    .filter((nota) => nota.ambiente === ambienteFiscal())
    .filter((nota) => !producao || nota.ambiente_nota === "producao")
    .map((nota) => ({
      id: String(nota.id),
      modelo: nota.modelo === "nfce" ? "nfce" : nota.modelo === "nfse" ? "nfse" : "nfe",
      numero: nota.numero === null || nota.numero === undefined ? null : Number(nota.numero),
      serie: nota.serie ? String(nota.serie) : null,
      chave: nota.chave ? String(nota.chave) : null,
      valor: Number(nota.valor) || 0,
      status: nota.status === "cancelada" ? "cancelada" : "autorizada",
      autorizadaEm: nota.autorizada_em ? String(nota.autorizada_em) : null,
      teste: nota.ambiente_nota !== "producao",
      temPdf: Boolean(nota.pdf_path),
      temXml: Boolean(nota.xml_path),
    }));
}
