import * as kv from "./kv_store.tsx";
import * as movimentosStock from "./movimentos-stock.tsx";
import { buscarArtigoPorId } from "./artigos.tsx";
import { buscarArmazemPorId } from "./armazens.tsx";
import { createLogger } from "./logger.tsx";
import * as exerciciosEconomicos from "./exercicios-economicos.tsx";
import { reservarNumeroSequencial } from "./document-numbering.tsx";

const logger = createLogger("DocumentosStock");
const DOCUMENTOS_STOCK_PREFIX = "documento_stock:";

export type TipoDocumentoStock =
  | "guia_entrada"
  | "guia_remessa"
  | "devolucao_cliente"
  | "devolucao_fornecedor"
  | "consumo_interno"
  | "auto_quebra"
  | "perda_vencimento"
  | "ajuste_positivo"
  | "ajuste_negativo";

export type EstadoDocumentoStock = "rascunho" | "emitido" | "anulado";

export interface LinhaDocumentoStock {
  id: string;
  artigoId: string;
  artigoCodigo: string;
  artigoNome: string;
  armazemId: string;
  armazemCodigo: string;
  armazemNome: string;
  loteId?: string;
  lote?: string;
  quantidade: number;
  custoUnitario?: number;
  valorTotal: number;
  observacoes?: string;
}

export interface DocumentoStock {
  id: string;
  empresaId: string;
  exercicioEconomicoId?: string;
  anoExercicio?: number;
  numero: string;
  tipo: TipoDocumentoStock;
  estado: EstadoDocumentoStock;
  dataDocumento: string;
  entidadeTipo?: "cliente" | "fornecedor" | "departamento" | "interno";
  entidadeId?: string;
  entidadeNome?: string;
  armazemId?: string;
  armazemCodigo?: string;
  armazemNome?: string;
  documentoOrigemTipo?: string;
  documentoOrigemId?: string;
  documentoOrigemNumero?: string;
  observacoes?: string;
  responsavel?: string;
  responsavelId?: string;
  responsavelNome?: string;
  responsavelEmail?: string;
  criadoPor?: string;
  criadoPorNome?: string;
  criadoPorEmail?: string;
  atualizadoPor?: string;
  atualizadoPorNome?: string;
  atualizadoPorEmail?: string;
  emitidoPor?: string;
  emitidoPorNome?: string;
  emitidoPorEmail?: string;
  emitidoEm?: string;
  anuladoPor?: string;
  anuladoPorNome?: string;
  anuladoPorEmail?: string;
  anuladoEm?: string;
  motivoAnulacao?: string;
  linhas: LinhaDocumentoStock[];
  totalLinhas: number;
  totalQuantidade: number;
  totalValor: number;
  movimentosIds: string[];
  movimentosReversaoIds: string[];
  criadoEm: string;
  atualizadoEm: string;
}

interface ConfiguracaoTipoDocumento {
  prefixo: string;
  label: string;
  movimentoTipo: movimentosStock.TipoMovimento;
  motivo: movimentosStock.MotivoMovimento;
  documentoTipoMovimento: string;
}

