// Gestão de Inventários Físicos
import * as kv from './kv_store.tsx';
import { buscarArtigoPorId } from './artigos.tsx';
import { buscarArmazemPorCodigo, buscarArmazemPorId, listarArmazens, type Armazem } from './armazens.tsx';
import { buscarStockArtigoArmazem, upsertStock, listarStockPorArmazem } from './stock-armazem.tsx';
import * as movimentosStock from './movimentos-stock.tsx';
import * as stockLotes from './stock-lotes.tsx';
import { createLogger } from "./logger.tsx";
import * as exerciciosEconomicos from "./exercicios-economicos.tsx";
import { reservarNumeroSequencial } from "./document-numbering.tsx";
import * as kvAtomic from "./kv_atomic.tsx";

const logger = createLogger('Inventarios');

// ========== INTERFACES ==========

export interface LinhaInventario {
  id: string;
  artigoId: string;
  artigoCodigo: string;
  artigoNome: string;
  artigoCustoMedio: number;
  stockSistema: number; // Quantidade no sistema antes do inventário
  contagemFisica: number | null; // Quantidade contada fisicamente
  diferenca: number; // contagemFisica - stockSistema
  valorDiferenca: number; // diferenca * custoMedio
  motivoDiferenca?: string;
  statusLinha: 'nao_contado' | 'contado' | 'conferido';
  observacoes?: string;
}

export interface Inventario {
  id: string;
  empresaId: string;
  exercicioEconomicoId?: string;
  anoExercicio?: number;
  numero: string; // INV-2024-001
  armazemId: string;
  armazemCodigo: string;
  armazemNome: string;
  tipo: 'total' | 'parcial';
  status: 'rascunho' | 'em_contagem' | 'fechado' | 'cancelado';
  dataInventario: string;
  dataInicio?: string; // Quando iniciou a contagem
  dataFinalizacao?: string; // Quando finalizou
  responsavel: string;
  responsavelId?: string;
  responsavelNome?: string;
  responsavelEmail?: string;
  criadoPor?: string;
  criadoPorNome?: string;
  criadoPorEmail?: string;
  atualizadoPor?: string;
  atualizadoPorNome?: string;
  atualizadoPorEmail?: string;
  observacoes?: string;
  linhas: LinhaInventario[];
  
  // Totalizadores (calculados)
  totalArtigos: number;
  totalContado: number;
  totalDiferencasPositivas: number;
  totalDiferencasNegativas: number;
  valorLiquidoDiferencas: number;
  
  criadoEm: string;
  atualizadoEm: string;
}

// ========== FUNÃ‡Ã•ES AUXILIARES ==========