export const tiposDocumentoStock: Record<TipoDocumentoStock, ConfiguracaoTipoDocumento> = {
  guia_entrada: {
    prefixo: "GEM",
    label: "Guia de Entrada de Mercadoria",
    movimentoTipo: "entrada",
    motivo: "recepcao",
    documentoTipoMovimento: "guia_entrada",
  },
  guia_remessa: {
    prefixo: "GRM",
    label: "Guia de Remessa",
    movimentoTipo: "saida",
    motivo: "venda",
    documentoTipoMovimento: "guia_remessa",
  },
  devolucao_cliente: {
    prefixo: "GDC",
    label: "Guia de Devolucao de Cliente",
    movimentoTipo: "entrada",
    motivo: "devolucao_cliente",
    documentoTipoMovimento: "guia_devolucao_cliente",
  },
  devolucao_fornecedor: {
    prefixo: "GDF",
    label: "Guia de Devolucao ao Fornecedor",
    movimentoTipo: "saida",
    motivo: "devolucao_fornecedor",
    documentoTipoMovimento: "guia_devolucao_fornecedor",
  },
  consumo_interno: {
    prefixo: "RCI",
    label: "Requisicao de Consumo Interno",
    movimentoTipo: "saida",
    motivo: "consumo_interno",
    documentoTipoMovimento: "requisicao_interna",
  },
  auto_quebra: {
    prefixo: "AQB",
    label: "Auto de Quebra/Avaria",
    movimentoTipo: "saida",
    motivo: "danificacao",
    documentoTipoMovimento: "auto_quebra",
  },
  perda_vencimento: {
    prefixo: "APV",
    label: "Auto de Perda por Vencimento",
    movimentoTipo: "saida",
    motivo: "perda_vencimento",
    documentoTipoMovimento: "relatorio_validade",
  },
  ajuste_positivo: {
    prefixo: "AJP",
    label: "Documento de Ajuste Positivo de Stock",
    movimentoTipo: "entrada",
    motivo: "ajuste_positivo",
    documentoTipoMovimento: "ajuste_stock",
  },
  ajuste_negativo: {
    prefixo: "AJN",
    label: "Documento de Ajuste Negativo de Stock",
    movimentoTipo: "saida",
    motivo: "ajuste_negativo",
    documentoTipoMovimento: "ajuste_stock",
  },
};

function gerarId(): string {
  return `doc_stock_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
}

function gerarIdLinha(): string {
  return `linha_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
}

function normalizarTipoDocumento(tipo: unknown): TipoDocumentoStock | null {
  const valor = String(tipo || "")
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .trim()
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, "_")
    .replace(/^_+|_+$/g, "");

  if (valor in tiposDocumentoStock) return valor as TipoDocumentoStock;
  return null;
}

function obterDataDocumento(valor?: string): string {
  if (!valor) return new Date().toISOString().split("T")[0];
  return String(valor).split("T")[0];
}

function obterNumeroPositivo(valor: unknown): number {
  const numero = Number(valor);
  return Number.isFinite(numero) && numero > 0 ? numero : 0;
}

function calcularTotalizadores(linhas: LinhaDocumentoStock[]) {
  return {
    totalLinhas: linhas.length,
    totalQuantidade: linhas.reduce((total, linha) => total + linha.quantidade, 0),
    totalValor: linhas.reduce((total, linha) => total + linha.valorTotal, 0),
  };
}

async function gerarNumeroDocumento(
  empresaId: string,
  tipo: TipoDocumentoStock,
  anoExercicio = new Date().getFullYear(),
): Promise<string> {
  const ano = anoExercicio;
  const config = tiposDocumentoStock[tipo];
  const documentos = await listarDocumentosStock(empresaId, { tipo });
  const reserva = await reservarNumeroSequencial<DocumentoStock>({
    empresaId,
    modulo: "stock-inventario",
    tipoDocumento: `documento_stock_${tipo}`,
    ano,
    documentosExistentes: documentos,
    extrairSequencia: (documento, anoDocumento) => {
      const prefixo = `${config.prefixo}-${anoDocumento}-`;
      const match = String(documento.numero || "").match(new RegExp(`^${prefixo}(\\d+)$`));
      return match ? Number.parseInt(match[1], 10) : null;
    },
    formatarNumero: (sequencia, anoDocumento) => `${config.prefixo}-${anoDocumento}-${String(sequencia).padStart(3, "0")}`,
  });

  return reserva.numeroDocumento;

  const prefixo = `${config.prefixo}-${ano}-`;
  const maiorSequencia = documentos.reduce((maior, documento) => {
    const match = String(documento.numero || "").match(new RegExp(`^${prefixo}(\\d+)$`));
    const sequencia = match ? Number.parseInt(match[1], 10) : 0;
    return Number.isFinite(sequencia) && sequencia > maior ? sequencia : maior;
  }, 0);

  return `${prefixo}${String(maiorSequencia + 1).padStart(3, "0")}`;
}

async function normalizarLinhaDocumento(
  linha: any,
  documento: { empresaId: string; armazemId?: string },
): Promise<{ success: true; linha: LinhaDocumentoStock } | { success: false; error: string }> {
  const artigoId = linha?.artigoId;
  if (!artigoId) return { success: false, error: "Cada linha deve ter um artigo" };

  const artigo = await buscarArtigoPorId(artigoId);
  if (!artigo || artigo.empresaId !== documento.empresaId) {
    return { success: false, error: `Artigo ${artigoId} nao encontrado para esta empresa` };
  }

  if ((artigo as any).tipo === "servico") {
    return { success: false, error: `O artigo ${artigo.codigo} e servico e nao movimenta stock` };
  }

  const armazemId = linha?.armazemId || documento.armazemId;
  if (!armazemId) {
    return { success: false, error: `Informe o armazem da linha do artigo ${artigo.codigo}` };
  }

  const armazem = await buscarArmazemPorId(armazemId, documento.empresaId);
  if (!armazem || armazem.empresaId !== documento.empresaId) {
    return { success: false, error: `Armazem ${armazemId} nao encontrado para esta empresa` };
  }

  if (!armazem.ativo) {
    return { success: false, error: `O armazem ${armazem.codigo} esta inativo` };
  }

  const quantidade = obterNumeroPositivo(linha?.quantidade);
  if (quantidade <= 0) {
    return { success: false, error: `Quantidade invalida no artigo ${artigo.codigo}` };
  }

  const custoUnitario = obterNumeroPositivo(linha?.custoUnitario ?? linha?.precoUnitario ?? (artigo as any).custoMedio ?? (artigo as any).precoCompra);

  return {
    success: true,
    linha: {
      id: linha?.id || gerarIdLinha(),
      artigoId: artigo.id,
      artigoCodigo: artigo.codigo,
      artigoNome: artigo.nome || (artigo as any).descricao || artigo.codigo,
      armazemId: armazem.id,
      armazemCodigo: armazem.codigo,
      armazemNome: armazem.nome,
      loteId: linha?.loteId || undefined,
      lote: linha?.lote || undefined,
      quantidade,
      custoUnitario,
      valorTotal: Math.round((quantidade * custoUnitario + Number.EPSILON) * 100) / 100,
      observacoes: linha?.observacoes || undefined,
    },
  };
}

async function normalizarLinhasDocumento(
  dados: any,
): Promise<{ success: true; linhas: LinhaDocumentoStock[] } | { success: false; error: string }> {
  const linhasOrigem = Array.isArray(dados?.linhas) ? dados.linhas : [];
  if (linhasOrigem.length === 0) {
    return { success: false, error: "O documento deve ter pelo menos uma linha" };
  }

  const linhas: LinhaDocumentoStock[] = [];
  for (const linhaOrigem of linhasOrigem) {
    const resultado = await normalizarLinhaDocumento(linhaOrigem, dados);
    if (!resultado.success) return resultado;
    linhas.push(resultado.linha);
  }

  return { success: true, linhas };
}

export async function buscarDocumentoStockPorId(id: string): Promise<DocumentoStock | null> {
  try {
    return await kv.get(`${DOCUMENTOS_STOCK_PREFIX}${id}`) as DocumentoStock | null;
  } catch (error) {
    logger.error("[DocumentosStock] Erro ao buscar documento:", error);
    return null;
  }
}