function gerarId(): string {
  return `inv_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}

async function gerarNumero(empresaId: string, anoExercicio = new Date().getFullYear()): Promise<string> {
  const ano = anoExercicio;
  const inventarios = await listarInventarios(empresaId);
  const reserva = await reservarNumeroSequencial<Inventario>({
    empresaId,
    modulo: "stock-inventario",
    tipoDocumento: "inventario",
    ano,
    documentosExistentes: inventarios,
    extrairSequencia: (inventario, anoDocumento) => {
      const match = String(inventario.numero || "").match(new RegExp(`^INV-${anoDocumento}-(\\d+)$`));
      return match ? Number.parseInt(match[1], 10) : null;
    },
    formatarNumero: (sequencia, anoDocumento) => `INV-${anoDocumento}-${String(sequencia).padStart(3, '0')}`,
  });

  return reserva.numeroDocumento;

  const inventariosDoAno = inventarios.filter(inv => inv.numero.startsWith(`INV-${ano}-`));
  const maiorSequencia = inventariosDoAno.reduce((max, inventario) => {
    const match = inventario.numero.match(new RegExp(`^INV-${ano}-(\\d+)$`));
    const sequencia = match ? Number.parseInt(match[1], 10) : 0;
    return Number.isFinite(sequencia) && sequencia > max ? sequencia : max;
  }, 0);
  const numeroSequencial = maiorSequencia + 1;
  return `INV-${ano}-${numeroSequencial.toString().padStart(3, '0')}`;
}

function calcularTotalizadores(linhas: LinhaInventario[]): {
  totalArtigos: number;
  totalContado: number;
  totalDiferencasPositivas: number;
  totalDiferencasNegativas: number;
  valorLiquidoDiferencas: number;
} {
  const totalArtigos = linhas.length;
  const totalContado = linhas.filter(l => l.statusLinha !== 'nao_contado').length;
  
  let totalDiferencasPositivas = 0;
  let totalDiferencasNegativas = 0;
  
  linhas.forEach(linha => {
    if (linha.valorDiferenca > 0) {
      totalDiferencasPositivas += linha.valorDiferenca;
    } else if (linha.valorDiferenca < 0) {
      totalDiferencasNegativas += Math.abs(linha.valorDiferenca);
    }
  });
  
  const valorLiquidoDiferencas = linhas.reduce((sum, l) => sum + l.valorDiferenca, 0);
  
  return {
    totalArtigos,
    totalContado,
    totalDiferencasPositivas,
    totalDiferencasNegativas,
    valorLiquidoDiferencas,
  };
}

function normalizarContagemFisica(valor: unknown): { success: true; valor: number | null } | { success: false; error: string } {
  if (valor === null || valor === undefined) {
    return { success: true, valor: null };
  }

  if (typeof valor !== 'number' && typeof valor !== 'string') {
    return { success: false, error: 'Contagem fisica invalida' };
  }

  if (typeof valor === 'string' && valor.trim() === '') {
    return { success: true, valor: null };
  }

  const numero = typeof valor === 'string'
    ? Number(valor.trim().replace(',', '.'))
    : Number(valor);

  if (!Number.isFinite(numero) || numero < 0) {
    return { success: false, error: 'Contagem fisica invalida' };
  }

  return { success: true, valor: numero };
}

async function registrarLoteAjusteInventario(dados: {
  empresaId: string;
  artigoId: string;
  armazemId: string;
  inventarioNumero: string;
  quantidade: number;
  custoUnitario: number;
}): Promise<void> {
  const loteAjuste = `INV-${dados.inventarioNumero}`;
  const loteExistente = await stockLotes.buscarLotePorIdentidade(
    dados.empresaId,
    dados.artigoId,
    dados.armazemId,
    loteAjuste,
    undefined,
  );

  await stockLotes.upsertLote({
    empresaId: dados.empresaId,
    artigoId: dados.artigoId,
    armazemId: dados.armazemId,
    lote: loteAjuste,
    quantidade: (loteExistente?.quantidade || 0) + dados.quantidade,
    quantidadeReservada: loteExistente?.quantidadeReservada || 0,
    custoUnitario: dados.custoUnitario,
    documentoCompraId: dados.inventarioNumero,
    localizacao: loteExistente?.localizacao,
    status: 'ativo',
  });
}

async function resolverArmazemInventario(empresaId: string, referencia: string): Promise<Armazem | null> {
  const valor = String(referencia || '').trim();
  if (!empresaId || !valor) {
    return null;
  }

  const candidatos = Array.from(new Set([
    valor,
    valor.startsWith('armazem:') ? valor.slice('armazem:'.length) : valor,
    valor.includes(' - ') ? valor.split(' - ')[0].trim() : valor,
  ].filter(Boolean)));

  for (const candidato of candidatos) {
    const porId = await buscarArmazemPorId(candidato, empresaId);
    if (porId?.empresaId === empresaId) {
      return porId;
    }

    const porCodigo = await buscarArmazemPorCodigo(empresaId, candidato);
    if (porCodigo?.empresaId === empresaId) {
      return porCodigo;
    }
  }

  const armazensEmpresa = await listarArmazens(empresaId);
  const referenciaUpper = valor.toUpperCase();
  return armazensEmpresa.find((armazem) => {
    const id = String(armazem.id || '');
    const codigo = String(armazem.codigo || '').toUpperCase();
    const nome = String(armazem.nome || '').toUpperCase();
    const composto = `${codigo} - ${nome}`;
    return (
      id === valor ||
      `armazem:${id}` === valor ||
      codigo === referenciaUpper ||
      nome === referenciaUpper ||
      composto === referenciaUpper
    );
  }) || null;
}

// ========== CRUD INVENTÁRIOS ==========

// Criar inventário
export async function criarInventario(dados: {
  empresaId: string;
  armazemId: string;
  tipo: 'total' | 'parcial';
  dataInventario: string;
  responsavel: string;
  responsavelId?: string;
  responsavelNome?: string;
  responsavelEmail?: string;
  criadoPor?: string;
  criadoPorNome?: string;
  criadoPorEmail?: string;
  usuarioAuditoriaId?: string;
  usuarioAuditoriaNome?: string;
  usuarioAuditoriaEmail?: string;
  observacoes?: string;
  artigosIds?: string[]; // Para inventário parcial
}): Promise<{ success: boolean; inventario?: Inventario; error?: string }> {
  try {
    logger.info('[Inventarios] ðŸ†• Criando inventário:', dados);

    // Buscar dados do armazém
    const armazem = await resolverArmazemInventario(dados.empresaId, dados.armazemId);
    if (!armazem) {
      return { success: false, error: 'Armazém não encontrado' };
    }
    if (armazem.empresaId !== dados.empresaId) {
      return { success: false, error: 'Armazém não pertence à empresa selecionada' };
    }
    const armazemIdCanonical = armazem.id;

    // Buscar stocks do armazém
    // ✅ Inclui tambem artigos com stock de sistema = 0 (ex: esgotados) —
    // caso contrario um inventario 'total' nunca conseguia capturar um
    // excedente fisico real encontrado para esses artigos.
    const todosStocks = await listarStockPorArmazem(armazemIdCanonical);
    const stocksDaEmpresa = todosStocks.filter(s => s.empresaId === dados.empresaId && s.quantidade >= 0);

    logger.info('[Inventarios] ðŸ“¦ Stocks encontrados:', stocksDaEmpresa.length);

    // Filtrar artigos se for inventário parcial
    let stocksParaInventariar = stocksDaEmpresa;
    if (dados.tipo === 'parcial' && dados.artigosIds && dados.artigosIds.length > 0) {
      stocksParaInventariar = stocksDaEmpresa.filter(s => dados.artigosIds!.includes(s.artigoId));
    }

    if (stocksParaInventariar.length === 0) {
      return { success: false, error: 'Nenhum artigo com stock encontrado no armazém selecionado' };
    }

    // Criar linhas do inventario apenas para produtos. Stock antigo de servicos e ignorado.
    const linhasComNulos = await Promise.all(
      stocksParaInventariar.map(async (stock): Promise<LinhaInventario | null> => {
        const artigo = await buscarArtigoPorId(stock.artigoId);
        if (!artigo || artigo.tipo === 'servico') {
          return null;
        }
        
        return {
          id: gerarId(),
          artigoId: stock.artigoId,
          artigoCodigo: artigo.codigo || '',
          artigoNome: artigo.nome || '',
          artigoCustoMedio: stock.custoMedio || 0,
          stockSistema: stock.quantidade,
          contagemFisica: null,
          diferenca: 0,
          valorDiferenca: 0,
          statusLinha: 'nao_contado',
        };
      })
    );
    const linhas: LinhaInventario[] = linhasComNulos.filter((linha): linha is LinhaInventario => Boolean(linha));

    if (linhas.length === 0) {
      return { success: false, error: 'Nenhum produto com stock encontrado no armazem selecionado' };
    }
    const agora = new Date().toISOString();
    const exercicio = await exerciciosEconomicos.validarExercicioAberto(
      dados.empresaId,
      dados.dataInventario,
      "inventario fisico",
    );
    const numero = await gerarNumero(dados.empresaId, exercicio.ano);

    const responsavel = dados.responsavelNome || dados.responsavel || dados.usuarioAuditoriaNome || dados.criadoPorNome || 'Sistema';
    const inventario: Inventario = {
      id: gerarId(),
      empresaId: dados.empresaId,
      exercicioEconomicoId: exercicio.id,
      anoExercicio: exercicio.ano,
      numero,
      armazemId: armazemIdCanonical,
      armazemCodigo: armazem.codigo,
      armazemNome: armazem.nome,
      tipo: dados.tipo,
      status: 'rascunho',
      dataInventario: dados.dataInventario,
      responsavel,
      responsavelId: dados.responsavelId || dados.usuarioAuditoriaId || dados.criadoPor,
      responsavelNome: responsavel,
      responsavelEmail: dados.responsavelEmail || dados.usuarioAuditoriaEmail || dados.criadoPorEmail,
      criadoPor: dados.criadoPor || dados.usuarioAuditoriaId,
      criadoPorNome: dados.criadoPorNome || dados.usuarioAuditoriaNome || responsavel,
      criadoPorEmail: dados.criadoPorEmail || dados.usuarioAuditoriaEmail,
      observacoes: dados.observacoes,
      linhas,
      ...calcularTotalizadores(linhas),
      criadoEm: agora,
      atualizadoEm: agora,
    };

    const chave = `inventario:${dados.empresaId}:${inventario.id}`;
    logger.info('[criarInventario] ðŸ’¾ Salvando com chave:', chave);
    logger.info('[criarInventario] ðŸ“‹ ID do inventário:', inventario.id);
    logger.info('[criarInventario] ðŸ¢ EmpresaId:', dados.empresaId);
    await kv.set(chave, inventario);
    logger.info('[criarInventario] âœ… Inventário salvo no KV');

    // logger.info('[Inventarios] âœ… Inventário criado:', numero);
    return { success: true, inventario };
  } catch (error) {
    logger.error('[Inventarios] âŒ Erro ao criar inventário:', error);
    return { success: false, error: String(error) };
  }
}

// Atualizar inventario
export async function atualizarInventario(
  id: string,
  dados: Partial<Inventario>
): Promise<{ success: boolean; inventario?: Inventario; error?: string }> {
  try {
    logger.info('[Inventarios] Atualizando inventario:', id);

    const inventario = await buscarInventarioPorId(id);
    if (!inventario) {
      return { success: false, error: 'Inventario nao encontrado' };
    }

    if (inventario.status === 'fechado' || inventario.status === 'cancelado') {
      return { success: false, error: 'Nao e possivel atualizar inventario fechado ou cancelado' };
    }

    const inventarioAtualizado: Inventario = {
      ...inventario,
      ...dados,
      atualizadoEm: new Date().toISOString(),
    };

    if (dados.linhas) {
      const totalizadores = calcularTotalizadores(inventarioAtualizado.linhas);
      Object.assign(inventarioAtualizado, totalizadores);
    }

    const chave = `inventario:${inventario.empresaId}:${inventario.id}`;
    await kv.set(chave, inventarioAtualizado);

    logger.info('[Inventarios] Inventario atualizado');
    return { success: true, inventario: inventarioAtualizado };
  } catch (error) {
    logger.error('[Inventarios] Erro ao atualizar inventario:', error);
    return { success: false, error: String(error) };
  }
}

// Atualizar linha do inventario
export async function atualizarLinhaInventario(
  inventarioId: string,
  linhaId: string,
  dados: Partial<LinhaInventario>
): Promise<{ success: boolean; inventario?: Inventario; error?: string }> {
  try {
    const inventario = await buscarInventarioPorId(inventarioId);
    if (!inventario) {
      return { success: false, error: 'Inventario nao encontrado' };
    }

    if (inventario.status !== 'em_contagem') {
      return { success: false, error: 'So e possivel editar contagens quando o inventario esta em contagem' };
    }

    const dadosNormalizados: Partial<LinhaInventario> = { ...dados };
    if ('contagemFisica' in dados) {
      const validacaoContagem = normalizarContagemFisica(dados.contagemFisica);
      if (!validacaoContagem.success) {
        return { success: false, error: validacaoContagem.error };
      }
      dadosNormalizados.contagemFisica = validacaoContagem.valor;
    }

    const linhaIndex = inventario.linhas.findIndex(l => l.id === linhaId);
    if (linhaIndex === -1) {
      return { success: false, error: 'Linha nao encontrada' };
    }

    const linhaAtualizada = {
      ...inventario.linhas[linhaIndex],
      ...dadosNormalizados,
    };

    if ('contagemFisica' in dadosNormalizados) {
      const contagemFisica = dadosNormalizados.contagemFisica;
      if (contagemFisica === null || contagemFisica === undefined) {
        linhaAtualizada.diferenca = 0;
        linhaAtualizada.valorDiferenca = 0;
        linhaAtualizada.statusLinha = 'nao_contado';
      } else {
        linhaAtualizada.diferenca = contagemFisica - linhaAtualizada.stockSistema;
        linhaAtualizada.valorDiferenca = linhaAtualizada.diferenca * linhaAtualizada.artigoCustoMedio;
        linhaAtualizada.statusLinha = 'contado';
      }
    }

    inventario.linhas[linhaIndex] = linhaAtualizada;

    const totalizadores = calcularTotalizadores(inventario.linhas);
    Object.assign(inventario, totalizadores);

    inventario.atualizadoEm = new Date().toISOString();

    const chave = `inventario:${inventario.empresaId}:${inventario.id}`;
    await kv.set(chave, inventario);

    return { success: true, inventario };
  } catch (error) {
    logger.error('[Inventarios] Erro ao atualizar linha:', error);
    return { success: false, error: String(error) };
  }
}

// Iniciar contagem (transição RASCUNHO â†’ EM_CONTAGEM)
export async function iniciarContagem(id: string): Promise<{ success: boolean; inventario?: Inventario; error?: string }> {
  try {
    const inventario = await buscarInventarioPorId(id);
    if (!inventario) {
      return { success: false, error: 'Inventário não encontrado' };
    }

    if (inventario.status !== 'rascunho') {
      return { success: false, error: 'Só é possível iniciar contagem em inventários com status RASCUNHO' };
    }

    const armazem = await resolverArmazemInventario(inventario.empresaId, inventario.armazemId);
    if (!armazem) {
      return { success: false, error: `Armazém do inventário ${inventario.numero} não encontrado` };
    }
    const armazemIdCanonical = armazem.id;

    const agora = new Date().toISOString();
    inventario.armazemId = armazemIdCanonical;
    inventario.armazemCodigo = armazem.codigo;
    inventario.armazemNome = armazem.nome;
    inventario.status = 'em_contagem';
    inventario.dataInicio = agora;
    inventario.atualizadoEm = agora;

    const chave = `inventario:${inventario.empresaId}:${inventario.id}`;
    await kv.set(chave, inventario);

    return { success: true, inventario };
  } catch (error) {
    return { success: false, error: String(error) };
  }
}

// Finalizar inventário (aplicar ajustes)
export async function finalizarInventario(id: string): Promise<{ success: boolean; error?: string }> {
  try {
    logger.info('[Inventarios] ðŸ Finalizando inventário:', id);

    const inventario = await buscarInventarioPorId(id);
    if (!inventario) {
      return { success: false, error: 'Inventário não encontrado' };
    }

    if (inventario.status === 'fechado') {
      return { success: false, error: 'Inventário já foi finalizado' };
    }

    if (inventario.status === 'cancelado') {
      return { success: false, error: 'Inventário está cancelado' };
    }

    // Só permite finalizar se estiver em contagem
    if (inventario.status !== 'em_contagem') {
      return { success: false, error: 'Só é possível finalizar inventários que estão em contagem' };
    }

    // ✅ Lock atomico (baseado na restricao de chave unica do KV) para evitar
    // que dois pedidos concorrentes (duplo clique, retry do cliente) passem
    // ambos pela verificacao de status acima antes de qualquer um escrever o
    // resultado, duplicando os movimentos de ajuste e o lancamento contabil.
    const chaveLock = `inventario_finalizando:${id}`;
    const lock = await kvAtomic.createIfAbsent(chaveLock, { iniciadoEm: new Date().toISOString() });
    if (!lock.created) {
      return { success: false, error: 'Este inventário já está a ser finalizado noutro pedido. Aguarde e tente novamente.' };
    }

    try {
      return await finalizarInventarioComLockAdquirido(inventario, id);
    } finally {
      await kvAtomic.deleteKey(chaveLock).catch(() => null);
    }
  } catch (error) {
    logger.error('[Inventarios] ❌ Erro ao finalizar inventário:', error);
    return { success: false, error: String(error) };
  }
}

async function finalizarInventarioComLockAdquirido(
  inventario: Inventario,
  id: string,
): Promise<{ success: boolean; error?: string }> {
  try {
    // Re-validar o status depois de adquirir o lock, para o caso de o estado
    // em memoria (lido antes do lock) estar desactualizado.
    const inventarioActual = await buscarInventarioPorId(id);
    if (!inventarioActual) {
      return { success: false, error: 'Inventário não encontrado' };
    }
    if (inventarioActual.status !== 'em_contagem') {
      return { success: false, error: 'Só é possível finalizar inventários que estão em contagem' };
    }
    inventario = inventarioActual;

    // Verificar se todas as linhas foram contadas
    const linhasNaoContadas = inventario.linhas.filter(l => l.statusLinha === 'nao_contado');
    if (linhasNaoContadas.length > 0) {
      return {
        success: false,
        error: `Existem ${linhasNaoContadas.length} artigo(s) não contado(s). Conte todos antes de finalizar.`
      };
    }

    const armazem = await resolverArmazemInventario(inventario.empresaId, inventario.armazemId);
    if (!armazem) {
      return { success: false, error: `Armazém do inventário ${inventario.numero} não encontrado` };
    }
    const armazemIdCanonical = armazem.id;

    const agora = new Date().toISOString();
    const exercicio = await exerciciosEconomicos.validarExercicioAberto(
      inventario.empresaId,
      inventario.dataInventario,
      "inventario fisico",
    );
    const dataMovimento = inventario.dataInventario || agora.split('T')[0];

    // Preparar todos os ajustes primeiro. Assim evitamos fechar metade do inventario se uma linha falhar.
    const ajustes: Array<{
      linha: LinhaInventario;
      contagemFisica: number;
      stockSistemaAtual: number;
      diferencaAplicada: number;
    }> = [];
    
    logger.info('[Inventarios] Linhas para validar:', inventario.linhas.length);

    for (const linha of inventario.linhas) {
      const validacaoContagem = normalizarContagemFisica(linha.contagemFisica);
      if (!validacaoContagem.success || validacaoContagem.valor === null) {
        return {
          success: false,
          error: `Contagem fisica obrigatoria para ${linha.artigoCodigo}. Informe a quantidade fisica antes de finalizar.`,
        };
      }
      const contagemFisica = validacaoContagem.valor;

      const artigo = await buscarArtigoPorId(linha.artigoId);
      if (!artigo) {
        return { success: false, error: `Artigo ${linha.artigoCodigo} nao encontrado` };
      }
      if (artigo.tipo === 'servico') {
        return { success: false, error: `O artigo ${linha.artigoCodigo} e um servico e nao pode entrar no inventario de stock` };
      }

      const stockAtual = await buscarStockArtigoArmazem(inventario.empresaId, linha.artigoId, armazemIdCanonical);
      const stockSistemaAtual = stockAtual?.quantidade || 0;
      const quantidadeReservada = stockAtual?.quantidadeReservada || 0;

      if (contagemFisica < quantidadeReservada) {
        return {
          success: false,
          error: `Nao e possivel finalizar o inventario para ${linha.artigoCodigo}: a contagem (${contagemFisica}) esta abaixo do stock reservado (${quantidadeReservada}).`,
        };
      }

      const diferencaAplicada = contagemFisica - stockSistemaAtual;
      if (diferencaAplicada !== 0) {
        ajustes.push({ linha, contagemFisica, stockSistemaAtual, diferencaAplicada });
      }
    }

    const movimentosCriados: string[] = [];

    try {
      for (const ajuste of ajustes) {
        const { linha, contagemFisica, stockSistemaAtual, diferencaAplicada } = ajuste;
        const loteAjuste = diferencaAplicada > 0 ? `INV-${inventario.numero}` : undefined;

        const resultadoMovimento = await movimentosStock.criarMovimento({
          empresaId: inventario.empresaId,
          artigoId: linha.artigoId,
          tipo: diferencaAplicada > 0 ? 'entrada' : 'saida',
          quantidade: Math.abs(diferencaAplicada),
          motivo: diferencaAplicada > 0 ? 'ajuste_positivo' : 'ajuste_negativo',
          armazemId: armazemIdCanonical,
          lote: loteAjuste,
          custoUnitario: linha.artigoCustoMedio || 0,
          documentoTipo: 'Inventario Fisico',
          documentoNumero: inventario.numero,
          observacoes:
            linha.motivoDiferenca ||
            `Ajuste por inventario fisico. Contagem: ${contagemFisica}, stock no sistema: ${stockSistemaAtual}, diferenca aplicada: ${diferencaAplicada}.`,
          responsavel: inventario.responsavel,
          dataMovimento,
          permitirConsumoExpirados: diferencaAplicada < 0,
        });

        if (!resultadoMovimento.success || !resultadoMovimento.data) {
          throw new Error(`Erro ao ajustar ${linha.artigoCodigo}: ${resultadoMovimento.error}`);
        }

        movimentosCriados.push(resultadoMovimento.data.id);

        if (diferencaAplicada > 0) {
          await registrarLoteAjusteInventario({
            empresaId: inventario.empresaId,
            artigoId: linha.artigoId,
            armazemId: armazemIdCanonical,
            inventarioNumero: inventario.numero,
            quantidade: diferencaAplicada,
            custoUnitario: linha.artigoCustoMedio || 0,
          });
        }

        logger.info(`[Inventarios] Ajuste reconciliado para ${linha.artigoCodigo}: ${diferencaAplicada > 0 ? '+' : ''}${diferencaAplicada}`);
      }
    } catch (error) {
      const errosRollback: string[] = [];
      for (const movimentoId of movimentosCriados.reverse()) {
        const rollback = await movimentosStock.deletarMovimento(movimentoId);
        if (!rollback.success) {
          errosRollback.push(`${movimentoId}: ${rollback.error}`);
        }
      }

      const detalheRollback = errosRollback.length > 0
        ? ` Rollback incompleto: ${errosRollback.join('; ')}`
        : '';

      return {
        success: false,
        error: `${error instanceof Error ? error.message : String(error)}.${detalheRollback}`,
      };
    }
    // Atualizar status do inventario
    inventario.armazemId = armazemIdCanonical;
    inventario.armazemCodigo = armazem.codigo;
    inventario.armazemNome = armazem.nome;
    inventario.exercicioEconomicoId = exercicio.id;
    inventario.anoExercicio = exercicio.ano;
    inventario.status = 'fechado';
    inventario.dataFinalizacao = agora;
    inventario.atualizadoEm = agora;

    const chave = `inventario:${inventario.empresaId}:${inventario.id}`;
    await kv.set(chave, inventario);

    logger.info('[Inventarios] âœ… Inventário finalizado com sucesso:', inventario.numero);
    return { success: true };
  } catch (error) {
    logger.error('[Inventarios] âŒ Erro ao finalizar inventário:', error);
    return { success: false, error: String(error) };
  }
}

// Cancelar inventário
export async function cancelarInventario(id: string): Promise<{ success: boolean; error?: string }> {
  try {
    const inventario = await buscarInventarioPorId(id);
    if (!inventario) {
      return { success: false, error: 'Inventário não encontrado' };
    }

    if (inventario.status === 'fechado') {
      return { success: false, error: 'Não é possível cancelar inventário já finalizado' };
    }

    inventario.status = 'cancelado';
    inventario.atualizadoEm = new Date().toISOString();

    const chave = `inventario:${inventario.empresaId}:${inventario.id}`;
    await kv.set(chave, inventario);

    logger.info('[Inventarios] âœ… Inventário cancelado:', inventario.numero);
    return { success: true };
  } catch (error) {
    logger.error('[Inventarios] âŒ Erro ao cancelar inventário:', error);
    return { success: false, error: String(error) };
  }
}

// Listar inventários
export async function listarInventarios(
  empresaId: string,
  filtros?: {
    armazemId?: string;
    status?: string;
    dataInicio?: string;
    dataFim?: string;
  }
): Promise<Inventario[]> {
  try {
    const prefix = `inventario:${empresaId}:`;
    const resultados = await kv.getByPrefix(prefix);
    
    let inventarios = resultados
      .filter((inv: any) => inv && inv.id) as Inventario[]; // kv.getByPrefix já devolve os valores

    // Aplicar filtros
    if (filtros) {
      if (filtros.armazemId) {
        inventarios = inventarios.filter(inv => inv.armazemId === filtros.armazemId);
      }
      if (filtros.status) {
        inventarios = inventarios.filter(inv => inv.status === filtros.status);
      }
      if (filtros.dataInicio) {
        inventarios = inventarios.filter(inv => inv.dataInventario >= filtros.dataInicio!);
      }
      if (filtros.dataFim) {
        inventarios = inventarios.filter(inv => inv.dataInventario <= filtros.dataFim!);
      }
    }

    // Ordenar por data (mais recentes primeiro)
    inventarios.sort((a, b) => 
      new Date(b.dataInventario).getTime() - new Date(a.dataInventario).getTime()
    );

    return inventarios;
  } catch (error) {
    logger.error('[Inventarios] âŒ Erro ao listar inventários:', error);
    return [];
  }
}

// Buscar inventário por ID
export async function buscarInventarioPorId(id: string): Promise<Inventario | null> {
  try {
    logger.info('[buscarInventarioPorId] ðŸ” Buscando inventário com ID:', id);
    const inventarios = await kv.getByPrefix('inventario:');
    logger.info('[buscarInventarioPorId] ðŸ“¦ Total de inventários encontrados:', inventarios.length);
    
    const inventario = inventarios
      .filter((inv: any) => inv && inv.id)
      .find((inv: Inventario) => inv.id === id);
    
    logger.info('[buscarInventarioPorId] âœ… Inventário encontrado:', !!inventario);
    if (inventario) {
      logger.info('[buscarInventarioPorId] ðŸ“‹ Dados:', { id: inventario.id, numero: inventario.numero, status: inventario.status });
    }
    
    return inventario || null;
  } catch (error) {
    logger.error('[buscarInventarioPorId] âŒ Erro ao buscar inventário:', error);
    return null;
  }
}

// Excluir inventário (apenas se não finalizado)
export async function excluirInventario(id: string): Promise<{ success: boolean; error?: string }> {
  try {
    const inventario = await buscarInventarioPorId(id);
    if (!inventario) {
      return { success: false, error: 'Inventário não encontrado' };
    }

    if (inventario.status === 'fechado') {
      return { success: false, error: 'Não é possível excluir inventário finalizado' };
    }

    const chave = `inventario:${inventario.empresaId}:${inventario.id}`;
    await kv.del(chave);

    logger.info('[Inventarios] âœ… Inventário excluído:', inventario.numero);
    return { success: true };
  } catch (error) {
    logger.error('[Inventarios] âŒ Erro ao excluir inventário:', error);
    return { success: false, error: String(error) };
  }
}