export async function listarDocumentosStock(
  empresaId: string,
  filtros?: {
    tipo?: TipoDocumentoStock;
    estado?: EstadoDocumentoStock;
    dataInicio?: string;
    dataFim?: string;
    termo?: string;
  },
): Promise<DocumentoStock[]> {
  try {
    const todos = await kv.getByPrefix<DocumentoStock>(DOCUMENTOS_STOCK_PREFIX);
    let documentos = todos.filter((doc) => doc && doc.empresaId === empresaId);

    if (filtros?.tipo) documentos = documentos.filter((doc) => doc.tipo === filtros.tipo);
    if (filtros?.estado) documentos = documentos.filter((doc) => doc.estado === filtros.estado);
    if (filtros?.dataInicio) documentos = documentos.filter((doc) => doc.dataDocumento >= filtros.dataInicio!);
    if (filtros?.dataFim) documentos = documentos.filter((doc) => doc.dataDocumento <= filtros.dataFim!);
    if (filtros?.termo) {
      const termo = filtros.termo.trim().toLowerCase();
      documentos = documentos.filter((doc) =>
        [doc.numero, doc.entidadeNome, doc.armazemNome, doc.responsavelNome, doc.responsavel, doc.observacoes]
          .filter(Boolean)
          .some((valor) => String(valor).toLowerCase().includes(termo)) ||
        doc.linhas.some((linha) =>
          [linha.artigoCodigo, linha.artigoNome, linha.armazemNome, linha.observacoes]
            .filter(Boolean)
            .some((valor) => String(valor).toLowerCase().includes(termo))
        )
      );
    }

    return documentos.sort((a, b) => {
      const data = (b.emitidoEm || b.criadoEm || "").localeCompare(a.emitidoEm || a.criadoEm || "");
      if (data !== 0) return data;
      return (b.numero || "").localeCompare(a.numero || "");
    });
  } catch (error) {
    logger.error("[DocumentosStock] Erro ao listar documentos:", error);
    return [];
  }
}

export async function criarDocumentoStock(dados: any): Promise<{ success: boolean; data?: DocumentoStock; error?: string }> {
  try {
    const empresaId = dados?.empresaId;
    if (!empresaId) return { success: false, error: "empresaId e obrigatorio" };

    const tipo = normalizarTipoDocumento(dados?.tipo);
    if (!tipo) return { success: false, error: "Tipo de documento de stock invalido" };

    const linhasResultado = await normalizarLinhasDocumento({ ...dados, tipo });
    if (!linhasResultado.success) return { success: false, error: linhasResultado.error };

    let armazemPadrao: any = null;
    if (dados?.armazemId) {
      armazemPadrao = await buscarArmazemPorId(dados.armazemId, empresaId);
    }

    const dataDocumento = obterDataDocumento(dados?.dataDocumento);
    const exercicio = await exerciciosEconomicos.validarExercicioAberto(
      empresaId,
      dataDocumento,
      "documento de stock",
    );
    const agora = new Date().toISOString();
    const totalizadores = calcularTotalizadores(linhasResultado.linhas);
    const documento: DocumentoStock = {
      id: gerarId(),
      empresaId,
      exercicioEconomicoId: exercicio.id,
      anoExercicio: exercicio.ano,
      numero: dados?.numero && !String(dados.numero).startsWith("RASCUNHO")
        ? dados.numero
        : `RASCUNHO-${Date.now()}`,
      tipo,
      estado: "rascunho",
      dataDocumento,
      entidadeTipo: dados?.entidadeTipo || undefined,
      entidadeId: dados?.entidadeId || undefined,
      entidadeNome: dados?.entidadeNome || undefined,
      armazemId: armazemPadrao?.id || dados?.armazemId || undefined,
      armazemCodigo: armazemPadrao?.codigo || undefined,
      armazemNome: armazemPadrao?.nome || undefined,
      documentoOrigemTipo: dados?.documentoOrigemTipo || undefined,
      documentoOrigemId: dados?.documentoOrigemId || undefined,
      documentoOrigemNumero: dados?.documentoOrigemNumero || undefined,
      observacoes: dados?.observacoes || undefined,
      responsavel: dados?.responsavel || dados?.responsavelNome || dados?.usuarioAuditoriaNome || dados?.criadoPorNome,
      responsavelId: dados?.responsavelId || dados?.usuarioAuditoriaId || dados?.criadoPor,
      responsavelNome: dados?.responsavelNome || dados?.usuarioAuditoriaNome || dados?.criadoPorNome || dados?.responsavel,
      responsavelEmail: dados?.responsavelEmail || dados?.usuarioAuditoriaEmail || dados?.criadoPorEmail,
      criadoPor: dados?.criadoPor || dados?.usuarioAuditoriaId,
      criadoPorNome: dados?.criadoPorNome || dados?.usuarioAuditoriaNome,
      criadoPorEmail: dados?.criadoPorEmail || dados?.usuarioAuditoriaEmail,
      linhas: linhasResultado.linhas,
      ...totalizadores,
      movimentosIds: [],
      movimentosReversaoIds: [],
      criadoEm: agora,
      atualizadoEm: agora,
    };

    await kv.set(`${DOCUMENTOS_STOCK_PREFIX}${documento.id}`, documento);
    return { success: true, data: documento };
  } catch (error) {
    logger.error("[DocumentosStock] Erro ao criar documento:", error);
    return { success: false, error: error.message };
  }
}

export async function atualizarDocumentoStock(
  id: string,
  dados: any,
): Promise<{ success: boolean; data?: DocumentoStock; error?: string }> {
  try {
    const documento = await buscarDocumentoStockPorId(id);
    if (!documento) return { success: false, error: "Documento nao encontrado" };
    if (documento.estado !== "rascunho") {
      return { success: false, error: "Apenas documentos em rascunho podem ser editados" };
    }

    const tipo = normalizarTipoDocumento(dados?.tipo || documento.tipo);
    if (!tipo) return { success: false, error: "Tipo de documento de stock invalido" };

    const linhasResultado = await normalizarLinhasDocumento({ ...documento, ...dados, tipo });
    if (!linhasResultado.success) return { success: false, error: linhasResultado.error };

    let armazemPadrao: any = null;
    const armazemId = dados?.armazemId ?? documento.armazemId;
    if (armazemId) {
      armazemPadrao = await buscarArmazemPorId(armazemId, documento.empresaId);
    }

    const dataDocumento = obterDataDocumento(dados?.dataDocumento || documento.dataDocumento);
    const exercicio = await exerciciosEconomicos.validarExercicioAberto(
      documento.empresaId,
      dataDocumento,
      "documento de stock",
    );
    const totalizadores = calcularTotalizadores(linhasResultado.linhas);
    const atualizado: DocumentoStock = {
      ...documento,
      exercicioEconomicoId: exercicio.id,
      anoExercicio: exercicio.ano,
      tipo,
      dataDocumento,
      entidadeTipo: dados?.entidadeTipo ?? documento.entidadeTipo,
      entidadeId: dados?.entidadeId ?? documento.entidadeId,
      entidadeNome: dados?.entidadeNome ?? documento.entidadeNome,
      armazemId: armazemPadrao?.id || armazemId || undefined,
      armazemCodigo: armazemPadrao?.codigo || documento.armazemCodigo,
      armazemNome: armazemPadrao?.nome || documento.armazemNome,
      documentoOrigemTipo: dados?.documentoOrigemTipo ?? documento.documentoOrigemTipo,
      documentoOrigemId: dados?.documentoOrigemId ?? documento.documentoOrigemId,
      documentoOrigemNumero: dados?.documentoOrigemNumero ?? documento.documentoOrigemNumero,
      observacoes: dados?.observacoes ?? documento.observacoes,
      responsavel: dados?.responsavel || dados?.responsavelNome || documento.responsavel,
      responsavelId: dados?.responsavelId || dados?.usuarioAuditoriaId || documento.responsavelId,
      responsavelNome: dados?.responsavelNome || dados?.usuarioAuditoriaNome || documento.responsavelNome,
      responsavelEmail: dados?.responsavelEmail || dados?.usuarioAuditoriaEmail || documento.responsavelEmail,
      atualizadoPor: dados?.atualizadoPor || dados?.usuarioAuditoriaId,
      atualizadoPorNome: dados?.atualizadoPorNome || dados?.usuarioAuditoriaNome,
      atualizadoPorEmail: dados?.atualizadoPorEmail || dados?.usuarioAuditoriaEmail,
      linhas: linhasResultado.linhas,
      ...totalizadores,
      atualizadoEm: new Date().toISOString(),
    };

    await kv.set(`${DOCUMENTOS_STOCK_PREFIX}${id}`, atualizado);
    return { success: true, data: atualizado };
  } catch (error) {
    logger.error("[DocumentosStock] Erro ao atualizar documento:", error);
    return { success: false, error: error.message };
  }
}

export async function emitirDocumentoStock(
  id: string,
  dados?: any,
): Promise<{ success: boolean; data?: DocumentoStock; error?: string }> {
  const movimentosCriados: string[] = [];

  try {
    const documento = await buscarDocumentoStockPorId(id);
    if (!documento) return { success: false, error: "Documento nao encontrado" };
    if (documento.estado === "emitido") return { success: true, data: documento };
    if (documento.estado === "anulado") return { success: false, error: "Documento anulado nao pode ser emitido" };

    const exercicio = await exerciciosEconomicos.validarExercicioAberto(
      documento.empresaId,
      documento.dataDocumento,
      "documento de stock",
    );
    const config = tiposDocumentoStock[documento.tipo];
    const numeroOficial = documento.numero.startsWith("RASCUNHO")
      ? await gerarNumeroDocumento(documento.empresaId, documento.tipo, exercicio.ano)
      : documento.numero;
    const agora = new Date().toISOString();

    for (const linha of documento.linhas) {
      const resultado = await movimentosStock.criarMovimento({
        empresaId: documento.empresaId,
        artigoId: linha.artigoId,
        loteId: linha.loteId,
        lote: linha.lote,
        tipo: config.movimentoTipo,
        quantidade: linha.quantidade,
        custoUnitario: linha.custoUnitario,
        motivo: config.motivo,
        documentoId: documento.id,
        documentoTipo: config.documentoTipoMovimento,
        documentoNumero: numeroOficial,
        armazemId: linha.armazemId,
        observacoes: [documento.observacoes, linha.observacoes].filter(Boolean).join(" | "),
        dataMovimento: documento.dataDocumento,
        responsavel: dados?.responsavel || dados?.responsavelNome || documento.responsavel,
        responsavelId: dados?.responsavelId || dados?.usuarioAuditoriaId || documento.responsavelId,
        responsavelNome: dados?.responsavelNome || dados?.usuarioAuditoriaNome || documento.responsavelNome,
        responsavelEmail: dados?.responsavelEmail || dados?.usuarioAuditoriaEmail || documento.responsavelEmail,
        criadoPor: dados?.criadoPor || dados?.usuarioAuditoriaId || documento.criadoPor,
        criadoPorNome: dados?.criadoPorNome || dados?.usuarioAuditoriaNome || documento.criadoPorNome,
        criadoPorEmail: dados?.criadoPorEmail || dados?.usuarioAuditoriaEmail || documento.criadoPorEmail,
      });

      if (!resultado.success || !resultado.data) {
        for (const movimentoId of movimentosCriados.reverse()) {
          await movimentosStock.deletarMovimento(movimentoId).catch(() => null);
        }
        return { success: false, error: resultado.error || `Erro ao gerar movimento da linha ${linha.artigoCodigo}` };
      }

      movimentosCriados.push(resultado.data.id);
    }

    const emitido: DocumentoStock = {
      ...documento,
      exercicioEconomicoId: exercicio.id,
      anoExercicio: exercicio.ano,
      numero: numeroOficial,
      estado: "emitido",
      movimentosIds: movimentosCriados,
      emitidoEm: agora,
      emitidoPor: dados?.emitidoPor || dados?.usuarioAuditoriaId || dados?.criadoPor,
      emitidoPorNome: dados?.emitidoPorNome || dados?.usuarioAuditoriaNome || dados?.criadoPorNome,
      emitidoPorEmail: dados?.emitidoPorEmail || dados?.usuarioAuditoriaEmail || dados?.criadoPorEmail,
      atualizadoEm: agora,
    };

    await kv.set(`${DOCUMENTOS_STOCK_PREFIX}${id}`, emitido);
    return { success: true, data: emitido };
  } catch (error) {
    logger.error("[DocumentosStock] Erro ao emitir documento:", error);
    for (const movimentoId of movimentosCriados.reverse()) {
      await movimentosStock.deletarMovimento(movimentoId).catch(() => null);
    }
    return { success: false, error: error.message };
  }
}

export async function anularDocumentoStock(
  id: string,
  dados?: any,
): Promise<{ success: boolean; data?: DocumentoStock; error?: string }> {
  try {
    const documento = await buscarDocumentoStockPorId(id);
    if (!documento) return { success: false, error: "Documento nao encontrado" };
    if (documento.estado === "anulado") return { success: true, data: documento };

    const agora = new Date().toISOString();
    const movimentosReversaoIds: string[] = [...(documento.movimentosReversaoIds || [])];
    const responsavel = dados?.responsavel || dados?.responsavelNome || dados?.usuarioAuditoriaNome || "Sistema";
    const observacoes = dados?.motivoAnulacao || dados?.observacoes || `Anulacao do documento ${documento.numero}`;

    if (documento.estado === "emitido") {
      for (const movimentoId of documento.movimentosIds || []) {
        const movimento = await movimentosStock.buscarMovimentoPorId(movimentoId);
        if (!movimento) continue;
        if (movimento.movimentoReversaoId || movimento.revertidoEm) {
          if (movimento.movimentoReversaoId) movimentosReversaoIds.push(movimento.movimentoReversaoId);
          continue;
        }

        if (movimento.tipo === "saida") {
          const reversao = await movimentosStock.reverterMovimentoDocumento(movimentoId, {
            responsavel,
            observacoes,
            documentoTipoReversao: "anulacao_documento_stock",
            documentoNumeroReversao: `AN-${documento.numero}`,
          });

          if (!reversao.success || !reversao.data) {
            return { success: false, error: reversao.error || `Erro ao anular movimento ${movimentoId}` };
          }

          movimentosReversaoIds.push(reversao.data.movimentoReversao.id);
        } else {
          const reversao = await movimentosStock.criarMovimento({
            empresaId: documento.empresaId,
            artigoId: movimento.artigoId,
            tipo: "saida",
            quantidade: movimento.quantidade,
            motivo: "ajuste_negativo",
            documentoId: documento.id,
            documentoTipo: "anulacao_documento_stock",
            documentoNumero: `AN-${documento.numero}`,
            armazemId: movimento.armazemId,
            observacoes,
            dataMovimento: agora.split("T")[0],
            responsavel,
            responsavelId: dados?.responsavelId || dados?.usuarioAuditoriaId,
            responsavelNome: dados?.responsavelNome || dados?.usuarioAuditoriaNome,
            responsavelEmail: dados?.responsavelEmail || dados?.usuarioAuditoriaEmail,
          });

          if (!reversao.success || !reversao.data) {
            return { success: false, error: reversao.error || `Erro ao anular movimento ${movimentoId}` };
          }

          movimentosReversaoIds.push(reversao.data.id);
        }
      }
    }

    const anulado: DocumentoStock = {
      ...documento,
      estado: "anulado",
      movimentosReversaoIds,
      anuladoEm: agora,
      anuladoPor: dados?.anuladoPor || dados?.usuarioAuditoriaId,
      anuladoPorNome: dados?.anuladoPorNome || dados?.usuarioAuditoriaNome,
      anuladoPorEmail: dados?.anuladoPorEmail || dados?.usuarioAuditoriaEmail,
      motivoAnulacao: observacoes,
      atualizadoEm: agora,
    };

    await kv.set(`${DOCUMENTOS_STOCK_PREFIX}${id}`, anulado);
    return { success: true, data: anulado };
  } catch (error) {
    logger.error("[DocumentosStock] Erro ao anular documento:", error);
    return { success: false, error: error.message };
  }
}

export async function eliminarDocumentoStock(id: string): Promise<{ success: boolean; error?: string }> {
  try {
    const documento = await buscarDocumentoStockPorId(id);
    if (!documento) return { success: false, error: "Documento nao encontrado" };
    if (documento.estado !== "rascunho") {
      return { success: false, error: "Apenas rascunhos podem ser eliminados. Documentos emitidos devem ser anulados." };
    }

    await kv.del(`${DOCUMENTOS_STOCK_PREFIX}${id}`);
    return { success: true };
  } catch (error) {
    logger.error("[DocumentosStock] Erro ao eliminar documento:", error);
    return { success: false, error: error.message };
  }
}
