import { Hono } from "hono";
import { cors } from "hono/cors";
import { logger } from "hono/logger";
import { createClient } from "../../src/compat/supabase.js";
import * as kv from "./kv_store.tsx";
import * as kvAtomic from "./kv_atomic.tsx";
import * as empresasModule from "./empresas.tsx";
import * as modulos from "./modulos.tsx";
import * as pagamentos from "./pagamentos.tsx";
import * as usuarios from "./usuarios.tsx";
import * as revendedores from "./revendedores.tsx";
import * as fornecedores from "./fornecedores.tsx";
import * as clientes from "./clientes.tsx";
import * as cotacoes from "./cotacoes.tsx";
import * as facturas from "./facturas.tsx";
import * as recibos from "./recibos.tsx";
import * as notas from "./notas.tsx";
import * as artigos from "./artigos.tsx";
import * as uploads from "./uploads.tsx";
import * as movimentosStock from "./movimentos-stock.tsx";
import * as armazens from "./armazens.tsx";
import * as stockArmazem from "./stock-armazem.tsx";
import * as stockLotes from "./stock-lotes.tsx";
import * as relatorioValidade from "./relatorio-validade.tsx";
import * as posValidadeConfig from "./pos-validade-config.tsx";
import * as transferencias from "./transferencias.tsx";
import * as documentosStock from "./documentos-stock.tsx";
import * as inventariosModule from "./inventarios.tsx";
import * as vendasDinheiro from "./vendas-dinheiro.tsx";
import * as adiantamentos from "./adiantamentos.tsx";
import * as permissoes from "./permissoes.tsx";
import * as auditoria from "./auditoria.tsx";
import * as authorization from "./authorization.tsx";
import { aplicarTotaisFiscais } from "./validacao-fiscal.tsx";
import saftRouter from "./saft.tsx";
import * as saftSeed from "./saft-seed-data.tsx";
import rascunhosRouter from "./rascunhos.tsx";
import * as compras from "./compras.tsx";
import * as contabilidade from "./contabilidade.tsx";
import * as folhaPagamentoRH from "./folha-pagamento.tsx";
import * as colaboradoresRH from "./colaboradores.tsx";
import * as subscricoes from "./subscricoes.tsx";
import * as interempresa from "./interempresa.tsx";
import * as mpesa from "./mpesa.tsx";
import * as tonlineConfig from "./tonline-config.tsx";
import * as exerciciosEconomicos from "./exercicios-economicos.tsx";
import * as integracaoFiscal from "./integracao-fiscal.tsx";
import {
  requireAnyPermission,
  requirePermission,
  verificarEscopoEmpresaRequest,
  type PermissionKey,
} from "./permission-middleware.tsx";
import { containsNormalizedText } from './text-normalization.tsx';
import {
  removerLancamentosContabeisRascunhoDoDocumento,
  verificarSemLancamentoContabilDefinitivo,
} from './integridade-documentos.tsx';
import {
  decodificarPayloadJwt,
  isEmpresaTonlineId,
  isUsuarioSuperAdminTonline,
  obterUsuarioAutenticadoRequest,
  validarSuperAdminTonlineRequest,
  validarAcessoEmpresaRequest,
  validarGestaoUsuariosRequest,
  validarAcessoUsuarioAlvoRequest,
  bloquearEscaladaPrivilegioUsuario,
  gerarSenhaTemporaria,
  RESERVA_CADASTRO_TTL_MS,
  RESERVA_RENOVACAO_TTL_MS,
  reservarChavesPagamento,
  libertarReservasPagamento,
  marcarReservasPagamento,
  criarSnapshotPagamento,
} from './admin-shared-helpers.tsx';
const app = new Hono();

function lerPaginacaoLista(c: any) {
  const limitParam = Number(c.req.query("limit") || c.req.query("limite") || 0);
  const offsetParam = Number(c.req.query("offset") || 0);
  const limit = Number.isFinite(limitParam) && limitParam > 0 ? Math.min(limitParam, 100) : 0;
  const offset = Number.isFinite(offsetParam) && offsetParam > 0 ? offsetParam : 0;

  return { limit, offset };
}

function responderListaPaginada(c: any, lista: any[]) {
  const { limit, offset } = lerPaginacaoLista(c);
  const data = limit > 0 ? lista.slice(offset, offset + limit) : lista;

  return c.json({
    success: true,
    data,
    pagination: limit > 0
      ? {
          limit,
          offset,
          total: lista.length,
          hasMore: offset + limit < lista.length,
        }
      : undefined,
  });
}

// ========== MIDDLEWARE DE TRATAMENTO GLOBAL DE ERROS ==========
// CRÃTICO: Captura TODOS os erros antes que poluam o stream HTTP
app.onError((err, c) => {
  // NUNCA logar no console em produção - polui o stream HTTP
  // console.error('[ERROR]', err);

  // Sempre retornar JSON limpo, mesmo em caso de erro crítico
  return c.json(
    {
      success: false,
      error: err.message || 'Erro interno do servidor',
      timestamp: new Date().toISOString(),
    },
    500
  );
});

// ========== HANDLER 404 - ROTA NÃƒO ENCONTRADA ==========
// CRÃTICO: Garantir que 404 retorna JSON, NÃƒO HTML
app.notFound((c) => {
  return c.json(
    {
      success: false,
      error: 'Rota não encontrada',
      path: c.req.path,
      method: c.req.method,
    },
    404
  );
});

// ========== MIDDLEWARE CORS ==========
// Configurar CORS para aceitar requisiçÃµes do frontend
app.use('*', cors({
  origin: '*',
  allowMethods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
  allowHeaders: ['Content-Type', 'Authorization', 'X-User-Token'], // âœ… FIX: Adicionar X-User-Token
  exposeHeaders: ['Content-Length', 'Content-Type'],
  maxAge: 86400,
  credentials: false,
}));

app.use('/make-server-7249dcd9/*', async (c, next) => {
  const debugActivo = Deno.env.get('ENABLE_DEBUG_ENDPOINTS') === 'true';
  if (!debugActivo && c.req.path.includes('/debug/')) {
    return c.json({ success: false, error: 'Rota não encontrada' }, 404);
  }

  return await next();
});

async function lerBodyJsonSeguro(c: any, fallback: any = {}) {
  // ✅ NAO sobrescrever c.req.bodyCache (estrutura interna do Hono, indexada
  // por metodo — 'json'/'text'/'arrayBuffer'/... — cada valor uma Promise).
  // Uma versao anterior deste helper substituia bodyCache pelo proprio corpo
  // ja resolvido (ex: {nome, empresaId, ...}); qualquer chamada posterior a
  // c.req.json() feita por um handler (sem passar por este helper) caia no
  // fallback interno do Hono `bodyCache[anyCachedKey].then(...)`, onde
  // anyCachedKey passava a ser um campo qualquer do corpo (ex: "nome") cujo
  // valor nao e uma Promise — daí o erro "bodyCache[anyCachedKey].then is
  // not a function". O proprio Hono ja cacheia o resultado de c.req.json()
  // por pedido, por isso basta chamar normalmente; chamadas repetidas
  // (noutros middlewares ou no handler final) reaproveitam o mesmo cache.
  try {
    return await c.req.json();
  } catch (_error) {
    return fallback;
  }
}

type RecursoFiscal = 'cotacao' | 'factura' | 'recibo' | 'nota' | 'vd' | 'adiantamento' | 'saft';

function identificarRecursoFiscal(path: string): RecursoFiscal | null {
  if (path.includes('/cotacoes')) return 'cotacao';
  if (path.includes('/facturas-recibo') || path.includes('/facturas')) return 'factura';
  if (path.includes('/recibos')) return 'recibo';
  if (path.includes('/notas')) return 'nota';
  if (path.includes('/vendas-dinheiro')) return 'vd';
  if (path.includes('/adiantamentos')) return 'adiantamento';
  if (path.includes('/saft')) return 'saft';
  return null;
}

async function carregarDocumentoFiscalDaRota(recurso: RecursoFiscal, id: string) {
  if (!id || id === 'proximo-numero') return null;
  if (recurso === 'cotacao') return await cotacoes.buscarCotacaoPorId(id);
  if (recurso === 'factura') return await facturas.buscarFacturaPorId(id);
  if (recurso === 'recibo') return await recibos.buscarReciboPorId(id);
  if (recurso === 'nota') {
    const resultado = await notas.getNotaById(id);
    return resultado?.data || resultado;
  }
  if (recurso === 'vd') {
    const resultado = await vendasDinheiro.getVDById(id);
    return resultado?.data || resultado;
  }
  if (recurso === 'adiantamento') {
    const resultado = await adiantamentos.getAdiantamentoById(id);
    return resultado?.data || resultado;
  }
  return null;
}

async function resolverSegurancaFiscal(c: any, recurso: RecursoFiscal) {
  const path = c.req.path;
  const metodo = c.req.method.toUpperCase();
  let body: any = {};

  if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(metodo)) {
    body = await lerBodyJsonSeguro(c, {});
  }

  const empresaNaRota = path.match(/\/empresas\/([^/]+)/)?.[1];
  const dashboardEmpresa = path.match(/\/dashboard\/estatisticas\/([^/]+)/)?.[1];
  const recursoMatch = path.match(new RegExp(`/${
    recurso === 'vd' ? 'vendas-dinheiro' : recurso === 'adiantamento' ? 'adiantamentos' : recurso === 'nota' ? 'notas' : recurso === 'recibo' ? 'recibos' : recurso === 'factura' ? 'facturas(?:-recibo)?' : recurso === 'cotacao' ? 'cotacoes' : 'saft'
  }/([^/]+)`));

  let documento: any = null;
  if (recursoMatch?.[1] && !['proximo-numero', 'dashboard', 'validar', 'exportar', 'historico', 'seed', 'clean-seed'].includes(recursoMatch[1])) {
    documento = await carregarDocumentoFiscalDaRota(recurso, decodeURIComponent(recursoMatch[1]));
  }

  const saftEmpresaNaRota = recurso === 'saft'
    ? path.match(/\/saft\/saft\/([^/]+)/)?.[1]
    : undefined;
  const historicoId = recurso === 'saft'
    ? decodeURIComponent(path.match(/\/saft\/historico\/(.+)\/download$/)?.[1] || '')
    : '';
  const historicoEmpresa = recurso === 'saft'
    ? historicoId.match(/^saft-historico:([^:]+):/)?.[1]
    : undefined;
  const empresaId = String(
    empresaNaRota ||
    dashboardEmpresa ||
    saftEmpresaNaRota ||
    body?.empresaId ||
    documento?.empresaId ||
    historicoEmpresa ||
    '',
  ).trim();

  let base: string;
  if (path.endsWith('/registrar-adiantamento')) {
    // ✅ /cotacoes/:id/registrar-adiantamento e /facturas/:id/registrar-adiantamento
    // ligam um adiantamento ja existente a uma cotacao/proforma — a accao que
    // realmente importa e se o utilizador pode gerir adiantamentos, nao se pode
    // editar o conteudo da cotacao/factura em si (permissoes normalmente
    // separadas: quem lanca adiantamentos nem sempre pode editar facturacao).
    base = 'vendas.adiantamento';
  } else if (recurso === 'nota') {
    const tipo = String(body?.tipo || documento?.tipo || '').toLowerCase();
    base = tipo === 'debito' ? 'faturacao.nota_debito' : tipo === 'credito' ? 'faturacao.nota_credito' : 'faturacao.nota';
  } else if (recurso === 'adiantamento') {
    base = 'vendas.adiantamento';
  } else if (recurso === 'saft') {
    base = 'faturacao.factura';
  } else if (recurso === 'factura') {
    // ✅ Factura, Factura-Recibo e Factura Proforma sao guardadas na mesma
    // tabela (tipoDocumento diferencia-as), mas tem permissoes proprias e
    // independentes — ex: um utilizador pode criar Proformas sem poder criar
    // Facturas reais. Ver PermissoesFaturacao em tipos-permissoes-modulo.ts.
    if (path.includes('/facturas-recibo')) {
      base = 'faturacao.factura_recibo';
    } else {
      const tipoFactura = String(body?.tipoDocumento || documento?.tipoDocumento || 'factura')
        .trim().toLowerCase().replace(/-/g, '_');
      base = (tipoFactura === 'factura_proforma' || tipoFactura === 'proforma')
        ? 'faturacao.factura_proforma'
        : 'faturacao.factura';
    }
  } else {
    base = `faturacao.${recurso}`;
  }

  let accoes: string[] = ['visualizar'];
  if (metodo === 'GET' && path.endsWith('/pode-editar')) accoes = ['editar'];
  if (metodo === 'GET' && path.endsWith('/pode-eliminar')) accoes = ['deletar'];
  if (metodo === 'DELETE') accoes = ['deletar'];
  if (metodo === 'PUT') accoes = ['editar'];
  if (metodo === 'PATCH') accoes = ['editar'];
  if (metodo === 'POST') {
    if (path.endsWith('/anular')) accoes = ['anular', 'editar'];
    // ✅ "Registar um adiantamento" liga um adiantamento JA CRIADO a uma
    // cotacao/factura — mais proximo de "criar" uma associacao nova do que
    // de "editar" algo existente. Aceitar qualquer uma das duas evita negar
    // utilizadores que so tem permissao de criar adiantamentos configurada
    // (o caso mais comum), sem exigir tambem editar.
    else if (path.endsWith('/registrar-adiantamento')) accoes = ['criar', 'editar'];
    else if (path.includes('/aplicar') || path.includes('/registrar-')) accoes = ['editar'];
    else if (path.endsWith('/historico') || path.endsWith('/validar') || path.endsWith('/exportar')) accoes = ['visualizar'];
    else accoes = ['criar'];
  }
  if (recurso === 'cotacao' && path.endsWith('/estado')) {
    accoes = ['aprovar', 'rejeitar', 'editar'];
  }
  if (recurso === 'nota' && base === 'faturacao.nota') {
    // ✅ Usa TODAS as accoes (ex: ['anular','editar']), não só accoes[0] — caso
    // contrário um utilizador só com a permissão genérica 'editar' (sem 'anular')
    // ficava bloqueado de anular uma nota nesta rota, ao contrário do que acontece
    // nas rotas equivalentes de factura/vd/adiantamento/cotacao.
    return {
      empresaId,
      permissions: accoes.flatMap((sufixo) => [
        `faturacao.nota_credito.${sufixo}`,
        `faturacao.nota_debito.${sufixo}`,
      ]) as PermissionKey[],
    };
  }

  return {
    empresaId,
    permissions: accoes.map((acao) => `${base}.${acao}` as PermissionKey),
  };
}

app.use('/make-server-7249dcd9/*', async (c, next) => {
  // ✅ Rota de manutenção do cron (autenticada pelo seu próprio segredo
  // X-Vd-Pendencias-Secret, ver rota abaixo) — não é um documento VD
  // individual, por isso não deve exigir X-User-Token como as rotas
  // /vendas-dinheiro/:id.
  if (c.req.path.endsWith('/vendas-dinheiro/processar-pendencias')) {
    return await next();
  }

  const recurso = identificarRecursoFiscal(c.req.path);
  if (!recurso) return await next();

  const { empresaId, permissions } = await resolverSegurancaFiscal(c, recurso);
  return await requireAnyPermission(...permissions)(c, async () => {
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    await next();
  });
});


// ========== MIDDLEWARE DE VALIDAÃ‡ÃƒO DE ACESSO ==========
/**
 * Middleware para validar acesso a módulos baseado na subscrição
 * Uso: app.get("/rota", validarAcessoMiddleware("moduloId"), handler)
 */
function validarAcessoMiddleware(moduloId: string) {
  return async (c: any, next: any) => {
    // Resolver empresaId sem confundir IDs de recursos (ex: artigoId) com a empresa.
    let empresaId = c.req.query("empresaId") || c.req.param("empresaId");

    // Se não encontrou na URL, tentar pegar do body (para POSTs/PUTs/PATCHes)
    // ✅ Usa lerBodyJsonSeguro: o Hono já cacheia o resultado de c.req.json()
    // por pedido, por isso um handler que leia o body de novo mais tarde
    // (ex: `await c.req.json()` directo) reaproveita o mesmo valor sem
    // reler o stream nem corromper o cache interno do Hono.
    if (!empresaId) {
      const body = await lerBodyJsonSeguro(c, {});
      empresaId = body?.empresaId;
    }

    // Usar `:id` como empresaId apenas em rotas realmente escopadas por empresa.
    if (!empresaId && c.req.path.startsWith("/make-server-7249dcd9/empresas/")) {
      empresaId = c.req.param("id");
    }

    if (!empresaId) {
      return c.json({
        success: false,
        error: "ID da empresa não fornecido",
      }, 400);
    }

    // Empresa Tonline sempre tem acesso total (bypass)
    if (empresaId === "tonline_01") {
      return await next();
    }

    // Validar acesso ao módulo
    const validacao = await subscricoes.validarAcessoModulo(empresaId, moduloId);

    if (!validacao.permitido) {
      // Se não tem subscrição, permitir acesso (empresa em migração ou nova)
      if (validacao.motivo?.includes("não possui subscrição")) {
        console.warn(`[MIDDLEWARE] âš ï¸ Empresa sem subscrição, permitindo acesso temporário - Empresa: ${empresaId}`);
        return await next();
      }

      console.warn(`[MIDDLEWARE] âŒ Acesso negado - Empresa: ${empresaId}, Módulo: ${moduloId}`);
      console.warn(`[MIDDLEWARE] Motivo: ${validacao.motivo}`);

      return c.json({
        success: false,
        error: validacao.motivo,
        bloqueado: true,
        empresaId,
        moduloId,
        subscricao: validacao.subscricao ? {
          estado: validacao.subscricao.estado,
          planoId: validacao.subscricao.planoId,
          diasGracePeriod: validacao.subscricao.diasGracePeriod,
        } : null,
      }, 403); // 403 Forbidden
    }

    // Acesso permitido (pode ter aviso de grace period)
    if (validacao.motivo && validacao.motivo.includes("âš ï¸")) {
      console.warn(`[MIDDLEWARE] âš ï¸ ${validacao.motivo}`);
    }

    // Adicionar info de subscrição no contexto para uso posterior
    c.set("subscricao", validacao.subscricao);

    return await next();
  };
}

// ========== INICIALIZAÃ‡ÃƒO DO SISTEMA ==========
// Cadastrar APENAS Tonline e criar super admin
/**
 * Inicializar sistema com APENAS a empresa Tonline e Super Admin
 *
 * FLUXO DE AUTENTICAÃ‡ÃƒO:
 * 1. Sistema inicializa com Tonline (dona do sistema) e Super Admin
 * 2. Super Admin faz login: admin@tonline.co.mz / admin123
 * 3. Super Admin cadastra empresas clientes através do painel
 * 4. Cada empresa cliente terá seus próprios usuários cadastrados
 * 5. Usuários das empresas fazem login com suas credenciais
 *
 * NÃƒO HÃ CONTAS DEMO - APENAS CONTAS CADASTRADAS
 */
async function inicializarSistema() {
  try {
    console.log("ðŸš€ [Sistema] Verificando inicialização...");

    // Verificar se o sistema já foi inicializado
    const jaInicializado = await kv.get("sistema:inicializado_v3");
    if (jaInicializado) {
      console.log("âœ… [Sistema] Sistema já foi inicializado anteriormente. Pulando inicialização.");
      return;
    }

    console.log("âš ï¸ [Sistema] Sistema não inicializado. Criando Tonline...");

    const supabase = createClient(
      Deno.env.get("SUPABASE_URL") ?? "",
      Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? ""
    );

    console.log("ðŸ”§ [Sistema] Iniciando configuração do sistema...");

    // ========== 1. CADASTRAR TONLINE COMO EMPRESA ==========
    console.log("ðŸ“‹ [Sistema] Cadastrando Tonline como empresa...");

    const tonlineId = "tonline_01"; // âœ… ID simplificado sem prefixo
    const tonlineEmpresa = {
      id: tonlineId,
      // Identificação
      nomeEmpresa: "Tonline, Lda",
      nomeComercial: "Tonline",
      nuit: "400000000", // âœ… CORRIGIDO: Era "nif", agora é "nuit"

      // Contacto
      email: "geral@tonline.co.mz",
      telefone: "+258 84 000 0000",
      telemovel: "",
      fax: "",
      website: "www.tonline.co.mz",

      // Morada
      endereco: "Av. Marginal, 1000",
      cidade: "Maputo",
      provincia: "Maputo",
      codigoPostal: "",
      pais: "Moçambique",

      // Dados Fiscais
      regimeIva: "Regime Geral",
      actividadePrincipal: "Software ERP",
      cae: "",

      // ConfiguraçÃµes Financeiras
      moedaPadrao: "MZN",
      anoFiscal: new Date().getFullYear().toString(),
      metodoInventario: "FIFO",

      // Dados Bancários
      bancos: [],

      // ConfiguraçÃµes do Sistema
      logotipo: "",
      numeroSerieInicial: "1",
      formatoDocumentos: "FAT{YYYY}{MM}{NNNN}",

      // Controle Multi-Tenant
      status: "ativa",
      paymentStatus: "em-dia",
      plano: "Super Admin",
      taxaInscricao: 0,
      valorAvenca: 0,
      proximoPagamento: new Date(2099, 11, 31).toISOString(), // Nunca expira
      diasEmAtraso: 0,

      // Auditoria
      dataCadastro: new Date().toISOString(),
      dataUltimaAtualizacao: new Date().toISOString(),
      ultimoAcesso: new Date().toISOString(),
      criadoPor: "Sistema",
    };

    await kv.set(`empresa:${tonlineId}`, tonlineEmpresa);
    console.log(`âœ… [Sistema] Tonline cadastrada como empresa com ID: ${tonlineId}`);

    // ========== 2. CRIAR SUPER ADMIN DA TONLINE ==========
    console.log("ðŸ‘¤ [Sistema] Criando Super Admin...");

    // PRIMEIRO: Tentar deletar usuário admin existente (se existir)
    try {
      const { data: existingUsers } = await supabase.auth.admin.listUsers();
      const existingAdmin = existingUsers?.users?.find(u => u.email === "admin@tonline.co.mz");

      if (existingAdmin) {
        console.log("âš ï¸  [Sistema] Usuário admin já existe. Deletando...");
        await supabase.auth.admin.deleteUser(existingAdmin.id);
        console.log("âœ… [Sistema] Usuário admin antigo deletado!");

        // Aguardar 500ms para garantir que foi deletado
        await new Promise(resolve => setTimeout(resolve, 500));
      }
    } catch (deleteError: any) {
      // console.log("âš ï¸  [Sistema] Erro ao deletar usuário admin antigo (pode não existir):", deleteError.message);
    }

    // SEGUNDO: Criar novo usuário admin
    const { data: adminAuth, error: adminError } = await supabase.auth.admin.createUser({
      email: "admin@tonline.co.mz",
      password: "admin123",
      user_metadata: {
        empresa_id: tonlineId,
        tipo: "admin",
        nome_empresa: "Tonline, Lda",
        nivel: "super_admin",
      },
      email_confirm: true,
    });

    if (adminError) {
      console.error("âŒ [Sistema] Erro ao criar Super Admin:", adminError);
      throw new Error(`Falha ao criar Super Admin: ${adminError.message}`);
    } else {
      console.log("âœ… [Sistema] Super Admin criado no Supabase Auth!");

      // Criar registro do usuário no nosso sistema (KV)
      const adminId = adminAuth.user.id;
      await kv.set(`usuario:${adminId}`, {
        id: adminId,
        authUserId: adminId, // âœ… CORREÃ‡ÃƒO: Adicionar authUserId
        email: "admin@tonline.co.mz",
        nome: "Administrador Tonline",
        empresaId: tonlineId,
        nivel: "super_admin",
        modulosPermitidos: [],
        ativo: true,
        dataCriacao: new Date().toISOString(),
        permissoes: {}, // âœ… Adicionar campo de permissÃµes
      });
      await kv.set(`usuario:email:admin@tonline.co.mz`, adminId);
      console.log(`âœ… [Sistema] Super Admin criado no KV com ID: ${adminId}`);
    }

    // Marcar sistema como inicializado (v3 - versão limpa)
    await kv.set("sistema:inicializado_v3", "true");
    console.log("âœ… [Sistema] Sistema marcado como inicializado (v3)");

    // console.log("");
    // console.log("========================================");
    // console.log("ðŸŽ‰ SISTEMA INICIALIZADO COM SUCESSO!");
    // console.log("========================================");
    // console.log("");
    // console.log("ðŸ‘¥ CREDENCIAIS DE ACESSO:");
    // console.log("");
    // console.log("ðŸ”µ SUPER ADMIN (Tonline):");
    // console.log("   Email: admin@tonline.co.mz");
    // console.log("   Senha: admin123");
    // console.log("");
    // console.log("========================================");

  } catch (error) {
    // console.error("âŒ [Sistema] Erro na inicialização:", error);
  }
}

// âš ï¸ INICIALIZAÃ‡ÃƒO AUTOMÃTICA REMOVIDA
// A função inicializarSistema() só é chamada manualmente via rota /reinicializar
// Isso evita perda de dados quando o servidor reinicia
// console.log("ðŸš€ [Sistema] Servidor iniciado. Os dados existentes foram preservados.");
// console.log("ðŸ’¡ [Sistema] Para criar o usuário admin inicial, use a rota /reinicializar");

// Enable CORS for all routes and methods
app.use(
  "/*",
  cors({
    origin: "*",
    allowHeaders: ["Content-Type", "Authorization", "X-User-Token"], // âœ… FIX: Adicionar X-User-Token
    allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
    exposeHeaders: ["Content-Length"],
    maxAge: 600,
  }),
);


async function lerCorpoAuditoria(c: any): Promise<any | undefined> {
  try {
    const contentType = c.req.header('content-type') || '';
    if (!contentType.toLowerCase().includes('application/json')) return undefined;
    return await c.req.raw.clone().json();
  } catch (_error) {
    return undefined;
  }
}

async function obterUsuarioAuditoriaRequest(c: any, corpo: any) {
  const tokenPayload = decodificarPayloadJwt(c.req.header('X-User-Token'));
  const id = tokenPayload?.sub || corpo?.usuarioAuditoriaId || corpo?.usuarioId || corpo?.usuario?.id || corpo?.usuario?.authUserId || corpo?.criadoPor || corpo?.atualizadoPor || corpo?.desativadoPor || corpo?.responsavelId;
  const empresaId = corpo?.empresaId || corpo?.dadosUsuario?.empresaId || c.req.param('empresaId') || c.req.param('id');
  const usuario = await auditoria.buscarUsuarioAuditoria(id, empresaId).catch(() => null);
  return {
    id: usuario?.id || id || 'sistema',
    nome: usuario?.nome || corpo?.usuarioAuditoriaNome || corpo?.usuarioNome || corpo?.usuario?.nome || corpo?.criadoPorNome || corpo?.atualizadoPorNome || corpo?.desativadoPorNome || '',
    email: usuario?.email || tokenPayload?.email || corpo?.usuarioAuditoriaEmail || corpo?.usuarioEmail || corpo?.usuario?.email || corpo?.criadoPorEmail || corpo?.atualizadoPorEmail || corpo?.desativadoPorEmail || '',
  };
}

async function preencherUsuarioDocumento(c: any, corpo: any, tipo: 'criar' | 'editar' = 'criar') {
  const usuario = await obterUsuarioAuditoriaRequest(c, corpo || {});
  const idRaw = String(usuario?.id || corpo?.usuarioAuditoriaId || corpo?.criadoPorId || corpo?.criadoPor || '').trim();
  const nomeRaw = String(usuario?.nome || corpo?.usuarioAuditoriaNome || corpo?.criadoPorNome || corpo?.usuarioNome || '').trim();
  const id = idRaw.toLowerCase() === 'sistema' ? '' : idRaw;
  const nome = nomeRaw.toLowerCase() === 'sistema' ? '' : nomeRaw;
  const email = String(usuario?.email || corpo?.usuarioAuditoriaEmail || corpo?.criadoPorEmail || corpo?.usuarioEmail || '').trim();

  corpo.usuarioAuditoriaId = id || corpo?.usuarioAuditoriaId || '';
  corpo.usuarioAuditoriaNome = nome || corpo?.usuarioAuditoriaNome || '';
  corpo.usuarioAuditoriaEmail = email || corpo?.usuarioAuditoriaEmail || '';

  if (tipo === 'editar') {
    corpo.atualizadoPor = id || nome || email || corpo?.atualizadoPor || '';
    corpo.atualizadoPorNome = nome || corpo?.atualizadoPorNome || '';
    corpo.atualizadoPorEmail = email || corpo?.atualizadoPorEmail || '';
    corpo.editadoPor = id || nome || email || corpo?.editadoPor || '';
    corpo.editadoPorNome = nome || corpo?.editadoPorNome || '';
    corpo.editadoPorEmail = email || corpo?.editadoPorEmail || '';
    return corpo;
  }

  corpo.criadoPor = nome || id || email || corpo?.criadoPor || '';
  corpo.criadoPorId = id || corpo?.criadoPorId || '';
  corpo.criadoPorNome = nome || corpo?.criadoPorNome || '';
  corpo.criadoPorEmail = email || corpo?.criadoPorEmail || '';
  return corpo;
}

const normalizarReferenciaDocumento = (valor: unknown) =>
  String(valor || '')
    .trim()
    .replace(/\s+/g, ' ')
    .toLowerCase();

function facturaEhDocumentoFiscalConvertido(factura: any) {
  const tipo = String(factura?.tipoDocumento || 'factura').trim().toLowerCase().replace(/-/g, '_');
  return tipo === 'factura' || tipo === 'factura_recibo';
}

async function localizarCotacaoOrigemFactura(factura: any) {
  const cotacaoId = String(factura?.cotacaoId || '').trim();
  if (cotacaoId) {
    const cotacao = await cotacoes.buscarCotacaoPorId(cotacaoId).catch(() => null);
    if (cotacao) return cotacao;
  }

  const referencia = normalizarReferenciaDocumento(factura?.cotacaoReferencia);
  if (!referencia || !factura?.empresaId) return null;

  const cotacoesEmpresa = await cotacoes.listarCotacoesPorEmpresa(factura.empresaId);
  return cotacoesEmpresa.find((cotacao: any) =>
    normalizarReferenciaDocumento(cotacao?.numeroDocumento) === referencia
  ) || null;
}

async function reverterCotacaoOrigemSeLivre(factura: any) {
  // ✅ A factura já foi eliminada quando isto corre — uma falha aqui nunca pode
  // fazer a rota de eliminação reportar erro ao cliente (a eliminação já
  // aconteceu). Falha é registada como pendência em vez de propagar.
  try {
    if (!facturaEhDocumentoFiscalConvertido(factura)) return;

    const cotacao = await localizarCotacaoOrigemFactura(factura);
    if (!cotacao || cotacao.estado !== 'convertida') return;

    const referenciaCotacao = normalizarReferenciaDocumento(cotacao.numeroDocumento);
    const facturasEmpresa = await facturas.listarFacturasPorEmpresa(factura.empresaId);
    const existeOutroDocumento = facturasEmpresa.some((documento: any) => {
      if (documento.id === factura.id) return false;
      if (!facturaEhDocumentoFiscalConvertido(documento)) return false;
      if (String(documento.estado || '').toLowerCase() === 'anulado') return false;

      return (
        (cotacao.id && documento.cotacaoId === cotacao.id) ||
        (referenciaCotacao && normalizarReferenciaDocumento(documento.cotacaoReferencia) === referenciaCotacao)
      );
    });

    if (existeOutroDocumento) return;

    const documentosOriginados = Array.isArray(cotacao.documentosOriginados)
      ? cotacao.documentosOriginados.filter((documento: string) => !String(documento || '').includes(String(factura.id || '')))
      : cotacao.documentosOriginados;

    await cotacoes.atualizarCotacao(cotacao.id, {
      estado: 'aprovada',
      documentosOriginados,
    } as any);
    await integracaoFiscal.resolverPendencia(cotacao.empresaId, cotacao.id).catch(() => null);
  } catch (error: any) {
    console.error(`[reverterCotacaoOrigemSeLivre] Erro ao reverter cotacao de origem da factura ${factura?.id}:`, error);
    if (factura?.empresaId && factura?.cotacaoId) {
      await integracaoFiscal.registrarPendencia(
        { empresaId: factura.empresaId, id: factura.cotacaoId, numeroDocumento: factura.cotacaoId, tipoDocumento: 'cotacao' },
        [`Falha ao reverter estado da cotacao apos eliminar factura ${factura.numeroDocumento || factura.id}: ${error?.message || String(error)}`],
      ).catch(() => null);
    }
  }
}

app.use('/make-server-7249dcd9/*', async (c, next) => {
  const metodo = c.req.method.toUpperCase();
  const rota = c.req.path;

  if (metodo === 'GET' || metodo === 'OPTIONS' || rota.includes('/auditoria')) {
    return await next();
  }

  const inicio = Date.now();
  const corpo = await lerCorpoAuditoria(c);
  const usuario = await obterUsuarioAuditoriaRequest(c, corpo || {});

  try {
    await next();
  } catch (error) {
    await auditoria.registrarEventoHttp({
      metodo,
      rota,
      statusHttp: 500,
      duracaoMs: Date.now() - inicio,
      corpo,
      usuario,
      ip: c.req.header('x-forwarded-for') || c.req.header('cf-connecting-ip') || c.req.header('x-real-ip'),
      userAgent: c.req.header('user-agent'),
    }).catch((auditError) => console.error('[AUDITORIA] Erro ao registrar falha:', auditError));
    throw error;
  }

  const auditoriaManual = typeof c.get === 'function' ? c.get('auditoriaManual') : false;
  if (auditoriaManual) return;

  await auditoria.registrarEventoHttp({
    metodo,
    rota,
    statusHttp: c.res?.status || 200,
    duracaoMs: Date.now() - inicio,
    corpo,
    usuario,
    ip: c.req.header('x-forwarded-for') || c.req.header('cf-connecting-ip') || c.req.header('x-real-ip'),
    userAgent: c.req.header('user-agent'),
  }).catch((error) => console.error('[AUDITORIA] Erro ao registrar operacao:', error));
});

async function registrarAuditoriaFactura(c: any, operacao: string, factura: any, opcoes?: { body?: any; antes?: any; estadoAnterior?: string }) {
  try {
    if (!factura) return;
    const contexto = {
      ...(opcoes?.body || {}),
      empresaId: factura.empresaId || opcoes?.body?.empresaId,
    };
    const usuario = await obterUsuarioAuditoriaRequest(c, contexto);
    const tipoDocumentoRaw = ((factura.tipoDocumento || contexto.tipoDocumento || 'factura') as string)
      .trim()
      .toLowerCase()
      .replace(/-/g, '_');
    const tipoDocumento = tipoDocumentoRaw === 'factura_recibo' || tipoDocumentoRaw === 'fatura_recibo'
      ? 'factura_recibo'
      : tipoDocumentoRaw === 'factura_proforma' || tipoDocumentoRaw === 'fatura_proforma' || tipoDocumentoRaw === 'proforma'
        ? 'factura_proforma'
        : 'factura';
    const tipoNome = tipoDocumento === 'factura_recibo'
      ? 'Factura-Recibo'
      : tipoDocumento === 'factura_proforma'
        ? 'Factura Proforma'
        : 'Factura';
    const numero = factura.numeroDocumento || contexto.numeroDocumento || factura.id;
    const clienteNome = factura.cliente?.nome || factura.clienteNome || contexto.cliente?.nome || contexto.clienteNome || 'cliente nao identificado';
    const total = Number(factura.totalGeral ?? contexto.totalGeral ?? 0);
    const moeda = factura.moeda || contexto.moeda || 'MT';
    const valorTexto = Number.isFinite(total) ? `${total.toLocaleString('pt-MZ', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} ${moeda}` : moeda;
    const verbos: Record<string, string> = {
      criar: 'criou',
      editar: 'editou',
      deletar: 'eliminou',
      anular: 'anulou',
      emitir: 'emitiu',
      aprovar: 'aprovou',
    };
    const verbo = verbos[operacao] || 'alterou';
    const mensagem = `${usuario.nome || 'Sistema'} ${verbo} ${tipoNome} ${numero} para ${clienteNome}, no valor de ${valorTexto}.`;
    const alteracoes = opcoes?.antes
      ? auditoria.compararObjetosLegivel(opcoes.antes, factura, { limite: 80 })
      : opcoes?.estadoAnterior
        ? auditoria.compararObjetosLegivel({ estado: opcoes.estadoAnterior }, { estado: factura.estado }, { limite: 5 })
        : [];

    await auditoria.registrarLog({
      empresaId: factura.empresaId || contexto.empresaId || 'sistema',
      usuarioId: usuario.id || 'sistema',
      usuarioNome: usuario.nome || 'Sistema',
      usuarioEmail: usuario.email || '',
      operacao,
      documentoId: factura.id,
      documentoTipo: tipoDocumento,
      documentoNumero: numero,
      entidadeTipo: tipoDocumento,
      entidadeId: factura.id,
      entidadeNome: numero,
      modulo: 'faturacao-vendas',
      moduloNome: 'Facturacao e Vendas',
      titulo: `${tipoNome} ${numero}`,
      mensagem,
      detalhes: mensagem,
      detalhesTexto: mensagem,
      alteracoes,
      metadata: {
        resumo: {
          clienteNome,
          totalGeral: total,
          moeda,
          estado: factura.estado,
          tipoDocumento,
          numeroDocumento: numero,
          itens: Array.isArray(factura.itens || contexto.itens) ? (factura.itens || contexto.itens).length : 0,
        },
        cliente: {
          id: factura.clienteId || contexto.clienteId,
          nome: clienteNome,
          nuit: factura.cliente?.nuit || contexto.cliente?.nuit || factura.clienteNuit,
        },
        totalGeral: total,
        moeda,
        estado: factura.estado,
        tipoDocumento,
        numeroDocumento: numero,
        itens: Array.isArray(factura.itens || contexto.itens) ? (factura.itens || contexto.itens).length : 0,
      },
      origem: 'backend',
      nivel: operacao === 'deletar' || operacao === 'anular' ? 'aviso' : 'info',
      tags: ['faturacao', tipoDocumento, operacao],
    });
  } catch (error) {
    console.error('[AUDITORIA FACTURA] Erro ao registrar auditoria:', error);
  }
}

function marcarAuditoriaManual(c: any) {
  try {
    if (typeof c.set === 'function') c.set('auditoriaManual', true);
  } catch (_error) {
    // Sem efeito fora do Hono context.
  }
}

function valorNumeroAuditoria(valor: any, casas = 2): string {
  const numero = Number(valor ?? 0);
  if (!Number.isFinite(numero)) return '0';
  return numero.toLocaleString('pt-MZ', { minimumFractionDigits: casas, maximumFractionDigits: casas });
}

function quantidadeAuditoria(valor: any): string {
  const numero = Number(valor ?? 0);
  if (!Number.isFinite(numero)) return '0';
  return numero.toLocaleString('pt-MZ', { maximumFractionDigits: 4 });
}

function nomeArtigoAuditoria(artigo: any): string {
  const codigo = artigo?.codigo || artigo?.artigoCodigo || artigo?.id || '';
  const nome = artigo?.nome || artigo?.artigoNome || artigo?.descricao || '';
  if (codigo && nome && codigo !== nome) return `${codigo} - ${nome}`;
  return codigo || nome || 'artigo nao identificado';
}

function nomeArmazemAuditoria(dados: any): string {
  const codigo = dados?.armazemCodigo || '';
  const nome = dados?.armazemNome || '';
  if (codigo && nome && codigo !== nome) return `${codigo} - ${nome}`;
  return codigo || nome || dados?.armazemId || 'armazem nao identificado';
}

function resumoArtigoAuditoria(artigo: any, extra: Record<string, any> = {}) {
  return {
    artigoCodigo: artigo?.codigo || artigo?.artigoCodigo,
    artigoNome: artigo?.nome || artigo?.artigoNome,
    tipo: artigo?.tipo,
    unidade: artigo?.unidade,
    stockNovo: artigo?.estoqueAtual,
    stockMinimo: artigo?.estoqueMinimo,
    precoCompra: artigo?.precoCompra,
    precoVenda: artigo?.precoVenda,
    iva: artigo?.iva,
    armazemId: artigo?.armazemId,
    fornecedorNome: artigo?.fornecedorNome,
    lote: artigo?.lote,
    ...extra,
  };
}

function linhasInventarioResumo(linhas: any[] = [], limite = 8) {
  return linhas.slice(0, limite).map((linha) => ({
    artigoCodigo: linha.artigoCodigo,
    artigoNome: linha.artigoNome,
    stockSistema: linha.stockSistema,
    contagemFisica: linha.contagemFisica,
    diferenca: linha.diferenca,
    valorDiferenca: linha.valorDiferenca,
    motivo: linha.motivoDiferenca,
    status: linha.statusLinha,
  }));
}

function textoLinhasInventario(linhas: any[] = [], limite = 6): string {
  if (!linhas.length) return 'Sem linhas de inventario.';
  const partes = linhas.slice(0, limite).map((linha) => {
    const contagem = linha.contagemFisica === null || linha.contagemFisica === undefined ? 'nao contada' : quantidadeAuditoria(linha.contagemFisica);
    const diferenca = Number(linha.diferenca || 0);
    const sinal = diferenca > 0 ? '+' : '';
    return `${linha.artigoCodigo || ''} - ${linha.artigoNome || ''}: stock sistema ${quantidadeAuditoria(linha.stockSistema)}, contagem ${contagem}, diferenca ${sinal}${quantidadeAuditoria(diferenca)}`;
  });
  const restantes = linhas.length - partes.length;
  return restantes > 0 ? `${partes.join('; ')}; e mais ${restantes} artigo(s).` : `${partes.join('; ')}.`;
}

async function registrarAuditoriaArtigo(c: any, operacao: string, artigo: any, opcoes?: { body?: any; antes?: any; extraResumo?: Record<string, any>; detalhes?: string; nivel?: 'info' | 'aviso' | 'critico' }) {
  try {
    if (!artigo) return;
    const contexto = { ...(opcoes?.body || {}), empresaId: artigo.empresaId || opcoes?.body?.empresaId };
    const usuario = await obterUsuarioAuditoriaRequest(c, contexto);
    const alvo = nomeArtigoAuditoria(artigo);
    const verbos: Record<string, string> = {
      criar: 'criou', editar: 'editou', deletar: 'eliminou', bloquear: 'desativou', desbloquear: 'ativou', configurar: 'ajustou o stock de',
    };
    const verbo = verbos[operacao] || 'alterou';
    const alteracoes = opcoes?.antes ? auditoria.compararObjetosLegivel(opcoes.antes, artigo, { limite: 80 }) : [];
    const detalhesAlteracoes = alteracoes.length > 0 ? ` Campos alterados: ${auditoria.alteracoesParaTexto(alteracoes)}` : '';
    const detalhes = opcoes?.detalhes || `${usuario.nome || 'Sistema'} ${verbo} o artigo ${alvo}.${detalhesAlteracoes}`;
    const resultadoAuditoria = await auditoria.registrarLog({
      empresaId: artigo.empresaId || contexto.empresaId || 'sistema',
      usuarioId: usuario.id || 'sistema',
      usuarioNome: usuario.nome || 'Sistema',
      usuarioEmail: usuario.email || '',
      operacao,
      documentoId: artigo.id,
      documentoTipo: 'artigo',
      documentoNumero: artigo.codigo,
      entidadeTipo: 'artigo',
      entidadeId: artigo.id,
      entidadeNome: alvo,
      modulo: 'stock-inventario',
      moduloNome: 'Stock e Inventario',
      titulo: `${operacao === 'configurar' ? 'Ajustou stock do' : labelOperacaoStock(operacao)} Artigo ${alvo}`,
      mensagem: detalhes,
      detalhes,
      detalhesTexto: detalhes,
      alteracoes,
      metadata: {
        resumo: resumoArtigoAuditoria(artigo, opcoes?.extraResumo || {}),
        artigo,
        antes: opcoes?.antes,
        corpo: opcoes?.body,
      },
      origem: 'backend',
      nivel: opcoes?.nivel || (operacao === 'deletar' ? 'aviso' : 'info'),
      tags: ['stock', 'artigo', operacao],
    });
    if (resultadoAuditoria.success) marcarAuditoriaManual(c);
  } catch (error) {
    console.error('[AUDITORIA STOCK] Erro ao registrar artigo:', error);
  }
}

function labelOperacaoStock(operacao: string): string {
  const labels: Record<string, string> = {
    criar: 'Criou', editar: 'Editou', deletar: 'Eliminou', bloquear: 'Desativou', desbloquear: 'Ativou', configurar: 'Ajustou',
    contar: 'Contou', iniciar_contagem: 'Iniciou', finalizar_inventario: 'Finalizou', cancelar: 'Cancelou', reverter: 'Reverteu',
  };
  return labels[operacao] || operacao;
}

async function registrarAuditoriaMovimentoStock(c: any, operacao: string, movimento: any, opcoes?: { body?: any; antes?: any; detalhes?: string; nivel?: 'info' | 'aviso' | 'critico' }) {
  try {
    if (!movimento) return;
    const contexto = { ...(opcoes?.body || {}), empresaId: movimento.empresaId || opcoes?.body?.empresaId };
    const usuario = await obterUsuarioAuditoriaRequest(c, contexto);
    const artigoNome = nomeArtigoAuditoria(movimento);
    const tipo = movimento.tipo === 'entrada' ? 'entrada' : 'saida';
    const armazem = nomeArmazemAuditoria(movimento);
    const detalhes = opcoes?.detalhes || `${usuario.nome || 'Sistema'} registou ${tipo} de ${quantidadeAuditoria(movimento.quantidade)} ${movimento.artigoUnidade || ''} do artigo ${artigoNome} no ${armazem}. Motivo: ${movimento.motivo || 'nao informado'}.`;
    const resultadoAuditoria = await auditoria.registrarLog({
      empresaId: movimento.empresaId || contexto.empresaId || 'sistema',
      usuarioId: usuario.id || 'sistema',
      usuarioNome: usuario.nome || 'Sistema',
      usuarioEmail: usuario.email || '',
      operacao,
      documentoId: movimento.id,
      documentoTipo: 'movimento_stock',
      documentoNumero: movimento.documentoNumero || movimento.id,
      entidadeTipo: 'movimento_stock',
      entidadeId: movimento.id,
      entidadeNome: `${tipo} ${artigoNome}`,
      modulo: 'stock-inventario',
      moduloNome: 'Stock e Inventario',
      titulo: `${labelOperacaoStock(operacao)} movimento de stock - ${artigoNome}`,
      mensagem: detalhes,
      detalhes,
      detalhesTexto: detalhes,
      alteracoes: opcoes?.antes ? auditoria.compararObjetosLegivel(opcoes.antes, movimento, { limite: 60 }) : [],
      metadata: {
        resumo: {
          artigoCodigo: movimento.artigoCodigo,
          artigoNome: movimento.artigoNome,
          tipo: movimento.tipo,
          quantidade: movimento.quantidade,
          motivo: movimento.motivo,
          armazemCodigo: movimento.armazemCodigo,
          armazemNome: movimento.armazemNome,
          lote: movimento.lote,
          documentoTipo: movimento.documentoTipo,
          documentoNumero: movimento.documentoNumero,
          responsavel: movimento.responsavel,
          dataMovimento: movimento.dataMovimento,
        },
        movimento,
        antes: opcoes?.antes,
        corpo: opcoes?.body,
      },
      origem: 'backend',
      nivel: opcoes?.nivel || (operacao === 'deletar' || movimento.tipo === 'saida' ? 'aviso' : 'info'),
      tags: ['stock', 'movimento_stock', operacao, movimento.tipo, movimento.motivo].filter(Boolean),
    });
    if (resultadoAuditoria.success) marcarAuditoriaManual(c);
  } catch (error) {
    console.error('[AUDITORIA STOCK] Erro ao registrar movimento:', error);
  }
}

function labelDocumentoStock(tipo?: string): string {
  const labels: Record<string, string> = {
    guia_entrada: 'Guia de Entrada de Mercadoria',
    guia_remessa: 'Guia de Remessa',
    devolucao_cliente: 'Guia de Devolucao de Cliente',
    devolucao_fornecedor: 'Guia de Devolucao ao Fornecedor',
    consumo_interno: 'Requisicao de Consumo Interno',
    auto_quebra: 'Auto de Quebra/Avaria',
    perda_vencimento: 'Auto de Perda por Vencimento',
    ajuste_positivo: 'Documento de Ajuste Positivo de Stock',
    ajuste_negativo: 'Documento de Ajuste Negativo de Stock',
  };
  return labels[tipo || ''] || tipo || 'Documento de Stock';
}

function textoLinhasDocumentoStock(linhas: any[] = [], limite = 8): string {
  const linhasTexto = (linhas || []).slice(0, limite).map((linha) =>
    `${linha.artigoCodigo || ''} - ${linha.artigoNome || ''}: ${quantidadeAuditoria(linha.quantidade)} un no ${linha.armazemCodigo || ''} - ${linha.armazemNome || ''}`
  );
  const extra = (linhas || []).length > limite ? `; +${(linhas || []).length - limite} linha(s)` : '';
  return linhasTexto.length > 0 ? `Linhas: ${linhasTexto.join('; ')}${extra}.` : 'Sem linhas informadas.';
}

async function registrarAuditoriaDocumentoStock(c: any, operacao: string, documento: any, opcoes?: { body?: any; antes?: any; detalhes?: string; nivel?: 'info' | 'aviso' | 'critico' }) {
  try {
    if (!documento) return;
    const contexto = { ...(opcoes?.body || {}), empresaId: documento.empresaId || opcoes?.body?.empresaId };
    const usuario = await obterUsuarioAuditoriaRequest(c, contexto);
    const numero = documento.numero || documento.id;
    const tipoLabel = labelDocumentoStock(documento.tipo);
    const detalhes = opcoes?.detalhes || `${usuario.nome || 'Sistema'} ${labelOperacaoStock(operacao).toLowerCase()} ${tipoLabel} ${numero}. Estado: ${documento.estado}. ${textoLinhasDocumentoStock(documento.linhas || [], 10)}`;
    const resultadoAuditoria = await auditoria.registrarLog({
      empresaId: documento.empresaId || contexto.empresaId || 'sistema',
      usuarioId: usuario.id || 'sistema',
      usuarioNome: usuario.nome || 'Sistema',
      usuarioEmail: usuario.email || '',
      operacao,
      documentoId: documento.id,
      documentoTipo: 'documento_stock',
      documentoNumero: numero,
      entidadeTipo: 'documento_stock',
      entidadeId: documento.id,
      entidadeNome: `${tipoLabel} ${numero}`,
      modulo: 'stock-inventario',
      moduloNome: 'Stock e Inventario',
      titulo: `${labelOperacaoStock(operacao)} ${tipoLabel} ${numero}`,
      mensagem: detalhes,
      detalhes,
      detalhesTexto: detalhes,
      alteracoes: opcoes?.antes ? auditoria.compararObjetosLegivel(opcoes.antes, documento, { limite: 100 }) : [],
      metadata: {
        resumo: {
          numero,
          tipo: documento.tipo,
          tipoLabel,
          estado: documento.estado,
          dataDocumento: documento.dataDocumento,
          entidadeNome: documento.entidadeNome,
          armazemCodigo: documento.armazemCodigo,
          armazemNome: documento.armazemNome,
          totalLinhas: documento.totalLinhas,
          totalQuantidade: documento.totalQuantidade,
          movimentosIds: documento.movimentosIds,
          movimentosReversaoIds: documento.movimentosReversaoIds,
          responsavel: documento.responsavelNome || documento.responsavel,
        },
        linhas: documento.linhas || [],
        documento,
        antes: opcoes?.antes,
        corpo: opcoes?.body,
      },
      origem: 'backend',
      nivel: opcoes?.nivel || (operacao === 'anular' || documento.estado === 'anulado' ? 'aviso' : 'info'),
      tags: ['stock', 'documento_stock', operacao, documento.tipo, documento.estado].filter(Boolean),
    });
    if (resultadoAuditoria.success) marcarAuditoriaManual(c);
  } catch (error) {
    console.error('[AUDITORIA DOC STOCK] Erro ao registrar documento:', error);
  }
}

async function registrarAuditoriaInventario(c: any, operacao: string, inventario: any, opcoes?: { body?: any; antes?: any; detalhes?: string; nivel?: 'info' | 'aviso' | 'critico'; extraResumo?: Record<string, any> }) {
  try {
    if (!inventario) return;
    const contexto = { ...(opcoes?.body || {}), empresaId: inventario.empresaId || opcoes?.body?.empresaId };
    const usuario = await obterUsuarioAuditoriaRequest(c, contexto);
    const numero = inventario.numero || inventario.id;
    const alteracoes = opcoes?.antes ? auditoria.compararObjetosLegivel(opcoes.antes, inventario, { limite: 100 }) : [];
    const detalhes = opcoes?.detalhes || `${usuario.nome || 'Sistema'} ${labelOperacaoStock(operacao).toLowerCase()} inventario ${numero} no ${nomeArmazemAuditoria(inventario)}. ${textoLinhasInventario(inventario.linhas || [], 6)}`;
    const resultadoAuditoria = await auditoria.registrarLog({
      empresaId: inventario.empresaId || contexto.empresaId || 'sistema',
      usuarioId: usuario.id || 'sistema',
      usuarioNome: usuario.nome || 'Sistema',
      usuarioEmail: usuario.email || '',
      operacao,
      documentoId: inventario.id,
      documentoTipo: 'inventario',
      documentoNumero: numero,
      entidadeTipo: 'inventario',
      entidadeId: inventario.id,
      entidadeNome: numero,
      modulo: 'stock-inventario',
      moduloNome: 'Stock e Inventario',
      titulo: `${labelOperacaoStock(operacao)} inventario ${numero}`,
      mensagem: detalhes,
      detalhes,
      detalhesTexto: detalhes,
      alteracoes,
      metadata: {
        resumo: {
          numero,
          armazemCodigo: inventario.armazemCodigo,
          armazemNome: inventario.armazemNome,
          tipo: inventario.tipo,
          status: inventario.status,
          dataInventario: inventario.dataInventario,
          responsavel: inventario.responsavel,
          totalArtigos: inventario.totalArtigos,
          totalContado: inventario.totalContado,
          diferencasPositivas: inventario.diferencasPositivas,
          diferencasNegativas: inventario.diferencasNegativas,
          valorLiquidoDiferencas: inventario.valorLiquidoDiferencas,
          ...(opcoes?.extraResumo || {}),
        },
        linhasResumo: linhasInventarioResumo(inventario.linhas || [], 20),
        inventario,
        antes: opcoes?.antes,
        corpo: opcoes?.body,
      },
      origem: 'backend',
      nivel: opcoes?.nivel || (operacao === 'cancelar' || operacao === 'deletar' ? 'aviso' : 'info'),
      tags: ['stock', 'inventario', operacao],
    });
    if (resultadoAuditoria.success) marcarAuditoriaManual(c);
  } catch (error) {
    console.error('[AUDITORIA STOCK] Erro ao registrar inventario:', error);
  }
}

async function registrarAuditoriaLinhaInventario(c: any, inventarioAntes: any, inventarioDepois: any, linhaId: string, body?: any) {
  try {
    const linhaAntes = inventarioAntes?.linhas?.find((linha: any) => linha.id === linhaId);
    const linhaDepois = inventarioDepois?.linhas?.find((linha: any) => linha.id === linhaId);
    if (!inventarioDepois || !linhaDepois) return;
    const usuario = await obterUsuarioAuditoriaRequest(c, { ...(body || {}), empresaId: inventarioDepois.empresaId });
    const diferenca = Number(linhaDepois.diferenca || 0);
    const sinal = diferenca > 0 ? '+' : '';
    const detalhes = `${usuario.nome || 'Sistema'} registou contagem do artigo ${linhaDepois.artigoCodigo} - ${linhaDepois.artigoNome} no inventario ${inventarioDepois.numero}. Stock no sistema: ${quantidadeAuditoria(linhaDepois.stockSistema)}; contagem fisica: ${quantidadeAuditoria(linhaDepois.contagemFisica)}; diferenca: ${sinal}${quantidadeAuditoria(diferenca)}; valor da diferenca: ${valorNumeroAuditoria(linhaDepois.valorDiferenca || 0)} MT.${linhaDepois.motivoDiferenca ? ` Motivo: ${linhaDepois.motivoDiferenca}.` : ''}`;
    const alteracoes = linhaAntes ? auditoria.compararObjetosLegivel(linhaAntes, linhaDepois, { limite: 40 }) : [];
    const resultadoAuditoria = await auditoria.registrarLog({
      empresaId: inventarioDepois.empresaId || 'sistema',
      usuarioId: usuario.id || 'sistema',
      usuarioNome: usuario.nome || 'Sistema',
      usuarioEmail: usuario.email || '',
      operacao: 'contar',
      documentoId: inventarioDepois.id,
      documentoTipo: 'inventario',
      documentoNumero: inventarioDepois.numero,
      entidadeTipo: 'inventario_linha',
      entidadeId: linhaDepois.id,
      entidadeNome: `${linhaDepois.artigoCodigo} - ${linhaDepois.artigoNome}`,
      modulo: 'stock-inventario',
      moduloNome: 'Stock e Inventario',
      titulo: `Contou artigo ${linhaDepois.artigoCodigo} - ${linhaDepois.artigoNome}`,
      mensagem: detalhes,
      detalhes,
      detalhesTexto: detalhes,
      alteracoes,
      metadata: {
        resumo: {
          numero: inventarioDepois.numero,
          armazemCodigo: inventarioDepois.armazemCodigo,
          armazemNome: inventarioDepois.armazemNome,
          artigoCodigo: linhaDepois.artigoCodigo,
          artigoNome: linhaDepois.artigoNome,
          stockSistema: linhaDepois.stockSistema,
          contagemFisica: linhaDepois.contagemFisica,
          diferenca: linhaDepois.diferenca,
          valorDiferenca: linhaDepois.valorDiferenca,
          motivo: linhaDepois.motivoDiferenca,
          status: linhaDepois.statusLinha,
        },
        linhaAntes,
        linhaDepois,
        corpo: body,
      },
      origem: 'backend',
      nivel: diferenca < 0 ? 'aviso' : 'info',
      tags: ['stock', 'inventario', 'contagem', 'artigo'],
    });
    if (resultadoAuditoria.success) marcarAuditoriaManual(c);
  } catch (error) {
    console.error('[AUDITORIA STOCK] Erro ao registrar linha de inventario:', error);
  }
}
async function obterFornecedorNomeContabil(fornecedorId?: string, fallback?: string): Promise<string> {
  if (!fornecedorId) return fallback || '';
  try {
    const fornecedor = await fornecedores.buscarFornecedorPorId(fornecedorId);
    return fornecedor?.nome || fornecedor?.nomeComercial || fallback || '';
  } catch {
    return fallback || '';
  }
}

function normalizarLinhasDocumentoContabil(linhas: any[] = []) {
  return (linhas || []).map((linha: any) => ({
    ...linha,
    nome: linha.nome || linha.artigoNome || linha.descricao,
    descricao: linha.descricao || linha.nome || linha.artigoNome,
    valor: linha.valor ?? linha.total ?? linha.subtotal,
  }));
}

async function contabilizarCompraOperacional(compra: any, opcoes: { fornecedorNome?: string; forcar?: boolean; previsualizar?: boolean } = {}) {
  try {
    if (
      !compra ||
      compra.estado === 'rascunho' ||
      compra.estado === 'anulado' ||
      compra.geraLancamentoContabil === false ||
      compras.obterPerfilDocumentoCompra(compra.tipoDocumento).geraLancamentoContabil === false
    ) {
      return { success: true, skipped: true };
    }

    const fornecedorNome = await obterFornecedorNomeContabil(compra.fornecedorId, opcoes.fornecedorNome || compra.fornecedorNome);
    return await contabilidade.gerarLancamentoAutomatico({
      tipo: 'compra' as any,
      empresaId: compra.empresaId,
      documentoId: compra.id,
      numeroDocumento: compra.numeroDocumento,
      tipoDocumentoOriginal: compra.tipoDocumento,
      condicaoPagamento: compra.condicaoPagamento || compra.tipoDocumento,
      liquidacaoImediata: compra.liquidacaoImediata ?? compras.obterPerfilDocumentoCompra(compra.tipoDocumento).liquidacaoImediata,
      data: compra.dataEmissao || compra.dataCriacao || new Date().toISOString().slice(0, 10),
      fornecedorId: compra.fornecedorId,
      fornecedorNome,
      entidadeNome: fornecedorNome,
      linhas: normalizarLinhasDocumentoContabil(compra.linhas || []),
      totalGeral: Number(compra.totalGeral || 0),
      totalIVA: Number(compra.totalIVA || 0),
      // ✅ Linhas com "IVA incluido nao liquidado" (ver calcularTotaisLinhaCompra
      // em DocumentoCompraForm.tsx) ficam de fora de compra.subtotal e
      // compra.totalIVA, mas o seu valor continua em compra.totalGeral — sem
      // este ajuste o credito de Compras/Estoque ficava menor que o debito de
      // Fornecedores/Tesouraria e o lancamento desequilibrava (mesma correcao
      // aplicada em contabilizarDocumentoFiscalOperacional para vendas).
      subtotal:
        Number(compra.subtotal || 0) +
        Math.max(0, Number(compra.totalGeral || 0) - Number(compra.subtotal || 0) - Number(compra.totalIVA || 0)),
      metodoPagamento: compra.metodoPagamento || compra.formaPagamento || compra.meioPagamento,
      contaBancaria: compra.contaBancaria,
      referenciaPagamento: compra.referenciaPagamento || compra.referencia,
      forcar: opcoes.forcar ?? true,
      previsualizar: opcoes.previsualizar ?? false,
    });
  } catch (error: any) {
    console.error('[CONTABILIDADE AUTO] Erro ao contabilizar compra:', error);
    return { success: false, error: error.message };
  }
}

async function contabilizarPagamentoFornecedor(pagamento: any, opcoes: { fornecedorNome?: string; compra?: any; forcar?: boolean; previsualizar?: boolean } = {}) {
  try {
    if (!pagamento || pagamento.contabilizarSeparado === false) return { success: true, skipped: true };
    const fornecedorNome = await obterFornecedorNomeContabil(pagamento.fornecedorId, opcoes.fornecedorNome || pagamento.fornecedorNome);
    const compra = opcoes.compra || (pagamento.compraId ? await compras.buscarCompraPorId(pagamento.compraId) : null);
    const documentosRelacionados = compra ? [{
      id: compra.id,
      tipo: 'compra' as any,
      tipoLabel: compra.tipoDocumento || 'Compra',
      numeroDocumento: compra.numeroDocumento,
      data: compra.dataEmissao,
      totalGeral: Number(compra.totalGeral || 0),
    }] : undefined;

    return await contabilidade.gerarLancamentoAutomatico({
      tipo: 'pagamento' as any,
      empresaId: pagamento.empresaId,
      documentoId: pagamento.id,
      numeroDocumento: pagamento.numeroDocumento,
      tipoDocumentoOriginal: pagamento.compraId ? 'pagamento_fornecedor' : 'adiantamento_fornecedor',
      condicaoPagamento: pagamento.compraId ? 'liquidacao_fornecedor' : 'adiantamento_fornecedor',
      data: pagamento.dataEmissao || pagamento.dataCriacao || new Date().toISOString().slice(0, 10),
      fornecedorId: pagamento.fornecedorId,
      fornecedorNome,
      entidadeNome: fornecedorNome,
      linhas: [{
        descricao: compra ? `Pagamento da compra ${compra.numeroDocumento}` : 'Adiantamento a fornecedor',
        valor: Number(pagamento.valor || 0),
        metodoPagamento: pagamento.metodoPagamento || pagamento.formaPagamento || pagamento.meioPagamento,
        contaBancaria: pagamento.contaBancaria || pagamento.banco,
        referenciaPagamento: pagamento.referencia,
      }],
      totalGeral: Number(pagamento.valor || 0),
      totalIVA: 0,
      subtotal: Number(pagamento.valor || 0),
      metodoPagamento: pagamento.metodoPagamento || pagamento.formaPagamento || pagamento.meioPagamento,
      contaBancaria: pagamento.contaBancaria || pagamento.banco,
      referenciaPagamento: pagamento.referencia,
      documentosRelacionados,
      forcar: opcoes.forcar ?? true,
      previsualizar: opcoes.previsualizar ?? false,
    });
  } catch (error: any) {
    console.error('[CONTABILIDADE AUTO] Erro ao contabilizar pagamento a fornecedor:', error);
    return { success: false, error: error.message };
  }
}

async function contabilizarDocumentoFiscalOperacional(
  documento: any,
  tipo: 'fatura' | 'factura_recibo' | 'venda_dinheiro' | 'nota_credito' | 'nota_debito' | 'adiantamento',
  opcoes: { forcar?: boolean; previsualizar?: boolean } = {},
) {
  try {
    if (!documento || documento.estado === 'anulado' || documento.estado === 'anulada') {
      return { success: true, skipped: true };
    }

    return await contabilidade.gerarLancamentoAutomatico({
      tipo: tipo as any,
      empresaId: documento.empresaId,
      documentoId: documento.id,
      numeroDocumento: documento.numeroDocumento,
      tipoDocumentoOriginal: documento.tipoDocumento || tipo,
      condicaoPagamento: documento.condicaoPagamento,
      data: documento.dataEmissao || documento.dataPagamento || new Date().toISOString().slice(0, 10),
      clienteId: documento.clienteId,
      clienteNome: documento.cliente?.nome || documento.clienteNome,
      entidadeNome: documento.cliente?.nome || documento.clienteNome,
      linhas: normalizarLinhasDocumentoContabil(documento.itens || documento.linhas || []),
      totalGeral: Number(documento.totalGeral || 0),
      totalIVA: Number(documento.totalImpostos ?? documento.totalIVA ?? 0),
      // ✅ Bug real (Financas/AT): tentar derivar o valor liquido a partir de
      // documento.subtotal - documento.descontos parte do princípio de que
      // "subtotal" vem sempre BRUTO (antes de desconto) — verdade apos
      // recalcularDocumentoFiscal (validacao-fiscal.tsx), mas NAO na
      // pre-validacao da Factura-Recibo (index.tsx, opcoes.previsualizar),
      // que chama esta funcao com o payload cru do formulario ANTES da
      // recalculacao do backend. Nesse payload, "subtotal" (calcularTotais()
      // no frontend) ja vem LIQUIDO (= totalLiquido). Subtrair descontos
      // outra vez sobre um valor ja liquido descontava a duas vezes e
      // desequilibrava o lancamento sempre que havia desconto de linha.
      // totalGeral e totalImpostos, ao contrario, tem sempre o mesmo
      // significado em ambos os casos — por isso o valor liquido (+ o
      // "IVA incluido nao liquidado", que fica fora do Total de IVA mas
      // dentro do totalGeral) e sempre totalGeral - totalIVA, sem depender
      // de subtotal/descontos/totalIvaIncluidoNaoLiquidado de todo.
      subtotal: Math.max(
        Math.abs(Number(documento.totalGeral || 0)) - Math.abs(Number(documento.totalImpostos ?? documento.totalIVA ?? 0)),
        0,
      ),
      metodoPagamento: documento.metodoPagamento || documento.formaPagamento || documento.meioPagamento,
      contaBancaria: documento.contaBancaria || documento.banco,
      referenciaPagamento: documento.referenciaPagamento || documento.referencia,
      forcar: opcoes.forcar ?? true,
      previsualizar: opcoes.previsualizar ?? false,
    });
  } catch (error: any) {
    console.error('[CONTABILIDADE AUTO] Erro ao contabilizar documento fiscal:', error);
    return { success: false, error: error.message };
  }
}

async function buscarLancamentoDocumentoContabil(empresaId: string, documentoId: string, tipoDocumento?: string) {
  if (!empresaId || !documentoId) return null;

  const resultado = await contabilidade.obterLancamentos(empresaId);
  if (!resultado.success) return null;

  const tipo = String(tipoDocumento || '').trim().toLowerCase();
  return (resultado.data || []).find((lancamento: any) =>
    lancamento.documentoId === documentoId &&
    lancamento.estado !== 'estornado' &&
    (!tipo || String(lancamento.tipoDocumento || '').trim().toLowerCase() === tipo)
  ) || null;
}

async function contabilizarReciboOperacional(recibo: any, opcoes: { forcar?: boolean; previsualizar?: boolean } = {}) {
  try {
    if (!recibo || recibo.estado === 'anulado' || recibo.estado === 'anulada') {
      return { success: true, skipped: true };
    }

    const documentosRelacionados = (recibo.pagamentos || [])
      .filter((pagamento: any) => pagamento?.facturaId && Number(pagamento.valorPago || 0) > 0)
      .map((pagamento: any) => ({
        id: pagamento.facturaId,
        tipo: 'fatura' as any,
        tipoLabel: 'Factura',
        numeroDocumento: pagamento.facturaNumero || pagamento.numeroDocumento || pagamento.facturaId,
        data: pagamento.facturaDataEmissao || pagamento.dataEmissao || recibo.dataEmissao,
        totalGeral: Number(pagamento.valorPago || 0),
      }));

    return await contabilidade.gerarLancamentoAutomatico({
      tipo: 'recibo' as any,
      empresaId: recibo.empresaId,
      documentoId: recibo.id,
      numeroDocumento: recibo.numeroDocumento || 'Recibo em preparacao',
      tipoDocumentoOriginal: recibo.tipo || 'recibo',
      data: recibo.dataEmissao || recibo.dataPagamento || new Date().toISOString().slice(0, 10),
      clienteId: recibo.clienteId,
      clienteNome: recibo.cliente?.nome || recibo.clienteNome,
      entidadeNome: recibo.cliente?.nome || recibo.clienteNome,
      linhas: normalizarLinhasDocumentoContabil(recibo.pagamentos || recibo.itens || []),
      totalGeral: Number(recibo.totalGeral || 0),
      totalIVA: Number(recibo.totalImpostos ?? recibo.totalIVA ?? 0),
      subtotal: Number(recibo.subtotal || recibo.totalGeral || 0),
      metodoPagamento: recibo.meioPagamento || recibo.metodoPagamento || recibo.formaPagamento,
      contaBancaria: recibo.contaBancaria || recibo.banco,
      referenciaPagamento: recibo.referenciaPagamento || recibo.referenciaTransferencia || recibo.numeroCheque,
      documentosRelacionados,
      forcar: opcoes.forcar ?? true,
      previsualizar: opcoes.previsualizar ?? false,
    });
  } catch (error: any) {
    console.error('[CONTABILIDADE AUTO] Erro ao contabilizar recibo:', error);
    return { success: false, error: error.message };
  }
}

async function contabilizarMovimentoStockOperacional(movimento: any, opcoes: { criadoPor?: string; forcar?: boolean } = {}) {
  try {
    if (!movimento) return { success: true, skipped: true };
    return await contabilidade.gerarLancamentoMovimentoStock(movimento, {
      criadoPor: opcoes.criadoPor,
      forcar: opcoes.forcar ?? true,
    });
  } catch (error: any) {
    console.error('[CONTABILIDADE AUTO] Erro ao contabilizar movimento de stock:', error);
    return { success: false, error: error.message };
  }
}

async function contabilizarMovimentosStockDocumento(
  empresaId: string,
  documentoNumero?: string,
  documentoTipo?: string,
  opcoes: { criadoPor?: string } = {},
) {
  try {
    if (!empresaId || !documentoNumero) return { success: true, skipped: true, data: [] };
    const movimentos = await movimentosStock.listarMovimentos(empresaId);
    const tipoNormalizado = (documentoTipo || '').trim().toLowerCase();
    const movimentosDocumento = movimentos.filter((movimento: any) => {
      const mesmoNumero = (movimento.documentoNumero || '').trim() === documentoNumero.trim();
      if (!mesmoNumero) return false;
      if (!tipoNormalizado) return true;
      return (movimento.documentoTipo || '').trim().toLowerCase() === tipoNormalizado;
    });

    const resultados = [];
    for (const movimento of movimentosDocumento) {
      resultados.push(await contabilizarMovimentoStockOperacional(movimento, opcoes));
    }

    const falhas = resultados.filter((resultado: any) => resultado.success === false);
    return {
      success: falhas.length === 0,
      error: falhas.length > 0 ? falhas.map((f: any) => f.error).join('; ') : undefined,
      data: resultados,
    };
  } catch (error: any) {
    console.error('[CONTABILIDADE AUTO] Erro ao contabilizar movimentos do documento:', error);
    return { success: false, error: error.message };
  }
}

async function sincronizarCompraInterempresaVenda(documento: any, tipo: interempresa.TipoDocumentoInterempresa) {
  try {
    const resultado = await interempresa.criarOuAtualizarCompraInterempresaDeVenda(documento, tipo);
    if (!resultado.success) {
      console.error('[INTEREMPRESA] Falha ao criar compra pendente:', resultado.error);
    }
    return resultado;
  } catch (error: any) {
    console.error('[INTEREMPRESA] Erro inesperado ao sincronizar venda:', error);
    return { success: false, error: error.message || String(error) };
  }
}

// ✅ Converte as falhas silenciosas de criarVendaDinheiro (movimento financeiro e/ou
// movimentos de stock por item) no mesmo formato {success:false, error} que
// anexarResultadoContabilidade já sabe transformar em pendência de integração,
// em vez de as deixar só num campo da resposta que o frontend nunca lê.
function movimentosVDParaPendencia(vd: any): Record<string, any> {
  const resultados: Record<string, any> = {};

  if (vd?.erroMovimentoFinanceiro) {
    resultados.movimentoFinanceiro = { success: false, error: vd.erroMovimentoFinanceiro };
  }

  if (Array.isArray(vd?.errosMovimentos) && vd.errosMovimentos.length > 0) {
    resultados.movimentosStock = {
      success: false,
      error: vd.errosMovimentos
        .map((item: any) => `${item.artigoCodigo}: ${item.erro}`)
        .join('; '),
    };
  }

  return resultados;
}

async function anexarResultadoContabilidade(documento: any, resultados: Record<string, any>) {
  if (!documento || typeof documento !== 'object') return documento;
  const erros = Object.entries(resultados)
    .filter(([, resultado]) => resultado && resultado.success === false)
    .map(([chave, resultado]) => `${chave}: ${resultado.error || 'erro desconhecido'}`);

  if (erros.length > 0) {
    await integracaoFiscal.registrarPendencia(documento, erros);
  } else if (documento?.empresaId && documento?.id) {
    await integracaoFiscal.resolverPendencia(documento.empresaId, documento.id);
  }

  return {
    ...documento,
    contabilidade: resultados,
    avisosContabilidade: erros.length > 0 ? erros : undefined,
  };
}

function responderDocumentoIntegrado(c: any, documento: any) {
  const avisos = Array.isArray(documento?.avisosContabilidade) ? documento.avisosContabilidade : [];
  if (avisos.length > 0) {
    return c.json({
      success: true,
      data: documento,
      warning: 'Documento emitido, mas a integração ficou pendente e foi registada para regularização.',
      integracaoPendente: true,
    }, 202);
  }
  return c.json({ success: true, data: documento });
}

function respostaErroContabilidadeObrigatoria(resultado: any, contexto: string) {
  if (!resultado || resultado.success !== false) return null;

  return {
    success: false,
    error: resultado.error || `Nao foi possivel validar a contabilidade para ${contexto}`,
  };
}
// Health check endpoint
app.get("/make-server-7249dcd9/health", (c) => {
  return c.json({ status: "ok" });
});

app.get(
  "/make-server-7249dcd9/empresas/:empresaId/integracoes-fiscais",
  requirePermission('faturacao.factura.visualizar'),
  async (c) => {
    const empresaId = c.req.param('empresaId');
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    return c.json({ success: true, data: await integracaoFiscal.listarPendencias(empresaId) });
  },
);

// ========== ROTAS DE AUTENTICAÃ‡ÃƒO ==========

// Status do sistema
app.get("/make-server-7249dcd9/status", async (c) => {
  try {
    const sistemaInicializado = await kv.get("sistema:inicializado_v3");
    const tonline = await kv.get("empresa:empresa_tonline"); // CORRIGIDO: usar chave correta
    const adminUser = await usuarios.buscarUsuarioPorEmail("admin@tonline.co.mz");

    return c.json({
      success: true,
      data: {
        sistemaInicializado: !!sistemaInicializado,
        tonlineExiste: !!tonline,
        adminUserExiste: !!adminUser,
        timestamp: new Date().toISOString()
      }
    });
  } catch (error: any) {
    // console.error("[API] Erro ao verificar status:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ====================================================================
// âš ï¸ ATENÃ‡ÃƒO: ROTAS DESTRUTIVAS - USO APENAS EM DESENVOLVIMENTO
// ====================================================================
// As seguintes rotas modificam ou apagam dados do banco:
// - POST /reinicializar - APAGA TUDO e recria apenas Tonline
// - POST /debug/limpar-sql-direto - APAGA TUDO com SQL
// - POST /debug/limpar-banco-completo - APAGA TUDO via KV
// - POST /debug/limpar-movimentos-duplicados - Remove movimentos
//
// ðŸ”’ PRODUÃ‡ÃƒO: Estas rotas devem ser DESATIVADAS ou PROTEGIDAS por senha
// ðŸ”’ Para desativar: Comente o bloco completo ou adicione autenticação
// ðŸ”’ Para proteger: Adicione verificação de senha/token antes de executar
// ====================================================================

// Reinicializar sistema (apenas desenvolvimento)
app.post("/make-server-7249dcd9/reinicializar", async (c) => {
  try {
    const acessoReinicializar = await validarSuperAdminTonlineRequest(c);
    if (!acessoReinicializar.permitido) return acessoReinicializar.resposta;

    // console.log("ðŸ”„ [Sistema] Reinicializando...");

    // 1. LIMPAR FLAGS
    // console.log("ðŸ—‘ï¸ [Sistema] Limpando flags...");
    await kv.del("sistema:inicializado_v3");
    await kv.del("sistema:inicializado_v2");
    await kv.del("sistema:inicializado");
    await kv.del("sistema:modo_limpo");

    // 2. LIMPAR EMPRESAS
    // console.log("ðŸ—‘ï¸ [Sistema] Limpando empresas...");
    const empresasAtuais = await kv.getByPrefix("empresa:");
    // console.log(`   Encontradas ${empresasAtuais.length} empresas`);
    for (const empresa of empresasAtuais) {
      const key = `empresa:${empresa.id}`;
      await kv.del(key);
      // console.log(`   ðŸ—‘ï¸ Removida: ${key}`);
    }

    // 3. LIMPAR ÃNDICES DE EMPRESAS
    // console.log("ðŸ—‘ï¸ [Sistema] Limpando índices de empresas...");
    const indicesNuit = await kv.getByPrefix("empresa_nuit_index:");
    for (const idx of indicesNuit) {
      await kv.del(idx.key); // CORRIGIDO: usar idx.key
      // console.log(`   ðŸ—‘ï¸ Removido: ${idx.key}`);
    }
    const indicesEmail = await kv.getByPrefix("empresa_email_index:");
    for (const idx of indicesEmail) {
      await kv.del(idx.key); // CORRIGIDO: usar idx.key
      // console.log(`   ðŸ—‘ï¸ Removido: ${idx.key}`);
    }
    // console.log(`   ${indicesNuit.length} índices NUIT removidos`);
    // console.log(`   ${indicesEmail.length} índices email removidos`);

    // 4. LIMPAR USUÃRIOS
    // console.log("ðŸ—‘ï¸ [Sistema] Limpando usuários...");
    const usuariosAtuais = await kv.getByPrefix("usuario:");
    for (const usuario of usuariosAtuais) {
      await kv.del(`usuario:${usuario.email}`);
    }
    // console.log(`   ${usuariosAtuais.length} usuários removidos`);

    // 5. LIMPAR MÃ“DULOS
    // console.log("ðŸ—‘ï¸ [Sistema] Limpando módulos...");
    const modulosKeys = await kv.getByPrefix("modulos:");
    for (const modulo of modulosKeys) {
      await kv.del(`modulos:${modulo.empresa_id || modulo.id}`);
    }
    // console.log(`   ${modulosKeys.length} módulos removidos`);

    // 6. LIMPAR PAGAMENTOS
    // console.log("ðŸ—‘ï¸ [Sistema] Limpando pagamentos...");
    const pagamentosKeys = await kv.getByPrefix("pagamento:");
    for (const pagamento of pagamentosKeys) {
      await kv.del(`pagamento:${pagamento.id}`);
    }
    // console.log(`   ${pagamentosKeys.length} pagamentos removidos`);

    // 6.1. LIMPAR MOVIMENTOS ANTIGOS (prefixo errado "movimento:")
    // console.log("ðŸ—‘ï¸ [Sistema] Limpando movimentos antigos (prefixo incorreto)...");
    const movimentosAntigos = await kv.getByPrefix("movimento:");
    for (const mov of movimentosAntigos) {
      await kv.del(mov.key);
    }
    // console.log(`   ${movimentosAntigos.length} movimentos antigos removidos`);

    // 6.2. LIMPAR MOVIMENTOS FINANCEIROS
    // console.log("ðŸ—‘ï¸ [Sistema] Limpando movimentos financeiros...");
    const movimentosFinanceiros = await kv.getByPrefix("movimento_financeiro:");
    for (const mov of movimentosFinanceiros) {
      await kv.del(mov.key);
    }
    // console.log(`   ${movimentosFinanceiros.length} movimentos financeiros removidos`);

    // 6.3. LIMPAR MOVIMENTOS DE STOCK
    // console.log("ðŸ—‘ï¸ [Sistema] Limpando movimentos de stock...");
    const movimentosStock = await kv.getByPrefix("movimento_stock:");
    for (const mov of movimentosStock) {
      await kv.del(mov.key);
    }
    // console.log(`   ${movimentosStock.length} movimentos de stock removidos`);

    // 6.4. LIMPAR CONTAS CORRENTES
    // console.log("ðŸ—‘ï¸ [Sistema] Limpando contas correntes...");
    const contasCorrentes = await kv.getByPrefix("conta_corrente:");
    for (const conta of contasCorrentes) {
      await kv.del(conta.key);
    }
    // console.log(`   ${contasCorrentes.length} contas correntes removidas`);

    // 7. AGUARDAR 500ms para garantir que todas as operaçÃµes de DELETE foram concluídas
    await new Promise(resolve => setTimeout(resolve, 500));

    // 8. REINICIALIZAR APENAS COM TONLINE
    // console.log("ðŸš€ [Sistema] Reinicializando com APENAS Tonline...");
    await inicializarSistema();

    // console.log("âœ… [Sistema] Reinicialização concluída! Sistema limpo com APENAS Tonline.");

    return c.json({
      success: true,
      message: "Sistema reinicializado com sucesso. APENAS Tonline cadastrada.",
      detalhes: {
        empresas_removidas: empresasAtuais.length,
        usuarios_removidos: usuariosAtuais.length,
        modulos_removidos: modulosKeys.length,
        pagamentos_removidos: pagamentosKeys.length,
      }
    });
  } catch (error: any) {
    // console.error("[API] Erro ao reinicializar:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Sign in
app.post("/make-server-7249dcd9/auth/signin", async (c) => {
  try {
    const { email, password } = await c.req.json();

    if (!email || !password) {
      return c.json({
        success: false,
        error: "Email e senha são obrigatórios"
      }, 400);
    }

    const supabase = createClient(
      Deno.env.get("SUPABASE_URL") ?? "",
      Deno.env.get("SUPABASE_ANON_KEY") ?? ""
    );

    // Fazer login
    const { data, error } = await supabase.auth.signInWithPassword({
      email,
      password,
    });

    if (error || !data.session) {
      // Log apropriado: apenas informativo para credenciais inválidas
      if (error?.message?.includes("Invalid login credentials")) {
        // console.log(`[Auth] âš ï¸ Tentativa de login falhou para: ${email} (credenciais inválidas)`);
      } else {
        // Outros erros são realmente erros de sistema
        // console.error("[Auth] Erro ao fazer login:", error);
      }

      // VERIFICAR SE O SISTEMA FOI INICIALIZADO
      const sistemaInicializado = await kv.get("sistema:inicializado_v3");

      // Se não inicializado E for o admin, inicializar agora
      if (!sistemaInicializado && email === "admin@tonline.co.mz") {
        // console.log("[Auth] Sistema não inicializado! Inicializando agora...");
        await inicializarSistema();
        // console.log("[Auth] Sistema inicializado! Tente fazer login novamente.");
        return c.json({
          success: false,
          error: "Sistema foi inicializado. Por favor, tente fazer login novamente.",
          needsRetry: true,
        }, 400);
      }

      // MELHORAR MENSAGEM DE ERRO
      let mensagemErro = "Credenciais inválidas";

      if (error?.message?.includes("Invalid login credentials")) {
        mensagemErro = "Email ou senha incorretos. Verifique suas credenciais e tente novamente.";

        // Se for o admin, dar dicas adicionais
        if (email === "admin@tonline.co.mz") {
          if (!sistemaInicializado) {
            mensagemErro = "Sistema não inicializado. Clique em 'Reinicializar Sistema' no menu Debug ou use a rota /reinicializar.";
          } else {
            mensagemErro = "Credenciais incorretas. Use: admin@tonline.co.mz / admin123. Se esqueceu a senha, use a rota /reinicializar.";
          }
        }
      } else if (error?.message?.includes("Email not confirmed")) {
        mensagemErro = "Email não confirmado. Entre em contato com o administrador.";
      }

      return c.json({
        success: false,
        error: mensagemErro,
        code: error?.code || "auth_error",
        needsInit: email === "admin@tonline.co.mz" && !(await kv.get("sistema:inicializado_v3"))
      }, 401);
    }

    const userMetadata = data.user?.user_metadata || {};

    // console.log(`[Auth] âœ… Login bem-sucedido: ${email} (${userMetadata.tipo || userMetadata.nivel || 'desconhecido'})`);

    // NOVO: Buscar dados completos do usuário do KV
    let usuarioKV = await usuarios.buscarUsuarioPorEmail(email);
    console.log(`[Auth] ðŸ” Dados do usuário no KV:`, {
      encontrado: !!usuarioKV,
      email: usuarioKV?.email,
      empresaId: usuarioKV?.empresaId,
      nivel: usuarioKV?.nivel,
    });

    // âœ… SOLUÃ‡ÃƒO: Se não encontrar no KV mas for o admin, criar automaticamente
    if (!usuarioKV && email === "admin@tonline.co.mz") {
      console.log("[Auth] âš ï¸ Admin não encontrado no KV durante login, criando automaticamente...");

      // Buscar empresa Tonline
      const empresasTonline = await kv.getByPrefix("empresa:");
      const tonline = empresasTonline.find((e: any) =>
        e.nomeComercial === "Tonline" || e.nome === "Tonline, Lda"
      );

      if (tonline) {
        // Criar usuário admin no KV
        const adminUser = {
          id: data.user.id,
          authUserId: data.user.id, // âœ… CORREÃ‡ÃƒO: Adicionar authUserId
          email: data.user.email,
          nome: "Administrador Tonline",
          empresaId: tonline.id,
          nivel: "super_admin",
          modulosPermitidos: [],
          ativo: true,
          dataCriacao: new Date().toISOString(),
          permissoes: {},
        };

        await kv.set(`usuario:${data.user.id}`, adminUser);
        await kv.set(`usuario:email:${data.user.email}`, data.user.id);

        console.log("[Auth] âœ… Admin criado no KV durante login:", adminUser);
        usuarioKV = adminUser;
      }
    }

    // Buscar nome da empresa
    let nomeEmpresa = userMetadata.nome_empresa || null;
    if (usuarioKV?.empresaId) {
      console.log(`[Auth] ðŸ” Tentando buscar empresa com ID: ${usuarioKV.empresaId}`);
      const empresaData = await kv.get(`empresa:${usuarioKV.empresaId}`);
      console.log(`[Auth] ðŸ” Empresa encontrada:`, !!empresaData);
      if (empresaData) {
        nomeEmpresa = empresaData.nomeComercial || empresaData.nome || nomeEmpresa;
        console.log(`[Auth] Nome da empresa: ${nomeEmpresa}`);
      } else {
        console.log(`[Auth] âŒ Empresa não encontrada com chave: empresa:${usuarioKV.empresaId}`);
        // Tentar buscar todas as empresas para debug
        const todasEmpresas = await kv.getByPrefix('empresa:');
        console.log(`[Auth] ðŸ“Š Total de empresas no sistema: ${todasEmpresas.length}`);
        if (todasEmpresas.length > 0) {
          console.log(`[Auth] ðŸ“‹ IDs das empresas disponíveis:`, todasEmpresas.slice(0, 3).map((e: any) => ({ id: e.id, nomeComercial: e.nomeComercial })));
        }

        // A empresa deste utilizador ja nao existe (dados orfaos de uma
        // eliminacao anterior a este fix, ou inconsistencia manual). Antes
        // isto so era registado no log e o login prosseguia na mesma,
        // emitindo uma sessao valida para uma empresa inexistente.
        if (!isUsuarioSuperAdminTonline(usuarioKV)) {
          return c.json({
            success: false,
            error: "A empresa associada a esta conta ja nao existe. Contacte o administrador.",
            code: "empresa_nao_encontrada",
          }, 403);
        }
      }
    } else {
      console.log(`[Auth] âš ï¸ Usuário não tem empresaId!`);
    }

    const userData = {
      accessToken: data.session.access_token,
      userId: data.user.id,
      email: data.user.email,
      nome: usuarioKV?.nome || userMetadata.nome || null,
      empresaId: usuarioKV?.empresaId || userMetadata.empresa_id || null,
      tipo: userMetadata.tipo || userMetadata.nivel || "usuario",
    };

    console.log(`[Auth] ðŸ“¤ Retornando dados do usuário:`, {
      email: userData.email,
      empresaId: userData.empresaId,
      tipo: userData.tipo,
    });

    return c.json({
      success: true,
      message: "Login realizado com sucesso",
      data: {
        ...userData,
        nivel: usuarioKV?.nivel || userMetadata.nivel || "usuario",
        nomeEmpresa,
        permissoes: usuarioKV?.permissoes || {}, // âœ… CORREÃ‡ÃƒO: Retornar permissÃµes do usuário
        modulosPermitidos: usuarioKV?.modulosPermitidos || [], // NOVO: Retornar módulos permitidos
      },
    });
  } catch (error) {
    // console.error("[Auth] Erro no signin:", error);
    return c.json({
      success: false,
      error: "Erro interno no servidor. Tente novamente."
    }, 500);
  }
});

// âœ… NOVO: Endpoint para restaurar sessão (buscar dados do usuário autenticado)
// âš ï¸ SOLUÃ‡ÃƒO: Usar POST em vez de GET para evitar middleware do Supabase que valida JWT automaticamente
app.post("/make-server-7249dcd9/auth/me", async (c) => {
  try {
    console.log("========================================");
    console.log("[Auth] ðŸ” POST /auth/me - INÃCIO DA REQUISIÃ‡ÃƒO");
    console.log("[Auth] URL completa:", c.req.url);
    console.log("[Auth] Método:", c.req.method);
    console.log("========================================");

    // âœ… SOLUÃ‡ÃƒO: Receber token do BODY em vez do header Authorization
    const body = await c.req.json();
    const accessToken = body.token;

    console.log("[Auth] Token recebido no body:", !!accessToken);
    console.log("[Auth] Token extraído (comprimento):", accessToken?.length || 0);
    if (accessToken) {
      console.log("[Auth] Token recebido para validação.");
    }

    if (!accessToken) {
      console.error("[Auth] âŒ Token não fornecido");
      return c.json({
        success: false,
        error: "Token de acesso não fornecido"
      }, 401);
    }

    // âœ… CRÃTICO: Validar token usando o cliente Supabase (método oficial)
    console.log("[Auth] Validando token com Supabase Auth...");

    const supabaseUrl = Deno.env.get("SUPABASE_URL") ?? "";
    const anonKey = Deno.env.get("SUPABASE_ANON_KEY") ?? "";

    console.log("[Auth] Supabase URL:", supabaseUrl);

    const supabase = createClient(supabaseUrl, anonKey);

    console.log("[Auth] Chamando supabase.auth.getUser() com o token...");

    // âœ… MÃ‰TODO CORRETO: Usar supabase.auth.getUser() com o token
    const { data: { user }, error } = await supabase.auth.getUser(accessToken);

    console.log("[Auth] Resposta do Supabase Auth:", {
      userFound: !!user,
      userId: user?.id,
      userEmail: user?.email,
      errorMessage: error?.message,
      errorName: error?.name,
      errorStatus: error?.status,
    });

    if (error || !user) {
      // âœ… Tratamento silencioso: Token expirado é normal e esperado
      if (error?.name === "AuthSessionMissingError" || error?.message?.includes("session_not_found")) {
        console.log("[Auth] â„¹ï¸ Token expirado - retornando 401 para frontend fazer logout");
      } else {
        console.error("[Auth] âŒ Token inválido:", error?.message);
      }
      return c.json({
        success: false,
        error: "Sessão inválida ou expirada",
        needsLogin: true
      }, 401);
    }

    console.log("[Auth] âœ… Usuário validado:", {
      userId: user.id,
      email: user.email,
    });

    console.log(`[Auth] âœ… Sessão restaurada para: ${user.email}`);

    // Buscar dados completos do usuário no KV
    let usuarioKV = await usuarios.buscarUsuarioPorEmail(user.email!);

    // âœ… SOLUÃ‡ÃƒO MELHORADA: Se não encontrar no KV, tentar sincronizar
    if (!usuarioKV) {
      console.log("[Auth] âš ï¸ Usuário não encontrado no KV, tentando sincronizar...");

      // Caso especial: Admin Tonline
      if (user.email === "admin@tonline.co.mz") {
        console.log("[Auth] ðŸ”§ Criando admin Tonline automaticamente...");

        // Buscar empresa Tonline
        const empresasTonline = await kv.getByPrefix("empresa:");
        const tonline = empresasTonline.find((e: any) =>
          e.nomeComercial === "Tonline" || e.nome === "Tonline, Lda"
        );

        if (tonline) {
          // Criar usuário admin no KV
          const adminUser = {
            id: user.id,
            email: user.email,
            nome: "Administrador Tonline",
            empresaId: tonline.id,
            nivel: "super_admin",
            modulosPermitidos: [],
            ativo: true,
            dataCriacao: new Date().toISOString(),
            permissoes: {},
          };

          await kv.set(`usuario:${user.id}`, adminUser);
          await kv.set(`usuario:email:${user.email}`, user.id);

          console.log("[Auth] âœ… Admin criado no KV:", adminUser);
          usuarioKV = adminUser;
        }
      }
      // Caso geral: Tentar sincronizar qualquer usuário que tenha empresaId no user_metadata
      else if (user.user_metadata?.empresa_id || user.user_metadata?.empresaId) {
        console.log("[Auth] ðŸ”§ Sincronizando usuário com empresa do metadata...");

        const empresaId = user.user_metadata?.empresa_id || user.user_metadata?.empresaId;
        const nivel = user.user_metadata?.nivel || user.user_metadata?.tipo || "usuario";
        const nome = user.user_metadata?.nome || user.email?.split("@")[0] || "Usuário";

        const novoUsuario = {
          id: user.id,
          email: user.email!,
          nome: nome,
          empresaId: empresaId,
          nivel: nivel,
          modulosPermitidos: [],
          ativo: true,
          dataCriacao: user.created_at || new Date().toISOString(),
          permissoes: {},
        };

        await kv.set(`usuario:${user.id}`, novoUsuario);
        await kv.set(`usuario:email:${user.email}`, user.id);

        console.log("[Auth] âœ… Usuário sincronizado no KV:", novoUsuario);
        usuarioKV = novoUsuario;
      }
    }

    if (!usuarioKV) {
      console.error("[Auth] âŒ Usuário não encontrado no KV e não foi possível sincronizar:", user.email);

      // Listar todos os usuários para debug
      const todosUsuarios = await kv.getByPrefix("usuario:");
      const usuariosReais = todosUsuarios.filter((item: any) => !item.key?.includes(":email:"));
      console.log("[Auth] ðŸ“Š Total de usuários no sistema:", usuariosReais.length);
      if (usuariosReais.length > 0) {
        console.log("[Auth] ðŸ“‹ Usuários disponíveis:", usuariosReais.map((u: any) => u.email));
      }

      console.log("[Auth] ðŸ“‹ User metadata disponível:", user.user_metadata);

      return c.json({
        success: false,
        error: "Usuário não encontrado no sistema. Por favor, entre em contato com o administrador ou faça o signup novamente com a empresa correta."
      }, 404);
    }

    console.log("[Auth] âœ… Dados do usuário recuperados do KV");

    // Buscar nome da empresa
    let nomeEmpresa = null;
    if (usuarioKV.empresaId) {
      const empresaData = await kv.get(`empresa:${usuarioKV.empresaId}`);
      if (empresaData) {
        nomeEmpresa = empresaData.nomeComercial || empresaData.nome;
      }
    }

    console.log("[Auth] âœ… Retornando dados completos para o frontend");

    return c.json({
      success: true,
      user: {
        id: usuarioKV.id,
        nome: usuarioKV.nome,
        email: usuarioKV.email,
        empresaId: usuarioKV.empresaId,
        tipo: usuarioKV.tipo || "usuario",
        nivel: usuarioKV.nivel || "usuario",
        permissoes: usuarioKV.permissoes || {},
        nomeEmpresa,
        modulosPermitidos: usuarioKV.modulosPermitidos || [],
      },
    });
  } catch (error) {
    console.error("[Auth] âŒ Erro no /auth/me:", error);
    return c.json({
      success: false,
      error: "Erro ao buscar dados do usuário"
    }, 500);
  }
});

// Sign up (criar usuário no Supabase Auth)
app.post("/make-server-7249dcd9/auth/signup", async (c) => {
  try {
    console.log("[Auth] POST /auth/signup - Iniciando criação de usuário...");

    const { email, password, empresaId, tipo, nomeEmpresa, nivel, nome } = await c.req.json();

    console.log("[Auth] Dados recebidos:", { email, empresaId, tipo, nomeEmpresa, nivel, nome });

    if (!email || !password) {
      return c.json({
        success: false,
        error: "Email e senha são obrigatórios"
      }, 400);
    }

    const supabase = createClient(
      Deno.env.get("SUPABASE_URL") ?? "",
      Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? ""
    );

    // ========== VERIFICAR SE USUÃRIO JÃ EXISTE (ANTES DE CRIAR) ==========
    console.log("[Auth] ðŸ” Verificando se usuário já existe com email:", email);

    const { data: existingUsers, error: listError } = await supabase.auth.admin.listUsers();

    if (listError) {
      console.error("[Auth] âŒ Erro ao listar usuários:", listError);
      return c.json({
        success: false,
        error: "Erro ao verificar usuários existentes: " + listError.message
      }, 500);
    }

    const usuarioExistente = existingUsers?.users?.find(u => u.email?.toLowerCase() === email.toLowerCase());

    if (usuarioExistente) {
      console.log("[Auth] âš ï¸ Usuário JÃ EXISTE no Supabase Auth!");
      console.log("[Auth] Dados do usuário existente:", {
        id: usuarioExistente.id,
        email: usuarioExistente.email,
        created_at: usuarioExistente.created_at
      });

      // âœ… SOLUÃ‡ÃƒO: Se usuário existe no Auth mas não no KV, criar entrada no KV
      const usuarioKV = await usuarios.buscarUsuarioPorEmail(email);

      if (!usuarioKV && empresaId) {
        console.log("[Auth] ðŸ”§ Criando entrada no KV para usuário existente...");

        const nivelFinal = nivel || tipo || "admin_empresa";
        const nomeUsuario = nome || usuarioExistente.user_metadata?.nome || email.split("@")[0];

        const novoUsuario = {
          id: usuarioExistente.id,
          authUserId: usuarioExistente.id, // âœ… FASE 5 FIX: Campo crítico para loadUserFromToken encontrar o usuário
          email: email,
          nome: nomeUsuario,
          empresaId: empresaId,
          nivel: nivelFinal,
          modulosPermitidos: [],
          ativo: true,
          dataCriacao: usuarioExistente.created_at || new Date().toISOString(),
          permissoes: {},
        };

        await kv.set(`usuario:${usuarioExistente.id}`, novoUsuario);
        await kv.set(`usuario:email:${email}`, usuarioExistente.id);

        console.log("[Auth] âœ… Entrada no KV criada com sucesso!");

        return c.json({
          success: true,
          alreadyExists: true,
          fixed: true, // Indica que corrigimos o problema
          message: "Usuário já existe no sistema e foi sincronizado",
          data: {
            email,
            empresaId,
            userId: usuarioExistente.id
          }
        }, 200);
      }

      // Retornar sucesso com flag "alreadyExists"
      return c.json({
        success: true,
        alreadyExists: true, // ðŸ”¥ FLAG IMPORTANTE
        message: "Usuário já existe no sistema",
        data: {
          email,
          empresaId,
          userId: usuarioExistente.id
        }
      }, 200);
    }

    console.log("[Auth] âœ… Usuário NÃƒO existe, prosseguindo com criação...");

    // âœ… VALIDAÃ‡ÃƒO: Verificar se empresaId foi fornecido
    if (!empresaId) {
      console.error("[Auth] âŒ empresaId nï¿½ï¿½o fornecido!");
      return c.json({
        success: false,
        error: "ID da empresa é obrigatório"
      }, 400);
    }

    // Criar usuário no Supabase Auth
    console.log("[Auth] Criando usuário no Supabase Auth...");
    const nivelFinal = nivel || tipo || "admin_empresa";

    const { data, error } = await supabase.auth.admin.createUser({
      email,
      password,
      user_metadata: {
        empresa_id: empresaId,
        tipo: nivelFinal,
        nome_empresa: nomeEmpresa,
        nivel: nivelFinal,
        nome: nome || email.split("@")[0],
      },
      email_confirm: true, // Auto-confirmar email
    });

    if (error) {
      console.error("[Auth] âŒ Erro ao criar usuário:", error);
      console.error("[Auth] error.message:", error.message);
      console.error("[Auth] error.code:", error.code);

      return c.json({
        success: false,
        error: error.message
      }, 400);
    }

    console.log("[Auth] âœ… Usuário criado com sucesso no Supabase Auth:", data.user?.id);

    // âœ… CORREÃ‡ÃƒO CRÃTICA: Salvar usuário no KV store
    console.log("[Auth] ðŸ’¾ Salvando usuário no KV store...");

    const nomeUsuario = nome || data.user?.user_metadata?.nome || email.split("@")[0];

    const novoUsuario = {
      id: data.user!.id,
      authUserId: data.user!.id, // âœ… FASE 5 FIX: Campo crítico para loadUserFromToken encontrar o usuário
      email: email,
      nome: nomeUsuario,
      empresaId: empresaId,
      nivel: nivelFinal,
      modulosPermitidos: [],
      ativo: true,
      dataCriacao: new Date().toISOString(),
      permissoes: {},
    };

    try {
      await kv.set(`usuario:${data.user!.id}`, novoUsuario);
      await kv.set(`usuario:email:${email}`, data.user!.id);

      console.log("[Auth] âœ… Usuário salvo no KV com sucesso!");
      console.log("[Auth] Dados salvos:", novoUsuario);
    } catch (kvError) {
      console.error("[Auth] âŒ ERRO CRÃTICO ao salvar no KV:", kvError);

      // Tentar deletar usuário do Auth já que não conseguimos salvar no KV
      try {
        await supabase.auth.admin.deleteUser(data.user!.id);
        console.log("[Auth] â™»ï¸ Usuário deletado do Auth devido a erro no KV");
      } catch (deleteError) {
        console.error("[Auth] âŒ Erro ao deletar usuário do Auth:", deleteError);
      }

      return c.json({
        success: false,
        error: "Erro ao salvar dados do usuário. Tente novamente."
      }, 500);
    }

    return c.json({
      success: true,
      alreadyExists: false, // ðŸ”¥ FLAG IMPORTANTE
      message: "Usuário criado com sucesso",
      data: {
        userId: data.user?.id,
        email: data.user?.email,
        empresaId,
      },
    });
  } catch (error: any) {
    console.error("[Auth] âŒ Erro inesperado ao criar usuário:", error);
    return c.json({
      success: false,
      error: error.message
    }, 500);
  }
});

// âœ… FASE 5 FIX: Rota de manutenção para corrigir usuários sem authUserId
app.post("/make-server-7249dcd9/auth/fix-missing-authuserid", async (c) => {
  try {
    const acessoFixAuth = await validarSuperAdminTonlineRequest(c);
    if (!acessoFixAuth.permitido) return acessoFixAuth.resposta;

    console.log("[Auth] POST /auth/fix-missing-authuserid - Iniciando correção...");

    // Buscar todos os usuários do KV Store
    const todosUsuarios = await kv.getByPrefix<any>('usuario:');

    // Filtrar apenas os usuários principais (não são emails)
    const usuariosReais = todosUsuarios.filter(u => u.email && u.id);

    console.log(`[Auth] Total de usuários encontrados: ${usuariosReais.length}`);

    let corrigidos = 0;
    let jaOk = 0;

    for (const usuario of usuariosReais) {
      if (!usuario.authUserId) {
        console.log(`[Auth] ðŸ”§ Corrigindo usuário sem authUserId: ${usuario.email}`);

        // Adicionar o campo authUserId com o valor do id
        const usuarioCorrigido = {
          ...usuario,
          authUserId: usuario.id, // Usar o ID como authUserId
        };

        await kv.set(`usuario:${usuario.id}`, usuarioCorrigido);
        corrigidos++;

        console.log(`[Auth] ï¿½ï¿½ Usuário corrigido: ${usuario.email}`);
      } else {
        jaOk++;
      }
    }

    console.log(`[Auth] ðŸ“Š Resultado: ${corrigidos} corrigidos, ${jaOk} já estavam OK`);

    return c.json({
      success: true,
      message: `Correção concluída: ${corrigidos} usuários corrigidos`,
      data: {
        total: usuariosReais.length,
        corrigidos,
        jaOk,
      }
    });
  } catch (error: any) {
    console.error("[Auth] âŒ Erro ao corrigir usuários:", error);
    return c.json({
      success: false,
      error: error.message
    }, 500);
  }
});

// Update password (atualizar senha no Supabase Auth)
app.post("/make-server-7249dcd9/auth/update-password", async (c) => {
  try {
    const acessoUpdatePassword = await validarSuperAdminTonlineRequest(c);
    if (!acessoUpdatePassword.permitido) return acessoUpdatePassword.resposta;

    console.log("[Auth] POST /auth/update-password - Atualizando senha...");

    const { userId, newPassword } = await c.req.json();

    console.log("[Auth] Dados recebidos:", { userId, hasPassword: !!newPassword });

    if (!userId || !newPassword) {
      return c.json({
        success: false,
        error: "User ID e nova senha são obrigatórios"
      }, 400);
    }

    const supabase = createClient(
      Deno.env.get("SUPABASE_URL") ?? "",
      Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? ""
    );

    // Atualizar senha do usuário
    console.log("[Auth] Atualizando senha no Supabase Auth...");
    const { data, error } = await supabase.auth.admin.updateUserById(
      userId,
      { password: newPassword }
    );

    if (error) {
      console.error("[Auth] âŒ Erro ao atualizar senha:", error);
      return c.json({
        success: false,
        error: error.message
      }, 400);
    }

    console.log("[Auth] âœ… Senha atualizada com sucesso!");

    return c.json({
      success: true,
      message: "Senha atualizada com sucesso",
      data: {
        userId: data.user?.id,
        email: data.user?.email,
      },
    });
  } catch (error: any) {
    console.error("[Auth] âŒ Erro inesperado ao atualizar senha:", error);
    return c.json({
      success: false,
      error: error.message
    }, 500);
  }
});

// Verificar sessão
app.get("/make-server-7249dcd9/auth/session", async (c) => {
  try {
    const authHeader = c.req.header("Authorization");
    const accessToken = authHeader?.split(" ")[1];

    if (!accessToken) {
      return c.json({
        success: false,
        error: "Token não fornecido"
      }, 401);
    }

    const supabase = createClient(
      Deno.env.get("SUPABASE_URL") ?? "",
      Deno.env.get("SUPABASE_ANON_KEY") ?? ""
    );

    const { data, error } = await supabase.auth.getUser(accessToken);

    if (error || !data.user) {
      return c.json({
        success: false,
        error: "Sessão inválida"
      }, 401);
    }

    const userMetadata = data.user.user_metadata || {};

    return c.json({
      success: true,
      data: {
        userId: data.user.id,
        email: data.user.email,
        empresaId: userMetadata.empresa_id || null,
        tipo: userMetadata.tipo || "cliente",
        nomeEmpresa: userMetadata.nome_empresa || null,
      },
    });
  } catch (error: any) {
    // console.error("[Auth] Erro ao verificar sessão:", error);
    return c.json({
      success: false,
      error: error.message
    }, 500);
  }
});

// Logout
app.post("/make-server-7249dcd9/auth/signout", async (c) => {
  try {
    const authHeader = c.req.header("Authorization");
    const accessToken = authHeader?.split(" ")[1];

    if (!accessToken) {
      return c.json({
        success: false,
        error: "Token não fornecido"
      }, 401);
    }

    const supabase = createClient(
      Deno.env.get("SUPABASE_URL") ?? "",
      Deno.env.get("SUPABASE_ANON_KEY") ?? ""
    );

    const { error } = await supabase.auth.signOut();

    if (error) {
      // console.error("[Auth] Erro ao fazer logout:", error);
      return c.json({
        success: false,
        error: error.message
      }, 500);
    }

    // console.log("[Auth] âœ… Logout realizado com sucesso");

    return c.json({
      success: true,
      message: "Logout realizado com sucesso",
    });
  } catch (error: any) {
    // console.error("[Auth] Erro no signout:", error);
    return c.json({
      success: false,
      error: error.message
    }, 500);
  }
});

// ========== ROTAS DE DEBUG ==========

// NOVO: Debug de empresa específica por NUIT
app.get("/make-server-7249dcd9/debug/empresa/:nuit", async (c) => {
  try {
    const acessoDebugEmpresa = await validarSuperAdminTonlineRequest(c);
    if (!acessoDebugEmpresa.permitido) return acessoDebugEmpresa.resposta;

    const nuit = c.req.param("nuit");
    // console.log(`ðŸ” [Debug] Verificando empresa com NUIT: ${nuit}`);

    // Buscar empresa por NUIT
    const empresaId = await kv.get(`empresa_nuit_index:${nuit}`);
    // console.log(`[Debug] ID da empresa: ${empresaId}`);

    if (!empresaId) {
      return c.json({
        success: false,
        error: "Empresa não encontrada",
        nuit
      });
    }

    // Buscar dados da empresa
    const empresa = await kv.get(`empresa:${empresaId}`);
    // console.log(`[Debug] Dados da empresa:`, empresa);

    // Buscar módulos da empresa
    const modulosEmpresa = await kv.get(`modulos_empresa:${empresaId}`);
    // console.log(`[Debug] Módulos da empresa:`, modulosEmpresa);

    // Buscar movimentos financeiros
    const movimentosRaw = await kv.getByPrefix("movimento:");
    const movimentos = movimentosRaw
      .filter((m: any) => m && m.empresaId === empresaId);
    // console.log(`[Debug] Movimentos financeiros: ${movimentos.length}`);

    return c.json({
      success: true,
      data: {
        nuit,
        empresaId,
        empresa,
        modulosEmpresa,
        totalModulos: Array.isArray(modulosEmpresa) ? modulosEmpresa.length : 0,
        movimentos,
        totalMovimentos: movimentos.length,
      }
    });
  } catch (error: any) {
    // console.error("[Debug] Erro ao verificar empresa:", error);
    return c.json({ success: false, error: error.message || String(error) }, 500);
  }
});

// ====================================================================
// ðŸ“Š ROTA DE DEBUG - SOMENTE LEITURA (SEGURA)
// ====================================================================
// Esta rota apenas LEITURA do banco e NÃƒO modifica dados
// Pode ser mantida em produção pois não apresenta riscos
// ====================================================================

// NOVO: Teste de criação simples de empresa
app.post("/make-server-7249dcd9/debug/teste-criar-empresa", async (c) => {
  try {
    const acessoTesteEmpresa = await validarSuperAdminTonlineRequest(c);
    if (!acessoTesteEmpresa.permitido) return acessoTesteEmpresa.resposta;

    console.log("ðŸ§ª [DEBUG TESTE] ================================");
    console.log("ðŸ§ª [DEBUG TESTE] Iniciando teste de criação...");

    // 1. Criar um objeto simples de teste
    const empresaTeste = {
      id: "teste_" + Date.now(),
      nomeComercial: "Empresa Teste",
      nuit: "999999999",
      email: "teste@teste.mz"
    };

    console.log("ðŸ§ª [DEBUG TESTE] Objeto de teste:", empresaTeste);

    // 2. Tentar salvar
    console.log("ðŸ§ª [DEBUG TESTE] Salvando com kv.set()...");
    const chave = `empresa:${empresaTeste.id}`;
    console.log("ðŸ§ª [DEBUG TESTE] Chave:", chave);

    const resultadoSet = await kv.set(chave, empresaTeste);
    console.log("ðŸ§ª [DEBUG TESTE] Resultado do kv.set():", resultadoSet);

    // 3. Tentar ler
    console.log("ðŸ§ª [DEBUG TESTE] Lendo com kv.get()...");
    const resultadoGet = await kv.get(chave);
    console.log("ðŸ§ª [DEBUG TESTE] Resultado do kv.get():", resultadoGet);

    // 4. Verificar com getByPrefix
    console.log("ðŸ§ª [DEBUG TESTE] Verificando com getByPrefix()...");
    const resultadoPrefix = await kv.getByPrefix("empresa:");
    console.log("ðŸ§ª [DEBUG TESTE] Resultado do getByPrefix():", resultadoPrefix.length, "items");
    console.log("ðŸ§ª [DEBUG TESTE] Estrutura RAW do primeiro item:", JSON.stringify(resultadoPrefix[0], null, 2));
    console.log("ðŸ§ª [DEBUG TESTE] Tipo do primeiro item:", typeof resultadoPrefix[0]);
    console.log("ðŸ§ª [DEBUG TESTE] Keys do primeiro item:", resultadoPrefix[0] ? Object.keys(resultadoPrefix[0]).join(', ') : 'n/a');

    const encontrado = resultadoPrefix.find((item: any) => item.key === chave);
    console.log("ðŸ§ª [DEBUG TESTE] Item encontrado no getByPrefix:", encontrado);

    // 5. Limpar após teste
    console.log("ðŸ§ª [DEBUG TESTE] Limpando teste...");
    await kv.del(chave);

    console.log("ðŸ§ª [DEBUG TESTE] ================================");

    return c.json({
      success: true,
      teste: {
        objeto_criado: empresaTeste,
        chave_usada: chave,
        set_result: resultadoSet,
        set_result_type: typeof resultadoSet,
        get_result: resultadoGet,
        get_result_type: typeof resultadoGet,
        get_result_null: resultadoGet === null,
        get_result_undefined: resultadoGet === undefined,
        prefix_total: resultadoPrefix.length,
        prefix_primeiro_item: resultadoPrefix[0],
        prefix_primeiro_keys: resultadoPrefix[0] ? Object.keys(resultadoPrefix[0]) : [],
        encontrado_prefix: !!encontrado,
        valor_encontrado: encontrado?.value
      }
    });
  } catch (error) {
    console.error("ðŸ§ª [DEBUG TESTE] Erro:", error);
    return c.json({ success: false, error: error.message, stack: error.stack }, 500);
  }
});

// NOVO: Verificar status do banco de dados
app.get("/make-server-7249dcd9/debug/banco", async (c) => {
  try {
    const acessoDebugBanco = await validarSuperAdminTonlineRequest(c);
    if (!acessoDebugBanco.permitido) return acessoDebugBanco.resposta;

    console.log("ðŸ” [DEBUG BANCO] ================================");
    console.log("ðŸ” [DEBUG BANCO] Verificando banco de dados...");

    // Buscar TODAS as empresas (raw)
    const empresasRaw = await kv.getByPrefix("empresa:");
    console.log(`ðŸ” [DEBUG BANCO] getByPrefix("empresa:") retornou ${empresasRaw.length} items`);
    console.log(`ðŸ” [DEBUG BANCO] Estrutura do primeiro item:`, empresasRaw[0]);

    // CORREÃ‡ÃƒO: getByPrefix() retorna os valores DIRETAMENTE, não {key, value}
    const empresas = empresasRaw.filter((e: any) =>
      e && e.id && !e.id.includes("_nuit_index") && !e.id.includes("_email_index")
    );
    console.log(`ðŸ” [DEBUG BANCO] Empresas filtradas: ${empresas.length}`);

    const empresasValidas = empresas.filter((e: any) => e && e.id && e.nomeComercial);
    console.log(`ðŸ” [DEBUG BANCO] Empresas válidas: ${empresasValidas.length}`);

    // Log detalhado de cada empresa
    empresasValidas.forEach((emp: any, idx: number) => {
      console.log(`ðŸ” [DEBUG BANCO] ${idx + 1}. ${emp.nomeComercial} (ID: ${emp.id}, NUIT: ${emp.nuit}, Email: ${emp.email})`);
    });

    // Buscar índices de NUIT (valores diretos)
    const nuitsRaw = await kv.getByPrefix("empresa_nuit_index:");
    console.log(`ðŸ” [DEBUG BANCO] Ãndices NUIT encontrados: ${nuitsRaw.length}`);
    nuitsRaw.forEach((item: any) => {
      console.log(`   - NUIT index: ${JSON.stringify(item)}`);
    });

    // Buscar índices de Email (valores diretos)
    const emailsRaw = await kv.getByPrefix("empresa_email_index:");
    console.log(`ðŸ” [DEBUG BANCO] Ãndices Email encontrados: ${emailsRaw.length}`);
    emailsRaw.forEach((item: any) => {
      console.log(`   - Email index: ${JSON.stringify(item)}`);
    });

    // Buscar usuários (valores diretos)
    const usuariosRaw = await kv.getByPrefix("usuario:");
    const usuarios = usuariosRaw.filter((u: any) => u && u.id && !u.id.includes(":email:"));

    // Buscar módulos (valores diretos)
    const modulosRaw = await kv.getByPrefix("modulos:");
    const modulos = modulosRaw;

    // Buscar pagamentos (valores diretos)
    const pagamentosRaw = await kv.getByPrefix("pagamento:");
    const pagamentos = pagamentosRaw;

    // Buscar flags do sistema (valores diretos)
    const flagsRaw = await kv.getByPrefix("sistema:");
    const flags = flagsRaw;

    console.log(`ðŸ“Š [DEBUG BANCO] RESUMO FINAL:`);
    console.log(`   Empresas Total: ${empresas.length}`);
    console.log(`   Empresas Válidas: ${empresasValidas.length}`);
    console.log(`   Ãndices NUIT: ${nuitsRaw.length}`);
    console.log(`   Ãndices Email: ${emailsRaw.length}`);
    console.log(`   Usuários: ${usuarios.length}`);
    console.log(`   Módulos: ${modulos.length}`);
    console.log(`   Pagamentos: ${pagamentos.length}`);
    console.log(`   Flags: ${flags.length}`);
    console.log("ðŸ” [DEBUG BANCO] ================================");

    return c.json({
      resumo: {
        empresas_total: empresas.length,
        empresas_validas: empresasValidas.length,
        empresas_invalidas: empresas.length - empresasValidas.length,
        indices_nuit: nuitsRaw.length,
        indices_email: emailsRaw.length,
        usuarios: usuarios.length,
        modulos: modulos.length,
        pagamentos: pagamentos.length,
        flags_sistema: flags.length,
      },
      empresas_detalhes: empresasValidas.map((e: any) => ({
        id: e.id,
        nomeComercial: e.nomeComercial,
        nuit: e.nuit,
        email: e.email,
        status: e.status,
      })),
      indices_nuit: nuitsRaw,
      indices_email: emailsRaw,
      empresas_invalidas: empresas.filter((e: any) => !e || !e.id || !e.nomeComercial),
      usuarios_emails: usuarios.map((u: any) => u.email),
      flags_sistema: flags,
    });
  } catch (error: any) {
    console.error("[DEBUG BANCO] Erro ao verificar banco:", error);
    return c.json({ success: false, error: error.message || String(error) }, 500);
  }
});

// ====================================================================
// âš ï¸ ATENÃ‡ÃƒO: ROTA DESTRUTIVA - SQL DIRETO
// ====================================================================
// Esta rota APAGA TODOS os dados usando DELETE SQL direto
// ðŸ”’ NUNCA deve ser usada em produçï¿½ï¿½o
// ðŸ”’ Para desativar: Comente o bloco completo abaixo
// ====================================================================

// NOVO: Limpar banco COMPLETAMENTE (SQL DIRETO)
app.post("/make-server-7249dcd9/debug/limpar-sql-direto", async (c) => {
  try {
    const acessoLimparSql = await validarSuperAdminTonlineRequest(c);
    if (!acessoLimparSql.permitido) return acessoLimparSql.resposta;

    // console.log("ðŸ’¥ [Debug] LIMPANDO BANCO COM SQL DIRETO...");

    const supabase = createClient(
      Deno.env.get("SUPABASE_URL") ?? "",
      Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? ""
    );

    // 1. DELETAR TUDO da tabela kv_store_7249dcd9
    // console.log("ðŸ—‘ï¸ [Debug] Executando DELETE FROM kv_store_7249dcd9...");

    const { data, error, count } = await supabase
      .from("kv_store_7249dcd9")
      .delete()
      .neq("key", "___IMPOSSIBLE___"); // Truque para deletar TUDO

    if (error) {
      // console.error("âŒ [Debug] Erro ao deletar:", error);
      return c.json({ success: false, error: error.message }, 500);
    }

    // console.log(`âœ… [Debug] Tabela limpa! ${count || 'Todos'} registros removidos`);

    // 2. Verificar se realmente está vazio
    const { data: verificacao, count: countVerificacao } = await supabase
      .from("kv_store_7249dcd9")
      .select("*", { count: "exact" });

    // console.log(`ðŸ“Š [Debug] Verificação: ${countVerificacao} registros restantes`);

    return c.json({
      success: true,
      message: `Banco limpo com SQL direto! ${countVerificacao} registros restantes (deve ser 0)`,
      detalhes: {
        registros_restantes: countVerificacao,
        verificacao: verificacao?.length || 0,
      }
    });
  } catch (error: any) {
    // console.error("[Debug] Erro ao limpar banco com SQL:", error);
    return c.json({ success: false, error: error.message || String(error) }, 500);
  }
});

// ====================================================================
// âš ï¸ ATENÃ‡ÃƒO: ROTA DESTRUTIVA - LIMPAR BANCO VIA KV
// ====================================================================
// Esta rota APAGA TODOS os dados via operaçÃµes KV
// ðŸ”’ NUNCA deve ser usada em produção
// ðŸ”’ Para desativar: Comente o bloco completo abaixo
// ====================================================================

// NOVO: Limpar banco COMPLETAMENTE
app.post("/make-server-7249dcd9/debug/limpar-banco-completo", async (c) => {
  try {
    const acessoLimparBanco = await validarSuperAdminTonlineRequest(c);
    if (!acessoLimparBanco.permitido) return acessoLimparBanco.resposta;

    // console.log("ðŸ—‘ï¸ [Debug] LIMPANDO BANCO COMPLETAMENTE...");

    let totalRemovido = 0;

    // 1. Buscar TODAS as empresas
    const empresasRaw = await kv.getByPrefix("empresa:");
    const empresas = empresasRaw.filter((e: any) => e && e.id);
    // console.log(`ðŸ“‹ [Debug] Encontradas ${empresas.length} empresas`);

    for (const emp of empresas) {
      await kv.del(`empresa:${emp.id}`);
      // console.log(`   ðŸ—‘ï¸ Removida: empresa:${emp.id}`);
      totalRemovido++;
    }

    // 2. LIMPAR ÃNDICES DE NUIT
    // console.log("ðŸ—‘ï¸ [Debug] Limpando índices de NUIT...");
    const indicesNuit = await kv.getByPrefix("empresa_nuit_index:");
    for (const idx of indicesNuit) {
      await kv.del(idx.key);
      // console.log(`   ðŸ—‘ï¸ Removido índice NUIT: ${idx.key}`);
      totalRemovido++;
    }

    // 3. LIMPAR ÃNDICES DE EMAIL
    // console.log("ðŸ—‘ï¸ [Debug] Limpando índices de EMAIL...");
    const indicesEmail = await kv.getByPrefix("empresa_email_index:");
    for (const idx of indicesEmail) {
      await kv.del(idx.key);
      // console.log(`   ðŸ—‘ï¸ Removido índice EMAIL: ${idx.key}`);
      totalRemovido++;
    }

    // 4. Buscar TODOS os usuários
    const usuariosRaw = await kv.getByPrefix("usuario:");
    const usuarios = usuariosRaw
      .filter((u: any) => u && u.email && u.id && !u.id.includes(":email:"));
    // console.log(`ðŸ“‹ [Debug] Encontrados ${usuarios.length} usuários`);

    for (const usr of usuarios) {
      await kv.del(`usuario:${usr.email}`);
      // console.log(`   ðŸ—‘ï¸ Removido: usuario:${usr.email}`);
      totalRemovido++;
    }

    // 5. LIMPAR ÃNDICES DE EMAIL DE USUÃRIOS
    const indicesEmailUsuarios = await kv.getByPrefix("usuario:email:");
    for (const idx of indicesEmailUsuarios) {
      await kv.del(idx.key);
      // console.log(`   ðŸ—‘ï¸ Removido índice EMAIL usuário: ${idx.key}`);
      totalRemovido++;
    }

    // 6. Buscar TODOS os módulos
    const modulosRaw = await kv.getByPrefix("modulos:");
    const modulos = modulosRaw.filter((m: any) => m);
    // console.log(`ðŸ“‹ [Debug] Encontrados ${modulos.length} módulos`);

    // Para deletar, precisamos das chaves - buscar novamente com getByPrefixWithKeys
    const modulosComChaves = await kv.getByPrefixWithKeys("modulos:");
    for (const mod of modulosComChaves) {
      await kv.del(mod.key);
      // console.log(`   ðŸ—‘ï¸ Removido: ${mod.key}`);
      totalRemovido++;
    }

    // 7. Buscar TODOS os pagamentos
    const pagamentosRaw = await kv.getByPrefix("pagamento:");
    const pagamentos = pagamentosRaw.filter((p: any) => p);
    // console.log(`ðŸ“‹ [Debug] Encontrados ${pagamentos.length} pagamentos`);

    for (const pag of pagamentosRaw) {
      await kv.del(pag.key);
      // console.log(`   ðŸ—‘ï¸ Removido: ${pag.key}`);
      totalRemovido++;
    }

    // 8. Limpar flags do sistema
    await kv.del("sistema:inicializado_v3");
    await kv.del("sistema:inicializado_v2");
    await kv.del("sistema:inicializado");
    await kv.del("sistema:modo_limpo");
    // console.log("ðŸ—‘ï¸ [Debug] Flags do sistema removidas");

    // console.log(`âœ… [Debug] LIMPEZA COMPLETA! ${totalRemovido} registros removidos`);

    return c.json({
      success: true,
      message: `Banco limpo completamente! ${totalRemovido} registros removidos`,
      detalhes: {
        empresas: empresas.length,
        indices_nuit: indicesNuit.length,
        indices_email: indicesEmail.length,
        usuarios: usuarios.length,
        modulos: modulos.length,
        pagamentos: pagamentos.length,
        total: totalRemovido,
      }
    });
  } catch (error: any) {
    // console.error("[Debug] Erro ao limpar banco:", error);
    return c.json({ success: false, error: error.message || String(error) }, 500);
  }
});

// NOVO: Limpar APENAS movimentos com prefixo incorreto
app.post("/make-server-7249dcd9/debug/limpar-movimentos-duplicados", async (c) => {
  try {
    const acessoLimparMovDup = await validarSuperAdminTonlineRequest(c);
    if (!acessoLimparMovDup.permitido) return acessoLimparMovDup.resposta;

    // console.log("ðŸ§¹ [Debug] Limpando movimentos com prefixo incorreto...");

    let totalRemovido = 0;

    // Limpar movimentos antigos com prefixo errado "movimento:"
    // console.log("ðŸ—‘ï¸ [Debug] Buscando movimentos com prefixo 'movimento:'...");
    const movimentosAntigos = await kv.getByPrefix("movimento:");
    // console.log(`ðŸ“‹ [Debug] Encontrados ${movimentosAntigos.length} movimentos com prefixo incorreto`);

    for (const mov of movimentosAntigos) {
      await kv.del(mov.key);
      // console.log(`   ðŸ—‘ï¸ Removido: ${mov.key}`);
      totalRemovido++;
    }

    // console.log(`âœ… [Debug] Limpeza concluída! ${totalRemovido} movimentos removidos`);

    return c.json({
      success: true,
      message: `${totalRemovido} movimentos com prefixo incorreto foram removidos`,
      detalhes: {
        movimentos_removidos: totalRemovido,
      }
    });
  } catch (error: any) {
    // console.error("[Debug] Erro ao limpar movimentos:", error);
    return c.json({ success: false, error: error.message || String(error) }, 500);
  }
});

// ========== ROTAS DE EMPRESAS ==========

// Listar empresas
// Rotas de Empresas (CRUD) movidas para admin-router.tsx (admin-server-7249dcd9)

// ========== ROTAS DE MÃ“DULOS ==========

// Listar todos os módulos disponíveis
app.get("/make-server-7249dcd9/modulos", async (c) => {
  try {
    return c.json({ success: true, data: modulos.MODULOS_SISTEMA });
  } catch (error: any) {
    // console.error("[API] Erro ao listar módulos:", error);
    return c.json({ success: false, error: error.message || String(error) }, 500);
  }
});

// Listar planos disponíveis
app.get("/make-server-7249dcd9/planos", async (c) => {
  try {
    const planos = await modulos.obterPlanosDisponiveisConfigurados();
    return c.json({ success: true, data: planos });
  } catch (error: any) {
    // console.error("[API] Erro ao listar planos:", error);
    return c.json({ success: false, error: error.message || String(error) }, 500);
  }
});

app.get("/make-server-7249dcd9/public/subscricao-config", async (c) => {
  try {
    const config = await tonlineConfig.obterSubscricaoConfig();
    return c.json({
      success: true,
      data: {
        planos: config.planos.filter((plano) => plano.ativo !== false),
        politica: config.politica,
      },
    });
  } catch (error: any) {
    return c.json({ success: false, error: error.message || String(error) }, 500);
  }
});

// Rotas GET/PUT /tonline/subscricao-config movidas para admin-router.tsx

// Obter módulos de uma empresa
app.get("/make-server-7249dcd9/empresas/:id/exercicios-economicos", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("id");
    const acesso = await validarAcessoEmpresaRequest(c, empresaId);
    if (!acesso.permitido) return acesso.resposta;

    const exercicios = await exerciciosEconomicos.listarExerciciosEmpresa(empresaId);
    const atual = await exerciciosEconomicos.obterExercicioAtual(empresaId);
    return c.json({ success: true, data: { exercicios, atual } });
  } catch (error: any) {
    return c.json({ success: false, error: error.message || String(error) }, 500);
  }
});

app.get("/make-server-7249dcd9/empresas/:id/exercicios-economicos/actual", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("id");
    const acesso = await validarAcessoEmpresaRequest(c, empresaId);
    if (!acesso.permitido) return acesso.resposta;

    const dataReferencia = c.req.query("dataReferencia") || undefined;
    const atual = await exerciciosEconomicos.garantirExercicioParaData(empresaId, dataReferencia);
    return c.json({ success: true, data: atual });
  } catch (error: any) {
    return c.json({ success: false, error: error.message || String(error) }, 500);
  }
});

app.post("/make-server-7249dcd9/empresas/:id/exercicios-economicos", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("id");
    const acesso = await validarAcessoEmpresaRequest(c, empresaId);
    if (!acesso.permitido) return acesso.resposta;

    const dados = await lerBodyJsonSeguro(c);
    const exercicios = await exerciciosEconomicos.salvarExercicioEmpresa(empresaId, dados, acesso.usuario?.id);
    return c.json({ success: true, data: exercicios });
  } catch (error: any) {
    return c.json({ success: false, error: error.message || String(error) }, 400);
  }
});

app.put("/make-server-7249dcd9/empresas/:id/exercicios-economicos/:exercicioId", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("id");
    const exercicioId = c.req.param("exercicioId");
    const acesso = await validarAcessoEmpresaRequest(c, empresaId);
    if (!acesso.permitido) return acesso.resposta;

    const dados = await lerBodyJsonSeguro(c);
    const exercicios = await exerciciosEconomicos.salvarExercicioEmpresa(
      empresaId,
      { ...dados, id: exercicioId },
      acesso.usuario?.id,
    );
    return c.json({ success: true, data: exercicios });
  } catch (error: any) {
    return c.json({ success: false, error: error.message || String(error) }, 400);
  }
});

app.patch("/make-server-7249dcd9/empresas/:id/exercicios-economicos/:exercicioId/estado", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("id");
    const exercicioId = c.req.param("exercicioId");
    const acesso = await validarAcessoEmpresaRequest(c, empresaId);
    if (!acesso.permitido) return acesso.resposta;

    const dados = await lerBodyJsonSeguro(c);
    const exercicios = await exerciciosEconomicos.alterarEstadoExercicioEmpresa(
      empresaId,
      exercicioId,
      dados.estado,
      acesso.usuario?.id,
      dados.observacoes,
    );
    return c.json({ success: true, data: exercicios });
  } catch (error: any) {
    return c.json({ success: false, error: error.message || String(error) }, 400);
  }
});

// Rotas /tonline/empresas/:id/exercicios-economicos* movidas para admin-router.tsx

// Checkout publico de subscricao por M-Pesa
app.post("/make-server-7249dcd9/public/subscricoes/mpesa-checkout", async (c) => {
  try {
    const dados = await c.req.json();
    const planoId = dados?.planoId || "mensal";
    const plano = await modulos.obterPlanoConfiguradoPorId(planoId);

    if (!plano || plano.legado) {
      return c.json({ success: false, error: "Plano publico invalido" }, 400);
    }

    const nomeComercial = String(dados?.nomeComercial || "").trim();
    const nuit = String(dados?.nuit || "").trim();
    const emailAdmin = String(dados?.emailAdmin || "").trim().toLowerCase();
    const telefoneMpesa = String(dados?.telefoneMpesa || "").trim();
    const codigoReferencia = String(dados?.codigoReferencia || "").trim();

    if (!nomeComercial || !nuit || !emailAdmin || !telefoneMpesa) {
      return c.json({
        success: false,
        error: "Nome comercial, NUIT, email do administrador e telefone M-Pesa sao obrigatorios",
      }, 400);
    }

    const nuitNormalizado = nuit.replace(/\D/g, "");
    if (nuitNormalizado.length !== 9) {
      return c.json({ success: false, error: "NUIT invalido. Deve ter 9 digitos." }, 400);
    }

    if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emailAdmin)) {
      return c.json({ success: false, error: "Email do administrador invalido" }, 400);
    }

    try {
      mpesa.normalizarTelefoneMpesa(telefoneMpesa);
    } catch (error: any) {
      return c.json({ success: false, error: error.message || "Telefone M-Pesa invalido" }, 400);
    }

    const empresaExistenteAntesPagamento = await empresasModule.buscarEmpresaPorNuit(nuitNormalizado);
    if (empresaExistenteAntesPagamento) {
      return c.json({
        success: false,
        error: `NUIT ja cadastrado para ${empresaExistenteAntesPagamento.nomeComercial || "esta empresa"}. Entre no ERP para renovar a subscricao ou contacte o suporte. Nenhuma cobranca foi iniciada.`,
        data: {
          empresaExistente: {
            id: empresaExistenteAntesPagamento.id,
            nomeComercial: empresaExistenteAntesPagamento.nomeComercial,
            email: empresaExistenteAntesPagamento.email,
          },
        },
      }, 409);
    }

    const empresaComEmailAntesPagamento = await empresasModule.buscarEmpresaPorEmail(emailAdmin);
    if (empresaComEmailAntesPagamento) {
      return c.json({
        success: false,
        error: `Email ja cadastrado para ${empresaComEmailAntesPagamento.nomeComercial || "esta empresa"}. Entre no ERP para renovar a subscricao ou contacte o suporte. Nenhuma cobranca foi iniciada.`,
        data: {
          empresaExistente: {
            id: empresaComEmailAntesPagamento.id,
            nomeComercial: empresaComEmailAntesPagamento.nomeComercial,
            email: empresaComEmailAntesPagamento.email,
          },
        },
      }, 409);
    }

    const usuarioComEmailAntesPagamento = await usuarios.buscarUsuarioPorEmail(emailAdmin);
    if (usuarioComEmailAntesPagamento) {
      return c.json({
        success: false,
        error: "Email ja pertence a um utilizador do sistema. Entre no ERP para renovar a subscricao ou contacte o suporte. Nenhuma cobranca foi iniciada.",
        data: {
          usuarioExistente: {
            id: usuarioComEmailAntesPagamento.id,
            nome: usuarioComEmailAntesPagamento.nome,
            email: usuarioComEmailAntesPagamento.email,
            empresaId: usuarioComEmailAntesPagamento.empresaId,
          },
        },
      }, 409);
    }

    const reservasCadastro = [
      `mpesa_signup_nuit:${nuitNormalizado}`,
      `mpesa_signup_email:${emailAdmin}`,
    ];
    const reservaCadastro = await reservarChavesPagamento(
      reservasCadastro,
      {
        tipo: "cadastro",
        nuit: nuitNormalizado,
        emailAdmin,
        nomeComercial,
        planoId: plano.id,
      },
      RESERVA_CADASTRO_TTL_MS,
    );

    if (!reservaCadastro.success) {
      return c.json({
        success: false,
        error: "Ja existe um pedido de activacao em processamento para este NUIT ou email. Aguarde alguns minutos antes de tentar novamente.",
      }, 409);
    }

    const checkoutResult = await mpesa.criarCheckoutC2B({
      planoId: plano.id,
      planoNome: plano.nome,
      nomeComercial,
      nuit: nuitNormalizado,
      emailAdmin,
      telefoneMpesa,
      valorPlano: plano.avencaTotal,
      taxaLicenca: plano.taxaInscricaoTotal,
      cicloMeses: plano.cicloMeses || 1,
    });

    const checkout = checkoutResult.checkout;

    if (!checkoutResult.success || !checkout || checkout.status !== "PAID") {
      if (mpesa.checkoutMpesaTemResultadoAmbiguo(checkout)) {
        return c.json({
          success: false,
          pending: true,
          status: "PENDING",
          error: checkoutResult.error || "O resultado do pagamento M-Pesa esta pendente. Aguarde antes de tentar novamente.",
          data: { checkout, pagamentoPendente: true },
        }, 202);
      }

      await libertarReservasPagamento(reservasCadastro);
      return c.json({
        success: false,
        error: checkoutResult.error || "Pagamento M-Pesa nao confirmado",
        data: { checkout },
      }, checkout?.status === "CONFIG_ERROR" ? 500 : 400);
    }

    const revendedorReferente = codigoReferencia
      ? await revendedores.buscarRevendedorPorCodigo(codigoReferencia)
      : null;

    const empresaResult = await empresasModule.criarEmpresa({
      nomeEmpresa: nomeComercial,
      nomeComercial,
      nuit: nuitNormalizado,
      email: emailAdmin,
      telefone: telefoneMpesa,
      telemovel: telefoneMpesa,
      plano: plano.nome,
      taxaInscricao: plano.taxaInscricaoTotal,
      valorAvenca: plano.avencaTotal,
      paymentStatus: "em-dia",
      regimeFiscal: "regime-geral-iva",
      tratamentoFiscalPadrao: "iva-normal",
      taxaIvaPadrao: 16,
      moedaPadrao: "MZN",
      metodoInventario: "FIFO",
      criadoPor: "Checkout M-Pesa",
      observacoes: `Empresa criada automaticamente pelo checkout M-Pesa ${checkout.thirdPartyReference}`,
      referidoPor: revendedorReferente?.id || undefined,
    });

    let empresa = empresaResult.data;

    if (!empresaResult.success || !empresa) {
      const empresaExistenteDepoisPagamento = await empresasModule.buscarEmpresaPorNuit(nuitNormalizado);
      await marcarReservasPagamento(reservasCadastro, "REVIEW_REQUIRED", {
        checkoutId: checkout.id,
        thirdPartyReference: checkout.thirdPartyReference,
        erroProvisionamento: empresaResult.error,
      });

      return c.json({
        success: false,
        error: empresaExistenteDepoisPagamento
          ? `Pagamento confirmado, mas o NUIT ja pertence a ${empresaExistenteDepoisPagamento.nomeComercial}. A associacao precisa de revisao manual.`
          : `Pagamento confirmado, mas a empresa nao foi criada: ${empresaResult.error}`,
        data: { checkout, pagamentoConfirmado: true, empresaExistente: empresaExistenteDepoisPagamento || null },
      }, 202);
    }

    if (!empresa) {
      await marcarReservasPagamento(reservasCadastro, "REVIEW_REQUIRED", {
        checkoutId: checkout.id,
        thirdPartyReference: checkout.thirdPartyReference,
        erroProvisionamento: empresaResult.error,
      });
      return c.json({
        success: false,
        error: `Pagamento confirmado, mas a empresa nao foi criada: ${empresaResult.error}`,
        data: { checkout, pagamentoConfirmado: true },
      }, 202);
    }

    const subscricaoResult = await subscricoes.criarSubscricao(empresa.id, plano.id, {
      licencaPaga: true,
    });

    if (!subscricaoResult.success) {
      await marcarReservasPagamento(reservasCadastro, "REVIEW_REQUIRED", {
        checkoutId: checkout.id,
        empresaId: empresa.id,
        thirdPartyReference: checkout.thirdPartyReference,
        erroProvisionamento: subscricaoResult.error,
      });
      return c.json({
        success: false,
        error: `Empresa criada e pagamento confirmado, mas a subscricao nao foi criada: ${subscricaoResult.error}`,
        data: { checkout, empresa, pagamentoConfirmado: true },
      }, 202);
    }

    const sincronizacaoResult = await subscricoes.sincronizarModulosComSubscricao(empresa.id);
    if (!sincronizacaoResult.success) {
      const fallbackPlano = await modulos.aplicarPlano(empresa.id, plano.id);
      if (!fallbackPlano.success) {
        await marcarReservasPagamento(reservasCadastro, "REVIEW_REQUIRED", {
          checkoutId: checkout.id,
          empresaId: empresa.id,
          subscricaoId: subscricaoResult.data?.id,
          thirdPartyReference: checkout.thirdPartyReference,
          erroProvisionamento: sincronizacaoResult.error || fallbackPlano.error,
        });
        return c.json({
          success: false,
          error: `Subscricao criada, mas os modulos nao foram activados: ${sincronizacaoResult.error || fallbackPlano.error}`,
          data: { checkout, empresa, subscricao: subscricaoResult.data, pagamentoConfirmado: true },
        }, 202);
      }
    }

    const dataPagamento = new Date().toISOString();
    const numeroDocumento = checkout.transactionId || checkout.thirdPartyReference;
    const snapshotPrimeiroPagamento = criarSnapshotPagamento({
      tipo: "primeiro_pagamento",
      plano,
      valorRecorrente: plano.avencaTotal,
      taxaLicenca: plano.taxaInscricaoTotal,
      cicloMeses: plano.cicloMeses || 1,
      checkout,
      dataProximaRenovacao: subscricaoResult.data?.dataProximaRenovacao,
    });

    if (plano.taxaInscricaoTotal > 0) {
      await pagamentos.registrarTaxaInscricao(
        empresa.id,
        plano.taxaInscricaoTotal,
        "mpesa",
        numeroDocumento,
        undefined,
        `Pagamento M-Pesa confirmado. Referencia: ${checkout.thirdPartyReference}`,
        snapshotPrimeiroPagamento
      );
    }

    const movimentoAvencaResult = await pagamentos.registrarPagamentoAvenca(
      empresa.id,
      plano.avencaTotal,
      plano.nome,
      "mpesa",
      numeroDocumento,
      undefined,
      `Pagamento M-Pesa confirmado. Referencia: ${checkout.thirdPartyReference}`,
      plano.cicloMeses || 1,
      snapshotPrimeiroPagamento
    );

    if (revendedorReferente) {
      await revendedores.registrarComissaoSeAplicavel(
        empresa.id,
        plano.avencaTotal,
        movimentoAvencaResult?.data?.id,
      );
    }

    await empresasModule.atualizarEmpresaSemValidacao(empresa.id, {
      plano: plano.nome,
      taxaInscricao: plano.taxaInscricaoTotal,
      valorAvenca: plano.avencaTotal,
      paymentStatus: "em-dia",
      proximoPagamento: subscricaoResult.data?.dataProximaRenovacao?.split("T")[0],
    });

    const senhaTemporaria = gerarSenhaTemporaria();
    const usuarioResult = await usuarios.criarUsuario({
      email: emailAdmin,
      password: senhaTemporaria,
      nome: nomeComercial,
      empresaId: empresa.id,
      nivel: "admin_empresa",
      modulosPermitidos: plano.modulos,
    });

    const checkoutProvisionado = await mpesa.marcarProvisionado(checkout.id, {
      empresaId: empresa.id,
      usuarioId: usuarioResult.data?.id,
      credenciaisGeradas: usuarioResult.success
        ? {
            email: emailAdmin,
            senhaTemporaria,
          }
        : undefined,
    });
    await marcarReservasPagamento(reservasCadastro, "COMPLETED", {
      checkoutId: checkout.id,
      empresaId: empresa.id,
      usuarioId: usuarioResult.data?.id,
      thirdPartyReference: checkout.thirdPartyReference,
    });

    if (!usuarioResult.success) {
      return c.json({
        success: false,
        error: `Empresa e subscricao criadas, mas o usuario administrador nao foi criado: ${usuarioResult.error}`,
        data: {
          checkout: checkoutProvisionado || checkout,
          empresa,
          subscricao: subscricaoResult.data,
          pagamentoConfirmado: true,
        },
      }, 202);
    }

    return c.json({
      success: true,
      message: "Pagamento M-Pesa confirmado. Empresa, subscricao e administrador criados com sucesso.",
      data: {
        checkout: checkoutProvisionado || checkout,
        empresa,
        subscricao: subscricaoResult.data,
        usuario: usuarioResult.data,
        credenciais: {
          email: emailAdmin,
          senhaTemporaria,
        },
        dataPagamento,
      },
    });
  } catch (error: any) {
    return c.json({ success: false, error: error.message || String(error) }, 500);
  }
});

app.get("/make-server-7249dcd9/public/subscricoes/mpesa-checkout/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const checkout = await mpesa.obterCheckout(id);

    if (!checkout) {
      return c.json({ success: false, error: "Checkout M-Pesa nao encontrado" }, 404);
    }

    return c.json({ success: true, data: checkout });
  } catch (error: any) {
    return c.json({ success: false, error: error.message || String(error) }, 500);
  }
});

app.post("/make-server-7249dcd9/public/subscricoes/reemitir-credenciais", async (c) => {
  try {
    const dados = await lerBodyJsonSeguro(c);
    const referencia = String(dados?.referencia || dados?.checkoutId || dados?.thirdPartyReference || "").trim();
    const nuit = String(dados?.nuit || "").replace(/\D/g, "");
    const emailAdmin = String(dados?.emailAdmin || "").trim().toLowerCase();

    if (!referencia || (!nuit && !emailAdmin)) {
      return c.json({
        success: false,
        error: "Informe a referencia M-Pesa e o NUIT ou email do administrador.",
      }, 400);
    }

    const checkout = await mpesa.obterCheckout(referencia);
    if (!checkout) {
      return c.json({ success: false, error: "Checkout M-Pesa nao encontrado" }, 404);
    }

    const checkoutEmail = String(checkout.emailAdmin || checkout.credenciaisGeradas?.email || "").trim().toLowerCase();
    const checkoutNuit = String(checkout.nuit || "").replace(/\D/g, "");
    const dadosConferem =
      (emailAdmin && emailAdmin === checkoutEmail) ||
      (nuit && nuit === checkoutNuit);

    if (!dadosConferem) {
      return c.json({ success: false, error: "Os dados informados nao conferem com o checkout." }, 403);
    }

    if (checkout.status !== "PAID" || !checkout.empresaId) {
      return c.json({
        success: false,
        error: "Este checkout ainda nao esta provisionado para reemitir credenciais.",
      }, 400);
    }

    const novaSenha = gerarSenhaTemporaria();
    const resetResult = await usuarios.redefinirSenhaUsuarioPorEmail(checkoutEmail, novaSenha);
    if (!resetResult.success) {
      return c.json({ success: false, error: resetResult.error || "Nao foi possivel reemitir credenciais" }, 400);
    }

    const checkoutAtualizado = await mpesa.marcarProvisionado(checkout.id, {
      empresaId: checkout.empresaId,
      usuarioId: resetResult.data?.id || checkout.usuarioId,
      credenciaisGeradas: {
        email: checkoutEmail,
        senhaTemporaria: novaSenha,
      },
    });

    return c.json({
      success: true,
      message: "Credenciais do administrador reemitidas com sucesso.",
      data: {
        checkout: checkoutAtualizado || checkout,
        credenciais: {
          email: checkoutEmail,
          senhaTemporaria: novaSenha,
        },
      },
    });
  } catch (error: any) {
    return c.json({ success: false, error: error.message || String(error) }, 500);
  }
});

// Rotas GET/POST /empresas/:id/modulos movidas para admin-router.tsx

// ========== ROTAS DE TEMPLATES DE DOCUMENTOS ==========

// Obter configuração de templates da empresa
app.get("/make-server-7249dcd9/empresas/:id/templates", async (c) => {
  try {
    const empresaId = c.req.param("id");

    // Buscar configuração no KV Store
    const configKey = `empresa:${empresaId}:templates`;
    const config = await kv.get(configKey);

    if (config) {
      return c.json({ success: true, data: config });
    }

    // Se não existe, retornar padrão (todos clássico)
    const configPadrao = {
      empresaId,
      templates: {
        cotacao: 'classico',
        factura: 'classico',
        recibo: 'classico',
        notaCredito: 'classico',
        notaDebito: 'classico',
        vd: 'classico',
        adiantamento: 'classico'
      },
      atualizadoEm: new Date().toISOString(),
      atualizadoPor: 'sistema'
    };

    return c.json({ success: true, data: configPadrao });
  } catch (error: any) {
    console.error("[API] Erro ao obter templates:", error);
    return c.json({ success: false, error: error.message || String(error) }, 500);
  }
});

// Salvar configuração de templates da empresa
app.post("/make-server-7249dcd9/empresas/:id/templates", async (c) => {
  try {
    const empresaId = c.req.param("id");
    const { templates, usuarioId } = await c.req.json();

    // Validar dados
    if (!templates) {
      return c.json({ success: false, error: "Templates não fornecidos" }, 400);
    }

    const config = {
      empresaId,
      templates,
      atualizadoEm: new Date().toISOString(),
      atualizadoPor: usuarioId || 'sistema'
    };

    // Salvar no KV Store
    const configKey = `empresa:${empresaId}:templates`;
    await kv.set(configKey, config);

    return c.json({ success: true, data: config });
  } catch (error: any) {
    console.error("[API] Erro ao salvar templates:", error);
    return c.json({ success: false, error: error.message || String(error) }, 500);
  }
});

// ========== ROTAS DE PREFERÃŠNCIAS DE TEMPLATES (COM CORES) ==========

// Buscar preferências de templates da empresa (modelo + cor)
app.get("/make-server-7249dcd9/empresas/template-preferencias/:empresaId", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");

    console.log(`[API] Buscando preferências de templates para empresa: ${empresaId}`);

    // Buscar do KV Store
    const chave = `template_preferencias:${empresaId}`;
    const preferencias = await kv.get(chave);

    if (preferencias) {
      return c.json({
        success: true,
        preferencias
      });
    }

    // Retornar null se não existir (frontend vai inicializar)
    return c.json({
      success: true,
      preferencias: null
    });
  } catch (error: any) {
    console.error("[API] Erro ao buscar preferências de templates:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Salvar preferências de templates da empresa (modelo + cor)
app.post("/make-server-7249dcd9/empresas/template-preferencias", async (c) => {
  try {
    const { empresaId, preferencias } = await c.req.json();

    if (!empresaId || !preferencias) {
      return c.json({
        success: false,
        error: "empresaId e preferencias são obrigatórios"
      }, 400);
    }

    console.log(`[API] Salvando preferências de templates para empresa: ${empresaId}`);

    // Salvar no KV Store
    const chave = `template_preferencias:${empresaId}`;
    await kv.set(chave, preferencias);

    console.log(`[API] âœ… Preferências salvas com sucesso`);

    return c.json({
      success: true,
      message: "Preferências salvas com sucesso"
    });
  } catch (error: any) {
    console.error("[API] Erro ao salvar preferências de templates:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.get("/make-server-7249dcd9/empresas/:empresaId/pos-validade-config", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const acesso = await validarAcessoEmpresaRequest(c, empresaId);
    if (!acesso.permitido) return acesso.resposta;

    const config = await posValidadeConfig.obterConfiguracaoPosValidade(empresaId);
    return c.json({ success: true, data: config });
  } catch (error: any) {
    console.error("[API] Erro ao buscar configuração POS/validade:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.post("/make-server-7249dcd9/empresas/:empresaId/pos-validade-config", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const acesso = await validarAcessoEmpresaRequest(c, empresaId);
    if (!acesso.permitido) return acesso.resposta;

    const dados = await lerBodyJsonSeguro(c);
    const config = await posValidadeConfig.salvarConfiguracaoPosValidade(empresaId, dados);
    return c.json({ success: true, data: config });
  } catch (error: any) {
    console.error("[API] Erro ao salvar configuração POS/validade:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Aplicar plano pré-configurado
// Rotas /empresas/:id/aplicar-plano e PATCH /empresas/:id/modulos/:moduloId movidas para admin-router.tsx

// Rotas de Subscricoes (GET/renovar/mpesa-renovar da empresa + operacoes em massa) movidas para admin-router.tsx (admin-server-7249dcd9)
// Rotas de Pagamentos (POST /pagamentos, pagar-avenca, movimentos, conta-corrente, anos-fiscais, status, delete) movidas para admin-router.tsx (admin-server-7249dcd9)

// ========== ROTAS DE USUÃRIOS ==========

// Rota GET /usuarios (listar todos) movida para admin-router.tsx (admin-server-7249dcd9)
// Listar usuários de uma empresa
app.get("/make-server-7249dcd9/empresas/:id/usuarios", async (c) => {
  try {
    const id = c.req.param("id");
    const acesso = await validarAcessoEmpresaRequest(c, id);
    if (!acesso.permitido) return acesso.resposta;

    const usuariosEmpresa = await usuarios.listarUsuariosEmpresa(id);

    return c.json({ success: true, data: usuariosEmpresa });
  } catch (error) {
    // console.error("[API] Erro ao listar usuários:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// âœ… DEBUG: Endpoint temporário para verificar todas as chaves de usuários no banco
app.get("/make-server-7249dcd9/debug/usuarios-raw", async (c) => {
  try {
    const acessoDebug = await validarSuperAdminTonlineRequest(c);
    if (!acessoDebug.permitido) return acessoDebug.resposta;

    const supabase = createClient(
      Deno.env.get('SUPABASE_URL')!,
      Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
    );

    // Buscar TODAS as chaves que contenham "usuario"
    const { data: todasChaves, error } = await supabase
      .from('kv_store_7249dcd9')
      .select('*')
      .or('key.ilike.%usuario%');

    if (error) {
      return c.json({ success: false, error: error.message }, 500);
    }

    // Agrupar por prefixo
    const grupos: Record<string, any[]> = {};

    todasChaves?.forEach((item: any) => {
      const prefixo = item.key.split(':')[0];
      if (!grupos[prefixo]) {
        grupos[prefixo] = [];
      }
      grupos[prefixo].push({
        chave: item.key,
        empresaId: item.value?.empresaId,
        email: item.value?.email,
        nome: item.value?.nome,
        nivel: item.value?.nivel,
        ativo: item.value?.ativo
      });
    });

    return c.json({
      success: true,
      totalChaves: todasChaves?.length || 0,
      grupos,
      message: 'Este endpoint é temporário para debug. Remova após identificar o problema.'
    });
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// âœ… NOVO: Endpoint para sincronizar usuários com authUserId vazio/undefined
app.post("/make-server-7249dcd9/debug/sync-usuarios-authid", async (c) => {
  try {
    const acessoSyncAuthId = await validarSuperAdminTonlineRequest(c);
    if (!acessoSyncAuthId.permitido) return acessoSyncAuthId.resposta;

    console.log('ðŸ”„ [/debug/sync-usuarios-authid] Iniciando sincronização de authUserId...');

    const supabase = createClient(
      Deno.env.get('SUPABASE_URL')!,
      Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
    );

    // Buscar todos os usuários do KV Store
    const usuariosKV = await kv.getByPrefix<any>('usuario:');

    if (!usuariosKV || usuariosKV.length === 0) {
      return c.json({
        success: false,
        message: 'Nenhum usuário encontrado no KV Store'
      }, 404);
    }

    console.log(`ðŸ” [sync] Total de usuários no KV: ${usuariosKV.length}`);

    // Identificar usuários com authUserId vazio ou undefined
    const usuariosSemAuthId = usuariosKV.filter((u: any) => !u.authUserId);

    console.log(`âš ï¸ [sync] Usuários sem authUserId: ${usuariosSemAuthId.length}`);

    if (usuariosSemAuthId.length === 0) {
      return c.json({
        success: true,
        message: 'Todos os usuários já têm authUserId configurado',
        totalUsuarios: usuariosKV.length,
        usuariosSincronizados: 0
      });
    }

    // Tentar sincronizar cada usuário
    const resultados = [];

    for (const usuario of usuariosSemAuthId) {
      try {
        console.log(`ðŸ”„ [sync] Processando usuário: ${usuario.email}`);

        // Buscar usuário no Supabase Auth pelo email
        const { data: authUsers, error: listError } = await supabase.auth.admin.listUsers();

        if (listError) {
          console.error(`âŒ [sync] Erro ao listar usuários Auth:`, listError);
          resultados.push({
            email: usuario.email,
            sucesso: false,
            erro: 'Erro ao listar usuários do Supabase Auth'
          });
          continue;
        }

        // Procurar usuário pelo email
        const authUser = authUsers.users.find((u: any) => u.email === usuario.email);

        if (!authUser) {
          console.warn(`âš ï¸ [sync] Usuário não encontrado no Supabase Auth: ${usuario.email}`);
          resultados.push({
            email: usuario.email,
            sucesso: false,
            erro: 'Usuário não existe no Supabase Auth'
          });
          continue;
        }

        // Atualizar usuário com authUserId correto
        usuario.authUserId = authUser.id;
        await kv.set(`usuario:${usuario.id}`, usuario);

        console.log(`âœ… [sync] authUserId atualizado para ${usuario.email}: ${authUser.id}`);

        resultados.push({
          email: usuario.email,
          authUserId: authUser.id,
          sucesso: true
        });

      } catch (error: any) {
        console.error(`âŒ [sync] Erro ao processar ${usuario.email}:`, error);
        resultados.push({
          email: usuario.email,
          sucesso: false,
          erro: error.message
        });
      }
    }

    const sincronizados = resultados.filter(r => r.sucesso).length;
    const falhas = resultados.filter(r => !r.sucesso).length;

    console.log(`âœ… [sync] Sincronização concluída: ${sincronizados} sucessos, ${falhas} falhas`);

    return c.json({
      success: true,
      message: `Sincronização concluída`,
      totalUsuarios: usuariosKV.length,
      usuariosSemAuthId: usuariosSemAuthId.length,
      sincronizados,
      falhas,
      resultados
    });

  } catch (error: any) {
    console.error('âŒ [sync] Erro geral:', error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Rotas POST /usuarios, PUT /usuarios/:id, resetar-senha, modulos, toggle, DELETE movidas para admin-router.tsx (admin-server-7249dcd9)

// ========== ROTAS DE FORNECEDORES ==========

// Listar fornecedores de uma empresa
app.get("/make-server-7249dcd9/empresas/:id/fornecedores", validarAcessoMiddleware("compras-fornecedores"), async (c) => {
  try {
    const id = c.req.param("id");
    const escopo = await verificarEscopoEmpresaRequest(c, id);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const { ativo } = c.req.query();

    const filtros: any = {};
    if (ativo !== undefined) {
      filtros.ativo = ativo === "true";
    }

    const fornecedoresList = await fornecedores.listarFornecedores(id, filtros);

    return c.json({ success: true, data: fornecedoresList });
  } catch (error) {
    // console.error("[API] Erro ao listar fornecedores:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar fornecedor por ID
app.get("/make-server-7249dcd9/fornecedores/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const fornecedor = await fornecedores.buscarFornecedorPorId(id);

    if (!fornecedor) {
      return c.json({ success: false, error: "Fornecedor não encontrado" }, 404);
    }

    const escopo = await verificarEscopoEmpresaRequest(c, fornecedor.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }

    return c.json({ success: true, data: fornecedor });
  } catch (error) {
    // console.error("[API] Erro ao buscar fornecedor:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Criar novo fornecedor
app.post("/make-server-7249dcd9/fornecedores", validarAcessoMiddleware("compras-fornecedores"), async (c) => {
  try {
    const dados = await c.req.json();
    const escopo = await verificarEscopoEmpresaRequest(c, dados.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const resultado = await fornecedores.criarFornecedor(dados);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    return c.json(resultado, 201);
  } catch (error) {
    // console.error("[API] Erro ao criar fornecedor:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Atualizar fornecedor
app.put("/make-server-7249dcd9/fornecedores/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const fornecedorExistente = await fornecedores.buscarFornecedorPorId(id);
    if (!fornecedorExistente) {
      return c.json({ success: false, error: "Fornecedor não encontrado" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, fornecedorExistente.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const dados = await c.req.json();
    const resultado = await fornecedores.atualizarFornecedor(id, dados);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    return c.json(resultado);
  } catch (error) {
    // console.error("[API] Erro ao atualizar fornecedor:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Deletar fornecedor
app.delete("/make-server-7249dcd9/fornecedores/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const fornecedorExistente = await fornecedores.buscarFornecedorPorId(id);
    if (!fornecedorExistente) {
      return c.json({ success: false, error: "Fornecedor não encontrado" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, fornecedorExistente.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const resultado = await fornecedores.deletarFornecedor(id);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    return c.json(resultado);
  } catch (error) {
    // console.error("[API] Erro ao deletar fornecedor:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Ativar/Desativar fornecedor
app.patch("/make-server-7249dcd9/fornecedores/:id/toggle", async (c) => {
  try {
    const id = c.req.param("id");
    const fornecedorExistente = await fornecedores.buscarFornecedorPorId(id);
    if (!fornecedorExistente) {
      return c.json({ success: false, error: "Fornecedor não encontrado" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, fornecedorExistente.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const { ativo } = await c.req.json();
    const resultado = await fornecedores.toggleFornecedor(id, ativo);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    return c.json(resultado);
  } catch (error) {
    // console.error("[API] Erro ao alternar status do fornecedor:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ========== ROTAS DE COMPRAS (FATURAS DE FORNECEDORES) ==========

// Listar todas as compras de uma empresa
app.get("/make-server-7249dcd9/empresas/:id/compras", validarAcessoMiddleware("compras-fornecedores"), async (c) => {
  try {
    const empresaId = c.req.param("id");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const fornecedorId = (c.req.query("fornecedorId") || "").trim().toLowerCase();
    const numeroDocumento = (c.req.query("numeroDocumento") || "").trim().toLowerCase();
    const tipoDocumento = (c.req.query("tipoDocumento") || "").trim().toLowerCase();
    const artigoId = (c.req.query("artigoId") || "").trim().toLowerCase();
    const codigo = (c.req.query("codigo") || "").trim().toLowerCase();
    let comprasList = await compras.listarCompras(empresaId);

    if (fornecedorId || numeroDocumento || tipoDocumento || artigoId || codigo) {
      comprasList = comprasList.filter((compra) => {
        if (fornecedorId && (compra.fornecedorId || "").trim().toLowerCase() !== fornecedorId) {
          return false;
        }

        if (numeroDocumento && (compra.numeroDocumento || "").trim().toLowerCase() !== numeroDocumento) {
          return false;
        }

        if (tipoDocumento && (compra.tipoDocumento || "").trim().toLowerCase() !== tipoDocumento) {
          return false;
        }

        if (artigoId || codigo) {
          return (compra.linhas || []).some((linha) => {
            const linhaArtigoId = (linha.artigoId || "").trim().toLowerCase();
            const linhaCodigo = (linha.codigo || "").trim().toLowerCase();
            return (artigoId && linhaArtigoId === artigoId) || (codigo && linhaCodigo === codigo);
          });
        }

        return true;
      });
    }

    return c.json({ success: true, data: comprasList });
  } catch (error: any) {
    console.error("[API] Erro ao listar compras:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar compras de um fornecedor específico
app.get("/make-server-7249dcd9/empresas/:id/compras/interempresa", async (c) => {
  try {
    const empresaId = c.req.param("id");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const documentos = await interempresa.listarComprasInterempresaPendentes(empresaId);
    return c.json({ success: true, data: documentos });
  } catch (error: any) {
    console.error("[API] Erro ao listar compras interempresa:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.get("/make-server-7249dcd9/empresas/:id/compras/interempresa/:docId/divergencias", async (c) => {
  try {
    const empresaId = c.req.param("id");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const docId = decodeURIComponent(c.req.param("docId"));
    const poId = c.req.query("poId") || undefined;

    const resultado = await interempresa.preverDivergenciasCompraInterempresa(empresaId, docId, { poId });
    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    return c.json(resultado);
  } catch (error: any) {
    console.error("[API] Erro ao prever divergencias interempresa:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.post("/make-server-7249dcd9/empresas/:id/compras/interempresa/:docId/aceitar", async (c) => {
  try {
    const empresaId = c.req.param("id");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const docId = decodeURIComponent(c.req.param("docId"));
    const dados = await c.req.json().catch(() => ({}));

    const resultado = await interempresa.aceitarCompraInterempresa(empresaId, docId, {
      armazemId: dados.armazemId,
      poId: dados.poId,
      aceitePor: dados.aceitePor || dados.usuarioAuditoriaNome || dados.criadoPor,
    });

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    if (resultado.compra) {
      const resultadoContabilidade = await contabilizarCompraOperacional(resultado.compra, { fornecedorNome: resultado.data?.empresaOrigemNome });
      resultado.compra = await anexarResultadoContabilidade(resultado.compra, { compra: resultadoContabilidade });
    }

    return c.json(resultado);
  } catch (error: any) {
    console.error("[API] Erro ao aceitar compra interempresa:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.post("/make-server-7249dcd9/empresas/:id/compras/interempresa/:docId/rejeitar", async (c) => {
  try {
    const empresaId = c.req.param("id");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const docId = decodeURIComponent(c.req.param("docId"));
    const dados = await c.req.json().catch(() => ({}));
    const resultado = await interempresa.rejeitarCompraInterempresa(empresaId, docId, {
      rejeitadoPor: dados.rejeitadoPor || dados.usuarioAuditoriaNome || dados.criadoPor,
      motivo: dados.motivo,
    });

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    return c.json(resultado);
  } catch (error: any) {
    console.error("[API] Erro ao rejeitar compra interempresa:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.get("/make-server-7249dcd9/fornecedores/:id/compras", async (c) => {
  try {
    const fornecedorId = c.req.param("id");
    const fornecedorParaCompras = await fornecedores.buscarFornecedorPorId(fornecedorId);
    if (!fornecedorParaCompras) {
      return c.json({ success: false, error: "Fornecedor não encontrado" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, fornecedorParaCompras.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    console.log(`[API] ðŸ” Buscando compras do fornecedor: ${fornecedorId}`);

    // DEBUG: Verificar índice do fornecedor
    const indice = await kv.get(`compras_fornecedor:${fornecedorId}`);
    console.log(`[API] ðŸ“Š Ãndice compras_fornecedor:${fornecedorId}:`, indice);

    const comprasList = await compras.listarComprasPorFornecedor(fornecedorId);
    console.log(`[API] ðŸ“¦ Total de compras encontradas: ${comprasList.length}`);

    if (comprasList.length > 0) {
      comprasList.forEach(compra => {
        console.log(`[API] ðŸ’° Compra: ${compra.numeroDocumento} | Valor: ${compra.totalGeral} | Estado: ${compra.estado}`);
      });
    }

    return c.json({ success: true, data: comprasList });
  } catch (error: any) {
    console.error("[API] Erro ao listar compras do fornecedor:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Criar nova compra
app.post("/make-server-7249dcd9/empresas/:id/compras", validarAcessoMiddleware("compras-fornecedores"), async (c) => {
  try {
    const empresaId = c.req.param("id");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const dados = await c.req.json();

    const prevalidacaoContabilidadeCompra = await contabilizarCompraOperacional(
      {
        ...dados,
        empresaId,
        id: dados.id || `prevalidacao_compra_${Date.now()}`,
        numeroDocumento: dados.numeroDocumento || 'Compra em preparacao',
      },
      {
        fornecedorNome: dados.fornecedorNome,
        previsualizar: true,
      },
    );
    const erroContabilidadeCompra = respostaErroContabilidadeObrigatoria(prevalidacaoContabilidadeCompra, 'compra');
    if (erroContabilidadeCompra) {
      return c.json(erroContabilidadeCompra, 400);
    }

    const resultado = await compras.criarCompra({
      ...dados,
      empresaId,
    });

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    const resultadoContabilidade = await contabilizarCompraOperacional(resultado.data, { fornecedorNome: dados.fornecedorNome });
    if (resultado.data) {
      resultado.data = await anexarResultadoContabilidade(resultado.data, { compra: resultadoContabilidade });
    }

    return c.json(resultado);
  } catch (error: any) {
    console.error("[API] Erro ao criar compra:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Criar documento de compra completo e processar todas as linhas em artigos/stock
app.post("/make-server-7249dcd9/empresas/:id/compras/processar-documento", validarAcessoMiddleware("compras-fornecedores"), async (c) => {
  try {
    const empresaId = c.req.param("id");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const dados = await c.req.json();

    const prevalidacaoContabilidadeCompraProcessada = await contabilizarCompraOperacional(
      {
        ...dados,
        empresaId,
        id: dados.id || `prevalidacao_compra_${Date.now()}`,
        numeroDocumento: dados.numeroDocumento || 'Compra em preparacao',
      },
      {
        fornecedorNome: dados.fornecedorNome,
        previsualizar: true,
      },
    );
    const erroContabilidadeCompraProcessada = respostaErroContabilidadeObrigatoria(
      prevalidacaoContabilidadeCompraProcessada,
      'compra',
    );
    if (erroContabilidadeCompraProcessada) {
      return c.json(erroContabilidadeCompraProcessada, 400);
    }

    const resultado = await compras.processarDocumentoCompra({
      ...dados,
      empresaId,
    });

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    const resultadoContabilidadeCompra = await contabilizarCompraOperacional(resultado.data, { fornecedorNome: dados.fornecedorNome });
    if (resultado.data) {
      resultado.data = await anexarResultadoContabilidade(resultado.data, { compra: resultadoContabilidadeCompra });
    }

    return c.json(resultado);
  } catch (error: any) {
    console.error("[API] Erro ao processar documento de compra:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.patch("/make-server-7249dcd9/compras/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const dados = await c.req.json();
    const compraAtual = await compras.buscarCompraPorId(id);

    if (!compraAtual) {
      return c.json({ success: false, error: "Compra nao encontrada" }, 404);
    }

    const escopo = await verificarEscopoEmpresaRequest(c, compraAtual.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }

    const deveReprocessarLinhas =
      Array.isArray(dados.linhas) ||
      Array.isArray(dados.detalhesLinhas) ||
      dados.reprocessarLinhas === true;

    const resultado = deveReprocessarLinhas
      ? await compras.reprocessarDocumentoCompraExistente(id, {
          empresaId: compraAtual.empresaId,
          fornecedorId: dados.fornecedorId || compraAtual.fornecedorId,
          fornecedorNome: dados.fornecedorNome,
          fornecedorCodigo: dados.fornecedorCodigo,
          fornecedorNuit: dados.fornecedorNuit,
          numeroDocumento: dados.numeroDocumento || compraAtual.numeroDocumento,
          tipoDocumento: dados.tipoDocumento || compraAtual.tipoDocumento,
          dataEmissao: dados.dataEmissao || compraAtual.dataEmissao,
          dataVencimento: dados.dataVencimento || compraAtual.dataVencimento,
          subtotal: dados.subtotal ?? compraAtual.subtotal,
          descontoGlobal: dados.descontoGlobal ?? compraAtual.descontoGlobal,
          totalIVA: dados.totalIVA ?? compraAtual.totalIVA,
          totalGeral: dados.totalGeral ?? compraAtual.totalGeral,
          observacoes: dados.observacoes ?? compraAtual.observacoes,
          armazemId: dados.armazemId ?? compraAtual.armazemId,
          linhas: dados.linhas || compraAtual.linhas,
          detalhesLinhas: dados.detalhesLinhas || [],
          criadoPor: dados.criadoPor || compraAtual.criadoPor,
        })
      : await compras.atualizarCompra(id, {
          fornecedorId: dados.fornecedorId || compraAtual.fornecedorId,
          numeroDocumento: dados.numeroDocumento || compraAtual.numeroDocumento,
          tipoDocumento: dados.tipoDocumento || compraAtual.tipoDocumento,
          dataEmissao: dados.dataEmissao || compraAtual.dataEmissao,
          subtotal: dados.subtotal ?? compraAtual.subtotal,
          descontoGlobal: dados.descontoGlobal ?? compraAtual.descontoGlobal,
          totalIVA: dados.totalIVA ?? compraAtual.totalIVA,
          totalGeral: dados.totalGeral ?? compraAtual.totalGeral,
          observacoes: dados.observacoes,
          armazemId: dados.armazemId,
          linhas: dados.linhas || compraAtual.linhas,
    });

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    const resultadoContabilidadeCompraAtualizada = await contabilizarCompraOperacional(resultado.data, { fornecedorNome: dados.fornecedorNome });
    if (resultado.data) {
      resultado.data = await anexarResultadoContabilidade(resultado.data, { compra: resultadoContabilidadeCompraAtualizada });
    }

    return c.json(resultado);
  } catch (error: any) {
    console.error("[API] Erro ao atualizar compra:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.delete("/make-server-7249dcd9/compras/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const compraParaDeletar = await compras.buscarCompraPorId(id);
    if (!compraParaDeletar) {
      return c.json({ success: false, error: "Compra nao encontrada" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, compraParaDeletar.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const resultado = await compras.deletarCompra(id);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    return c.json(resultado);
  } catch (error: any) {
    console.error("[API] Erro ao deletar compra:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ðŸ” ROTA DE DEBUG: Diagnóstico de compras de um fornecedor
app.get("/make-server-7249dcd9/debug/fornecedor/:fornecedorId/diagnostico", async (c) => {
  try {
    const chamadorDiagFornecedor = await obterUsuarioAutenticadoRequest(c);
    if (!chamadorDiagFornecedor || chamadorDiagFornecedor.ativo === false) {
      return c.json({ success: false, error: "Utilizador nao autenticado" }, 401);
    }
    const fornecedorId = c.req.param("fornecedorId");
    const fornecedorDiag = await fornecedores.buscarFornecedorPorId(fornecedorId);
    if (!fornecedorDiag) {
      return c.json({ success: false, error: "Fornecedor nao encontrado" }, 404);
    }
    if (!isUsuarioSuperAdminTonline(chamadorDiagFornecedor) && String(chamadorDiagFornecedor.empresaId || "") !== String((fornecedorDiag as any).empresaId || "")) {
      return c.json({ success: false, error: "Nao tem permissao para aceder a esta empresa" }, 403);
    }
    console.log(`[DEBUG] ðŸ” Diagnóstico do fornecedor: ${fornecedorId}`);

    // 1. Verificar índice
    const indice = await kv.get(`compras_fornecedor:${fornecedorId}`) || [];
    console.log(`[DEBUG] ðŸ“Š Ãndice compras_fornecedor: ${indice.length} IDs`);

    // 2. Buscar compras pelo índice
    const comprasPorIndice: any[] = [];
    for (const id of indice) {
      const compra = await kv.get(`compra:${id}`);
      if (compra) {
        comprasPorIndice.push(compra);
      }
    }

    // 3. Buscar TODAS as compras no banco (varredura completa)
    const todasCompras = await kv.getByPrefix('compra:');
    const comprasDoFornecedor = todasCompras.filter((c: any) => c.fornecedorId === fornecedorId);

    console.log(`[DEBUG] ðŸ“¦ Compras encontradas por índice: ${comprasPorIndice.length}`);
    console.log(`[DEBUG] ðŸ“¦ Compras encontradas por varredura: ${comprasDoFornecedor.length}`);

    // 4. Identificar compras não indexadas
    const comprasNaoIndexadas = comprasDoFornecedor.filter(
      (c: any) => !indice.includes(c.id)
    );

    return c.json({
      success: true,
      fornecedorId,
      diagnostico: {
        totalNoIndice: indice.length,
        totalPorIndice: comprasPorIndice.length,
        totalPorVarredura: comprasDoFornecedor.length,
        comprasNaoIndexadas: comprasNaoIndexadas.length,
      },
      indice,
      comprasPorIndice: comprasPorIndice.map(c => ({ id: c.id, numero: c.numeroDocumento, valor: c.totalGeral })),
      comprasPorVarredura: comprasDoFornecedor.map((c: any) => ({ id: c.id, numero: c.numeroDocumento, valor: c.totalGeral })),
      comprasNaoIndexadas: comprasNaoIndexadas.map((c: any) => ({ id: c.id, numero: c.numeroDocumento, valor: c.totalGeral })),
    });
  } catch (error: any) {
    console.error("[DEBUG] âŒ Erro no diagnóstico:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ðŸ” ROTA DE DEBUG: Ver TODAS as compras no sistema
app.get("/make-server-7249dcd9/debug/todas-compras", async (c) => {
  try {
    const acessoTodasCompras = await validarSuperAdminTonlineRequest(c);
    if (!acessoTodasCompras.permitido) return acessoTodasCompras.resposta;

    console.log('[API] ðŸ” Buscando TODAS as compras...');

    const todasCompras = await kv.getByPrefix('compra:');
    console.log(`[API] ðŸ“¦ Total de compras encontradas: ${todasCompras.length}`);

    todasCompras.forEach((compra: any, index: number) => {
      console.log(`[API] ðŸ“„ Compra ${index + 1}:`, {
        id: compra?.id,
        numero: compra?.numeroDocumento,
        fornecedorId: compra?.fornecedorId,
        empresaId: compra?.empresaId,
      });
    });

    return c.json({
      success: true,
      total: todasCompras.length,
      compras: todasCompras,
    });
  } catch (error: any) {
    console.error("[API] âŒ Erro ao buscar compras:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ðŸ”§ ROTA DE DEBUG: Reindexar todas as compras por fornecedor
app.post("/make-server-7249dcd9/debug/reindexar-compras", async (c) => {
  try {
    console.log('[API] ðŸ”§ Iniciando reindexação de compras...');

    const { empresaId } = await c.req.json();

    if (!empresaId) {
      return c.json({ success: false, error: "empresaId é obrigatório" }, 400);
    }

    const acessoReindexar = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!acessoReindexar.permitido) {
      return c.json({ success: false, error: acessoReindexar.error }, acessoReindexar.status as any);
    }

    // Buscar todas as compras da empresa
    const comprasIds = await kv.get(`compras_empresa:${empresaId}`) || [];
    console.log(`[API] ðŸ“Š Total de compras na empresa: ${comprasIds.length}`);

    let reindexadas = 0;
    const erros: string[] = [];

    for (const id of comprasIds) {
      try {
        const compra = await kv.get(`compra:${id}`) as any;
        if (compra && compra.fornecedorId) {
          // Reindexar por fornecedor
          const comprasFornecedor = await kv.get(`compras_fornecedor:${compra.fornecedorId}`) || [];

          if (!comprasFornecedor.includes(id)) {
            comprasFornecedor.push(id);
            await kv.set(`compras_fornecedor:${compra.fornecedorId}`, comprasFornecedor);
            reindexadas++;
            console.log(`[API] âœ… Reindexada: ${compra.numeroDocumento} para fornecedor ${compra.fornecedorId}`);
          }
        }
      } catch (err: any) {
        erros.push(`Erro ao reindexar ${id}: ${err.message}`);
      }
    }

    console.log(`[API] âœ… Reindexação concluída! ${reindexadas} compras reindexadas.`);

    return c.json({
      success: true,
      message: `${reindexadas} compras foram reindexadas`,
      total: comprasIds.length,
      reindexadas,
      erros: erros.length > 0 ? erros : undefined,
    });
  } catch (error: any) {
    console.error("[API] âŒ Erro ao reindexar compras:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Atualizar estado de uma compra
app.patch("/make-server-7249dcd9/compras/:id/estado", async (c) => {
  try {
    const id = c.req.param("id");
    const compraParaEstado = await compras.buscarCompraPorId(id);
    if (!compraParaEstado) {
      return c.json({ success: false, error: "Compra nao encontrada" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, compraParaEstado.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const { estado } = await lerBodyJsonSeguro(c);

    const resultado = await compras.atualizarEstadoCompra(id, estado);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    return c.json(resultado);
  } catch (error: any) {
    console.error("[API] Erro ao atualizar estado da compra:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.post("/make-server-7249dcd9/compras/:id/recepcionar", async (c) => {
  try {
    const id = c.req.param("id");
    const compraParaRecepcionar = await compras.buscarCompraPorId(id);
    if (!compraParaRecepcionar) {
      return c.json({ success: false, error: "Compra nao encontrada" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, compraParaRecepcionar.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const dados = await c.req.json();
    const resultado = await compras.recepcionarCompra(id, dados);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    const resultadoContabilidadeRecepcao = await contabilizarCompraOperacional(resultado.data);
    if (resultado.data) {
      resultado.data = await anexarResultadoContabilidade(resultado.data, { compra: resultadoContabilidadeRecepcao });
    }

    return c.json(resultado);
  } catch (error: any) {
    console.error("[API] Erro ao recepcionar compra:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ========== ROTAS DE PAGAMENTOS A FORNECEDORES ==========

// Listar todos os pagamentos de uma empresa
app.get("/make-server-7249dcd9/empresas/:id/pagamentos-compra", async (c) => {
  try {
    const empresaId = c.req.param("id");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const pagamentosList = await compras.listarPagamentosCompra(empresaId);

    return c.json({ success: true, data: pagamentosList });
  } catch (error: any) {
    console.error("[API] Erro ao listar pagamentos:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Listar pagamentos de um fornecedor específico
app.get("/make-server-7249dcd9/fornecedores/:id/pagamentos", async (c) => {
  try {
    const fornecedorId = c.req.param("id");
    const fornecedorParaPagamentos = await fornecedores.buscarFornecedorPorId(fornecedorId);
    if (!fornecedorParaPagamentos) {
      return c.json({ success: false, error: "Fornecedor não encontrado" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, fornecedorParaPagamentos.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const pagamentosList = await compras.listarPagamentosPorFornecedor(fornecedorId);

    return c.json({ success: true, data: pagamentosList });
  } catch (error: any) {
    console.error("[API] Erro ao listar pagamentos do fornecedor:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Criar novo pagamento a fornecedor
app.post("/make-server-7249dcd9/empresas/:id/pagamentos-compra", async (c) => {
  try {
    const empresaId = c.req.param("id");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const dados = await c.req.json();

    const prevalidacaoContabilidadePagamentoFornecedor = await contabilizarPagamentoFornecedor(
      {
        ...dados,
        empresaId,
        id: dados.id || `prevalidacao_pagamento_fornecedor_${Date.now()}`,
        numeroDocumento: dados.numeroDocumento || 'Pagamento a fornecedor em preparacao',
      },
      {
        fornecedorNome: dados.fornecedorNome,
        previsualizar: true,
      },
    );
    const erroContabilidadePagamentoFornecedor = respostaErroContabilidadeObrigatoria(
      prevalidacaoContabilidadePagamentoFornecedor,
      'pagamento a fornecedor',
    );
    if (erroContabilidadePagamentoFornecedor) {
      return c.json(erroContabilidadePagamentoFornecedor, 400);
    }

    const resultado = await compras.criarPagamentoCompra({
      ...dados,
      empresaId,
    });

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    const resultadoContabilidadePagamentoFornecedor = await contabilizarPagamentoFornecedor(resultado.data, { fornecedorNome: dados.fornecedorNome });
    if (resultado.data) {
      resultado.data = await anexarResultadoContabilidade(resultado.data, { pagamento: resultadoContabilidadePagamentoFornecedor });
    }

    return c.json(resultado);
  } catch (error: any) {
    console.error("[API] Erro ao criar pagamento:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ========== ROTAS DE CLIENTES ==========

// Listar clientes de uma empresa
app.get("/make-server-7249dcd9/empresas/:id/clientes", async (c) => {
  try {
    const id = c.req.param("id");
    const escopo = await verificarEscopoEmpresaRequest(c, id);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const { ativo } = c.req.query();

    const filtros: any = {};
    if (ativo !== undefined) {
      filtros.ativo = ativo === "true";
    }

    const clientesList = await clientes.listarClientes(id, filtros);

    return c.json({ success: true, data: clientesList });
  } catch (error) {
    // console.error("[API] Erro ao listar clientes:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar cliente por ID
app.get("/make-server-7249dcd9/clientes/:id", async (c) => {
  try {
    const chamadorCliente = await obterUsuarioAutenticadoRequest(c);
    if (!chamadorCliente || chamadorCliente.ativo === false) {
      return c.json({ success: false, error: "Utilizador nao autenticado" }, 401);
    }
    const id = c.req.param("id");
    const cliente = await clientes.buscarClientePorId(id);

    if (!cliente) {
      return c.json({ success: false, error: "Cliente não encontrado" }, 404);
    }
    if (!isUsuarioSuperAdminTonline(chamadorCliente) && String(chamadorCliente.empresaId || "") !== String(cliente.empresaId || "")) {
      return c.json({ success: false, error: "Nao tem permissao para aceder a esta empresa" }, 403);
    }

    return c.json({ success: true, data: cliente });
  } catch (error) {
    // console.error("[API] Erro ao buscar cliente:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Criar novo cliente
app.post("/make-server-7249dcd9/clientes", async (c) => {
  try {
    const dados = await lerBodyJsonSeguro(c);
    const acessoCriarCliente = await verificarEscopoEmpresaRequest(c, dados?.empresaId);
    if (!acessoCriarCliente.permitido) {
      return c.json({ success: false, error: acessoCriarCliente.error }, acessoCriarCliente.status as any);
    }
    const resultado = await clientes.criarCliente(dados);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    return c.json(resultado, 201);
  } catch (error) {
    // console.error("[API] Erro ao criar cliente:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Atualizar cliente
app.put("/make-server-7249dcd9/clientes/:id", async (c) => {
  try {
    const chamadorAtualizarCliente = await obterUsuarioAutenticadoRequest(c);
    if (!chamadorAtualizarCliente || chamadorAtualizarCliente.ativo === false) {
      return c.json({ success: false, error: "Utilizador nao autenticado" }, 401);
    }
    const id = c.req.param("id");
    const clienteExistenteParaAtualizar = await clientes.buscarClientePorId(id);
    if (!clienteExistenteParaAtualizar) {
      return c.json({ success: false, error: "Cliente não encontrado" }, 404);
    }
    if (!isUsuarioSuperAdminTonline(chamadorAtualizarCliente) && String(chamadorAtualizarCliente.empresaId || "") !== String(clienteExistenteParaAtualizar.empresaId || "")) {
      return c.json({ success: false, error: "Nao tem permissao para aceder a esta empresa" }, 403);
    }
    const dados = await lerBodyJsonSeguro(c);
    const resultado = await clientes.atualizarCliente(id, dados);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    return c.json(resultado);
  } catch (error) {
    // console.error("[API] Erro ao atualizar cliente:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Deletar cliente
app.delete("/make-server-7249dcd9/clientes/:id", async (c) => {
  try {
    const chamadorExcluirCliente = await obterUsuarioAutenticadoRequest(c);
    if (!chamadorExcluirCliente || chamadorExcluirCliente.ativo === false) {
      return c.json({ success: false, error: "Utilizador nao autenticado" }, 401);
    }
    const id = c.req.param("id");
    const clienteExistenteParaExcluir = await clientes.buscarClientePorId(id);
    if (!clienteExistenteParaExcluir) {
      return c.json({ success: false, error: "Cliente não encontrado" }, 404);
    }
    if (!isUsuarioSuperAdminTonline(chamadorExcluirCliente) && String(chamadorExcluirCliente.empresaId || "") !== String(clienteExistenteParaExcluir.empresaId || "")) {
      return c.json({ success: false, error: "Nao tem permissao para aceder a esta empresa" }, 403);
    }
    const resultado = await clientes.excluirCliente(id);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    return c.json(resultado);
  } catch (error) {
    // console.error("[API] Erro ao deletar cliente:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Ativar/Desativar cliente
app.patch("/make-server-7249dcd9/clientes/:id/toggle", async (c) => {
  try {
    const chamadorToggleCliente = await obterUsuarioAutenticadoRequest(c);
    if (!chamadorToggleCliente || chamadorToggleCliente.ativo === false) {
      return c.json({ success: false, error: "Utilizador nao autenticado" }, 401);
    }
    const id = c.req.param("id");
    const clienteExistenteParaToggle = await clientes.buscarClientePorId(id);
    if (!clienteExistenteParaToggle) {
      return c.json({ success: false, error: "Cliente não encontrado" }, 404);
    }
    if (!isUsuarioSuperAdminTonline(chamadorToggleCliente) && String(chamadorToggleCliente.empresaId || "") !== String(clienteExistenteParaToggle.empresaId || "")) {
      return c.json({ success: false, error: "Nao tem permissao para aceder a esta empresa" }, 403);
    }
    const { ativo } = await lerBodyJsonSeguro(c);
    const resultado = await clientes.toggleAtivo(id, ativo);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    return c.json(resultado);
  } catch (error) {
    // console.error("[API] Erro ao alternar status do cliente:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ========== ROTAS DE ARTIGOS ==========

// Listar artigos de uma empresa (usando query string)
app.get("/make-server-7249dcd9/artigos", validarAcessoMiddleware("stock-inventario"), async (c) => {
  try {
    const { empresaId, ativo, tipo, fornecedorId } = c.req.query();

    if (!empresaId) {
      return c.json({ success: false, error: "empresaId é obrigatório" }, 400);
    }

    const filtros: any = {};
    if (ativo !== undefined) {
      filtros.ativo = ativo === "true";
    }
    if (tipo) {
      filtros.tipo = tipo as any;
    }
    if (fornecedorId) {
      filtros.fornecedorId = fornecedorId;
    }

    const artigosList = await artigos.listarArtigos(empresaId, filtros);

    return c.json({ success: true, data: artigosList });
  } catch (error) {
    // console.error("[API] Erro ao listar artigos:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Listar artigos de uma empresa (usando path param - mantido para compatibilidade)
app.get("/make-server-7249dcd9/empresas/:id/artigos", validarAcessoMiddleware("stock-inventario"), async (c) => {
  try {
    const id = c.req.param("id");
    const { ativo, tipo, fornecedorId, comStock } = c.req.query();

    console.log('ðŸ“¦ [API] GET /empresas/:id/artigos - empresaId:', id);
    console.log('ðŸ“¦ [API] Filtros recebidos:', { ativo, tipo, fornecedorId, comStock });

    const filtros: any = {};
    if (ativo !== undefined) {
      filtros.ativo = ativo === "true";
    }
    if (tipo) {
      filtros.tipo = tipo as any;
    }
    if (fornecedorId) {
      filtros.fornecedorId = fornecedorId;
    }

    const artigosList = await artigos.listarArtigos(id, filtros);

    console.log('ðŸ“¦ [API] Artigos encontrados:', artigosList.length);
    console.log('ðŸ“¦ [API] Primeiros 3 artigos:', artigosList.slice(0, 3));

    // âœ… Se comStock=true, incluir informação de stock total em cada artigo
    if (comStock === 'true') {
      console.log('ðŸ“¦ [API] Buscando informaçÃµes de stock para', artigosList.length, 'artigos...');
      const artigosIds = artigosList.map(a => a.id);
      const mapaStock = await stockArmazem.obterMapaStockArtigos(id, artigosIds);
      const mapaResumoLotes = await stockLotes.obterMapaResumoArtigos(id, artigosIds);

      const artigosComStock = artigosList.map(artigo => ({
        ...artigo,
        stockTotal: mapaResumoLotes[artigo.id]?.temLotes
          ? mapaResumoLotes[artigo.id].quantidadeDisponivelValida
          : (mapaStock[artigo.id] || 0),
        dataValidade: mapaResumoLotes[artigo.id]?.proximaValidade || artigo.dataValidade,
        stockExpirado: mapaResumoLotes[artigo.id]?.quantidadeExpirada || 0,
        temLotes: mapaResumoLotes[artigo.id]?.temLotes || false,
        diasParaValidade: mapaResumoLotes[artigo.id]?.diasParaProximaValidade,
        alertaValidade: mapaResumoLotes[artigo.id]?.alertaValidade,
        nivelAlertaValidade: mapaResumoLotes[artigo.id]?.nivelAlertaValidade || "normal",
        descontoValidadeSugerido: mapaResumoLotes[artigo.id]?.descontoValidadeSugerido || 0,
      }));

      console.log('ðŸ“¦ [API] Artigos com stock preparados:', artigosComStock.length);
      return c.json({ success: true, data: artigosComStock });
    }

    return c.json({ success: true, data: artigosList });
  } catch (error) {
    console.error("âŒ [API] Erro ao listar artigos:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ðŸ”§ DEBUG: Listar TODOS os artigos do KV (sem filtro de empresa)
app.get("/make-server-7249dcd9/debug/artigos-kv", async (c) => {
  try {
    const acessoArtigosKv = await validarSuperAdminTonlineRequest(c);
    if (!acessoArtigosKv.permitido) return acessoArtigosKv.resposta;

    console.log('ðŸ”§ [DEBUG] Listando TODOS os artigos do KV...');
    const todosArtigos = await kv.getByPrefix<any>("artigo:");

    console.log('ðŸ”§ [DEBUG] Total de artigos no KV:', todosArtigos.length);

    if (todosArtigos.length > 0) {
      console.log('ðŸ”§ [DEBUG] Primeiro artigo:', todosArtigos[0]);
      console.log('ðŸ”§ [DEBUG] EmpresaIds encontrados:', [...new Set(todosArtigos.map(a => a.empresaId))]);
    }

    return c.json({ success: true, data: todosArtigos });
  } catch (error) {
    console.error("âŒ [DEBUG] Erro ao listar artigos:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Listar artigos com estoque baixo
app.get("/make-server-7249dcd9/empresas/:id/artigos/estoque-baixo", async (c) => {
  try {
    const id = c.req.param("id");
    const acessoEstoqueBaixo = await verificarEscopoEmpresaRequest(c, id);
    if (!acessoEstoqueBaixo.permitido) {
      return c.json({ success: false, error: acessoEstoqueBaixo.error }, acessoEstoqueBaixo.status as any);
    }
    const artigosList = await artigos.listarArtigosEstoqueBaixo(id);

    return c.json({ success: true, data: artigosList });
  } catch (error) {
    // console.error("[API] Erro ao listar artigos com estoque baixo:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar artigo por ID
app.get("/make-server-7249dcd9/artigos/:id", async (c) => {
  try {
    const chamadorArtigo = await obterUsuarioAutenticadoRequest(c);
    if (!chamadorArtigo || chamadorArtigo.ativo === false) {
      return c.json({ success: false, error: "Utilizador nao autenticado" }, 401);
    }
    const id = c.req.param("id");
    const artigo = await artigos.buscarArtigoPorId(id);

    if (!artigo) {
      return c.json({ success: false, error: "Artigo não encontrado" }, 404);
    }
    if (!isUsuarioSuperAdminTonline(chamadorArtigo) && String(chamadorArtigo.empresaId || "") !== String(artigo.empresaId || "")) {
      return c.json({ success: false, error: "Nao tem permissao para aceder a esta empresa" }, 403);
    }

    return c.json({ success: true, data: artigo });
  } catch (error) {
    // console.error("[API] Erro ao buscar artigo:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.get("/make-server-7249dcd9/artigos/sugestao-lote", validarAcessoMiddleware("stock-inventario"), async (c) => {
  try {
    const { empresaId, codigo, artigoId } = c.req.query();

    if (!empresaId || !codigo) {
      return c.json({ success: false, error: "empresaId e codigo sao obrigatorios" }, 400);
    }

    let artigo = null;

    if (artigoId) {
      artigo = await artigos.buscarArtigoPorId(artigoId);
    }

    if (!artigo) {
      artigo = await artigos.buscarArtigoPorCodigo(empresaId, codigo);
    }

    const codigoNormalizado = codigo.trim().toUpperCase();

    if (!artigo) {
      return c.json({
        success: true,
        data: {
          artigoExiste: false,
          loteSugerido: `${codigoNormalizado}-001`,
        },
      });
    }

    const loteSugerido = await stockLotes.sugerirProximoLote(empresaId, artigo.id, artigo.codigo);

    return c.json({
      success: true,
      data: {
        artigoExiste: true,
        artigoId: artigo.id,
        loteSugerido,
      },
    });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Criar novo artigo
app.post("/make-server-7249dcd9/artigos", validarAcessoMiddleware("stock-inventario"), async (c) => {
  try {
    // âœ… CORRIGIDO: Usar body cacheado se existir (já foi lido pelo middleware)
    const dados = await lerBodyJsonSeguro(c);
    console.log('[API] ðŸ“¦ POST /artigos - Dados recebidos:', JSON.stringify(dados, null, 2));

    const resultado = await artigos.criarArtigo(dados);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    console.log('[API] âœ… Artigo criado:', resultado.data.codigo);
    await registrarAuditoriaArtigo(c, 'criar', resultado.data, {
      body: dados,
      extraResumo: {
        stockInicial: dados.estoqueAtual,
        documentoTipo: dados.tipoDocumento,
        documentoNumero: dados.numeroDocumento,
      },
    });
    console.log('[API] ðŸ” Verificando se deve criar compra...');
    console.log('[API] ðŸ” fornecedorId:', dados.fornecedorId);
    console.log('[API] ðŸ” numeroDocumento:', dados.numeroDocumento);
    console.log('[API] ðŸ” tipoDocumento:', dados.tipoDocumento);

    // âœ… Se tiver fornecedor e documento, criar também a compra
    if (dados.fornecedorId && dados.numeroDocumento && dados.tipoDocumento) {
      console.log('[API] âœ… TODAS as condiçÃµes atendidas! Criando documento de compra para artigo:', resultado.data.codigo);

      const compraPayload = {
        empresaId: dados.empresaId,
        fornecedorId: dados.fornecedorId,
        numeroDocumento: dados.numeroDocumento,
        tipoDocumento: dados.tipoDocumento,
        dataEmissao: dados.dataDocumento || new Date().toISOString().split('T')[0],
        linhas: [{
          id: `linha_${Date.now()}`,
          artigoId: resultado.data.id,
          codigo: resultado.data.codigo,
          descricao: resultado.data.nome,
          tipoArtigo: resultado.data.tipo || 'produto',
          quantidade: dados.estoqueAtual || 1,
          unidade: resultado.data.unidade,
          precoUnitario: dados.precoCompra || 0,
          precoVenda: dados.precoVenda ?? resultado.data.precoVenda ?? 0,
          desconto: dados.desconto || 0,
          iva: dados.iva || 0,
          ivaIncluso: dados.ivaIncluso || false,
          motivoIsencao: dados.motivoIsencao,
          codigoMotivoIsencao: dados.codigoMotivoIsencao,
          codigoBarras: dados.codigoBarras ?? resultado.data.codigoBarras,
          dataValidade: dados.dataValidade ?? resultado.data.dataValidade,
          lote: dados.lote ?? resultado.data.lote,
          armazemId: dados.armazemId ?? resultado.data.armazemId,
          imagemUrl: dados.imagemUrl ?? resultado.data.imagemUrl,
          subtotal: (dados.estoqueAtual || 1) * (dados.precoCompra || 0),
        }],
        subtotal: (dados.estoqueAtual || 1) * (dados.precoCompra || 0),
        descontoGlobal: 0,
        totalIVA: 0,
        totalGeral: (dados.estoqueAtual || 1) * (dados.precoCompra || 0),
        estado: 'emitido',
        observacoes: dados.observacoes || '',
        armazemId: dados.armazemId,
      };

      console.log('[API] ðŸ“¦ Payload da compra:', JSON.stringify(compraPayload, null, 2));

      const compraResultado = await compras.criarCompra(compraPayload);

      if (compraResultado.success) {
        console.log('[API] âœ…âœ…âœ… Documento de compra criado com sucesso!');
        console.log('[API] ðŸ“„ Número do documento:', compraResultado.data.numeroDocumento);
        console.log('[API] ðŸ“„ ID da compra:', compraResultado.data.id);
      } else {
        console.error('[API] âŒ Erro ao criar documento de compra:', compraResultado.error);
      }
    } else {
      console.log('[API] âš ï¸ NÃƒO criará documento de compra. Dados faltando:');
      if (!dados.fornecedorId) console.log('[API]   âŒ fornecedorId');
      if (!dados.numeroDocumento) console.log('[API]   âŒ numeroDocumento');
      if (!dados.tipoDocumento) console.log('[API]   âŒ tipoDocumento');
    }

    return c.json(resultado, 201);
  } catch (error: any) {
    console.error("[API] âŒ Erro ao criar artigo:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Atualizar artigo
app.put("/make-server-7249dcd9/artigos/:id", validarAcessoMiddleware("stock-inventario"), async (c) => {
  try {
    const id = c.req.param("id");
    // âœ… CORRIGIDO: Usar body cacheado se existir (já foi lido pelo middleware)
    const dados = await lerBodyJsonSeguro(c);
    console.log('[API] ðŸ“ PUT /artigos - Dados recebidos:', JSON.stringify(dados, null, 2));

    const artigoAntes = await artigos.buscarArtigoPorId(id);
    const resultado = await artigos.atualizarArtigo(id, dados);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    console.log('[API] âœ… Artigo atualizado:', resultado.data.codigo);
    await registrarAuditoriaArtigo(c, 'editar', resultado.data, {
      body: dados,
      antes: artigoAntes,
      extraResumo: {
        documentoTipo: dados.tipoDocumento,
        documentoNumero: dados.numeroDocumento,
      },
    });
    console.log('[API] ðŸ” Verificando se deve criar compra...');
    console.log('[API] ðŸ” fornecedorId:', dados.fornecedorId);
    console.log('[API] ðŸ” numeroDocumento:', dados.numeroDocumento);
    console.log('[API] ðŸ” tipoDocumento:', dados.tipoDocumento);

    // âœ… Se tiver fornecedor e documento, criar também a compra (SE NÃƒO EXISTIR)
    if (dados.fornecedorId && dados.numeroDocumento && dados.tipoDocumento) {
      console.log('[API] âœ… TODAS as condiçÃµes atendidas! Verificando se compra já existe...');

      // Verificar se já existe uma compra com esse número de documento
      const compraExistente = await compras.buscarCompraPorNumero(dados.empresaId, dados.numeroDocumento);

      if (compraExistente) {
        console.log('[API] âš ï¸ Compra já existe:', compraExistente.numeroDocumento);
        console.log('[API] ðŸ“ Atualizando compra existente...');

        // Verificar se este artigo já está nas linhas da compra
        const linhaExistente = compraExistente.linhas.find((l: any) => l.artigoId === resultado.data.id);

        if (!linhaExistente) {
          // Adicionar nova linha Ã  compra existente
          console.log('[API] âž• Adicionando artigo Ã  compra existente');

          const novaLinha = {
            id: `linha_${Date.now()}`,
            artigoId: resultado.data.id,
            codigo: resultado.data.codigo,
            descricao: resultado.data.nome,
            tipoArtigo: resultado.data.tipo || 'produto',
            quantidade: dados.estoqueAtual || 1,
            unidade: resultado.data.unidade,
            precoUnitario: dados.precoCompra || 0,
            precoVenda: dados.precoVenda ?? resultado.data.precoVenda ?? 0,
            desconto: dados.desconto || 0,
            iva: dados.iva || 0,
            ivaIncluso: dados.ivaIncluso || false,
            motivoIsencao: dados.motivoIsencao,
            codigoMotivoIsencao: dados.codigoMotivoIsencao,
            codigoBarras: dados.codigoBarras ?? resultado.data.codigoBarras,
            dataValidade: dados.dataValidade ?? resultado.data.dataValidade,
            lote: dados.lote ?? resultado.data.lote,
            armazemId: dados.armazemId ?? resultado.data.armazemId,
            imagemUrl: dados.imagemUrl ?? resultado.data.imagemUrl,
            subtotal: (dados.estoqueAtual || 1) * (dados.precoCompra || 0),
          };

          compraExistente.linhas.push(novaLinha);

          // Recalcular totais
          compraExistente.subtotal = compraExistente.linhas.reduce((sum: number, l: any) => sum + l.subtotal, 0);
          compraExistente.totalGeral = compraExistente.subtotal + compraExistente.totalIVA - compraExistente.descontoGlobal;

          // Atualizar compra (agora com indexação automática)
          const resultadoAtualizacao = await compras.atualizarCompra(compraExistente.id, compraExistente);
          if (resultadoAtualizacao.success) {
            console.log('[API] âœ… Compra atualizada com novo artigo e reindexada');
          } else {
            console.error('[API] âŒ Erro ao atualizar compra:', resultadoAtualizacao.error);
          }
        } else {
          // Atualizar linha existente
          console.log('[API] ðŸ”„ Atualizando linha existente na compra');
          linhaExistente.quantidade = dados.estoqueAtual || linhaExistente.quantidade;
          linhaExistente.precoUnitario = dados.precoCompra || linhaExistente.precoUnitario;
          linhaExistente.precoVenda = dados.precoVenda ?? resultado.data.precoVenda ?? linhaExistente.precoVenda;
          linhaExistente.codigoBarras = dados.codigoBarras ?? resultado.data.codigoBarras ?? linhaExistente.codigoBarras;
          linhaExistente.dataValidade = dados.dataValidade ?? resultado.data.dataValidade ?? linhaExistente.dataValidade;
          linhaExistente.lote = dados.lote ?? resultado.data.lote ?? linhaExistente.lote;
          linhaExistente.armazemId = dados.armazemId ?? resultado.data.armazemId ?? linhaExistente.armazemId;
          linhaExistente.imagemUrl = dados.imagemUrl ?? resultado.data.imagemUrl ?? linhaExistente.imagemUrl;
          linhaExistente.tipoArtigo = resultado.data.tipo || linhaExistente.tipoArtigo || 'produto';
          linhaExistente.ivaIncluso = dados.ivaIncluso ?? resultado.data.ivaIncluso ?? linhaExistente.ivaIncluso;
          linhaExistente.iva = dados.iva ?? resultado.data.iva ?? linhaExistente.iva;
          linhaExistente.desconto = dados.desconto ?? resultado.data.desconto ?? linhaExistente.desconto;
          linhaExistente.subtotal = linhaExistente.quantidade * linhaExistente.precoUnitario;

          // Recalcular totais
          compraExistente.subtotal = compraExistente.linhas.reduce((sum: number, l: any) => sum + l.subtotal, 0);
          compraExistente.totalGeral = compraExistente.subtotal + compraExistente.totalIVA - compraExistente.descontoGlobal;

          // Atualizar compra (agora com indexação automática)
          const resultadoAtualizacao2 = await compras.atualizarCompra(compraExistente.id, compraExistente);
          if (resultadoAtualizacao2.success) {
            console.log('[API] âœ… Linha da compra atualizada e reindexada');
          } else {
            console.error('[API] âŒ Erro ao atualizar compra:', resultadoAtualizacao2.error);
          }
        }
      } else {
        console.log('[API] ðŸ“ Criando nova compra para artigo:', resultado.data.codigo);

        const compraPayload = {
          empresaId: dados.empresaId,
          fornecedorId: dados.fornecedorId,
          numeroDocumento: dados.numeroDocumento,
          tipoDocumento: dados.tipoDocumento,
          dataEmissao: dados.dataDocumento || new Date().toISOString().split('T')[0],
          linhas: [{
            id: `linha_${Date.now()}`,
            artigoId: resultado.data.id,
            codigo: resultado.data.codigo,
            descricao: resultado.data.nome,
            tipoArtigo: resultado.data.tipo || 'produto',
            quantidade: dados.estoqueAtual || 1,
            unidade: resultado.data.unidade,
            precoUnitario: dados.precoCompra || 0,
            precoVenda: dados.precoVenda ?? resultado.data.precoVenda ?? 0,
            desconto: dados.desconto || 0,
            iva: dados.iva || 0,
            ivaIncluso: dados.ivaIncluso || false,
            motivoIsencao: dados.motivoIsencao,
            codigoMotivoIsencao: dados.codigoMotivoIsencao,
            codigoBarras: dados.codigoBarras ?? resultado.data.codigoBarras,
            dataValidade: dados.dataValidade ?? resultado.data.dataValidade,
            lote: dados.lote ?? resultado.data.lote,
            armazemId: dados.armazemId ?? resultado.data.armazemId,
            imagemUrl: dados.imagemUrl ?? resultado.data.imagemUrl,
            subtotal: (dados.estoqueAtual || 1) * (dados.precoCompra || 0),
          }],
          subtotal: (dados.estoqueAtual || 1) * (dados.precoCompra || 0),
          descontoGlobal: 0,
          totalIVA: 0,
          totalGeral: (dados.estoqueAtual || 1) * (dados.precoCompra || 0),
          estado: 'emitido',
          observacoes: dados.observacoes || '',
          armazemId: dados.armazemId,
        };

        console.log('[API] ðŸ“¦ Payload da compra:', JSON.stringify(compraPayload, null, 2));

        const compraResultado = await compras.criarCompra(compraPayload);

        if (compraResultado.success) {
          console.log('[API] âœ…âœ…âœ… Documento de compra criado com sucesso!');
          console.log('[API] ðŸ“„ Número do documento:', compraResultado.data.numeroDocumento);
          console.log('[API] ðŸ“„ ID da compra:', compraResultado.data.id);
        } else {
          console.error('[API] âŒ Erro ao criar documento de compra:', compraResultado.error);
        }
      }
    } else {
      console.log('[API] âš ï¸ NÃƒO criará documento de compra. Dados faltando:');
      if (!dados.fornecedorId) console.log('[API]   âŒ fornecedorId');
      if (!dados.numeroDocumento) console.log('[API]   âŒ numeroDocumento');
      if (!dados.tipoDocumento) console.log('[API]   âŒ tipoDocumento');
    }

    return c.json(resultado);
  } catch (error: any) {
    console.error("[API] âŒ Erro ao atualizar artigo:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Atualizar estoque do artigo
app.patch("/make-server-7249dcd9/artigos/:id/estoque", async (c) => {
  try {
    const chamadorEstoqueArtigo = await obterUsuarioAutenticadoRequest(c);
    if (!chamadorEstoqueArtigo || chamadorEstoqueArtigo.ativo === false) {
      return c.json({ success: false, error: "Utilizador nao autenticado" }, 401);
    }
    const id = c.req.param("id");
    const dados = await lerBodyJsonSeguro(c);
    const { quantidade, operacao } = dados;
    const artigoAntes = await artigos.buscarArtigoPorId(id);
    if (!artigoAntes) {
      return c.json({ success: false, error: "Artigo não encontrado" }, 404);
    }
    if (!isUsuarioSuperAdminTonline(chamadorEstoqueArtigo) && String(chamadorEstoqueArtigo.empresaId || "") !== String(artigoAntes.empresaId || "")) {
      return c.json({ success: false, error: "Nao tem permissao para aceder a esta empresa" }, 403);
    }
    const resultado = await artigos.atualizarEstoque(id, quantidade, operacao);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    await registrarAuditoriaArtigo(c, 'configurar', resultado.data, {
      body: dados,
      antes: artigoAntes,
      extraResumo: {
        operacaoStock: operacao,
        quantidade,
        stockAnterior: artigoAntes?.estoqueAtual,
        stockNovo: resultado.data?.estoqueAtual,
      },
      detalhes: `${(await obterUsuarioAuditoriaRequest(c, dados)).nome || 'Sistema'} ajustou o stock do artigo ${nomeArtigoAuditoria(resultado.data)}. Operacao: ${operacao}; quantidade informada: ${quantidadeAuditoria(quantidade)}; stock anterior: ${quantidadeAuditoria(artigoAntes?.estoqueAtual)}; stock novo: ${quantidadeAuditoria(resultado.data?.estoqueAtual)}.`,
    });

    return c.json(resultado);
  } catch (error) {
    // console.error("[API] Erro ao atualizar estoque:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Deletar artigo
app.delete("/make-server-7249dcd9/artigos/:id", validarAcessoMiddleware("stock-inventario"), async (c) => {
  try {
    const id = c.req.param("id");
    const artigoAntes = await artigos.buscarArtigoPorId(id);
    const resultado = await artigos.deletarArtigo(id);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    await registrarAuditoriaArtigo(c, 'deletar', artigoAntes, {
      body: { id, empresaId: artigoAntes?.empresaId },
      nivel: 'aviso',
      detalhes: `${(await obterUsuarioAuditoriaRequest(c, { empresaId: artigoAntes?.empresaId })).nome || 'Sistema'} eliminou o artigo ${nomeArtigoAuditoria(artigoAntes)}. O sistema tambem removeu ou zerou os stocks associados conforme a rotina de eliminacao.`,
    });

    return c.json(resultado);
  } catch (error) {
    // console.error("[API] Erro ao deletar artigo:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ========== ROTAS DE UPLOADS ==========

// Upload de imagem de artigo
app.post("/make-server-7249dcd9/uploads/artigo-imagem", uploads.uploadArtigoImagem);
app.post("/make-server-7249dcd9/uploads/documento-suporte", uploads.uploadDocumentoSuporte);
app.get("/make-server-7249dcd9/uploads/documento-suporte/signed-url", uploads.getDocumentoSuporteSignedUrl);

// Deletar imagem de artigo
app.delete("/make-server-7249dcd9/uploads/artigo-imagem", uploads.deleteArtigoImagem);
app.delete("/make-server-7249dcd9/uploads/documento-suporte", uploads.deleteDocumentoSuporte);

// ========== FIM ROTAS DE UPLOADS ==========

// Rotas de Backup e Restauracao movidas para admin-router.tsx (admin-server-7249dcd9)

// Ativar/Desativar artigo
app.patch("/make-server-7249dcd9/artigos/:id/toggle", async (c) => {
  try {
    const chamadorToggleArtigo = await obterUsuarioAutenticadoRequest(c);
    if (!chamadorToggleArtigo || chamadorToggleArtigo.ativo === false) {
      return c.json({ success: false, error: "Utilizador nao autenticado" }, 401);
    }
    const id = c.req.param("id");
    const dados = await lerBodyJsonSeguro(c);
    const { ativo } = dados;
    const artigoAntes = await artigos.buscarArtigoPorId(id);
    if (!artigoAntes) {
      return c.json({ success: false, error: "Artigo não encontrado" }, 404);
    }
    if (!isUsuarioSuperAdminTonline(chamadorToggleArtigo) && String(chamadorToggleArtigo.empresaId || "") !== String(artigoAntes.empresaId || "")) {
      return c.json({ success: false, error: "Nao tem permissao para aceder a esta empresa" }, 403);
    }
    const resultado = await artigos.toggleArtigo(id, ativo);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    await registrarAuditoriaArtigo(c, ativo ? 'desbloquear' : 'bloquear', resultado.data, {
      body: dados,
      antes: artigoAntes,
      extraResumo: { ativoAnterior: artigoAntes?.ativo, ativoNovo: resultado.data?.ativo },
    });

    return c.json(resultado);
  } catch (error) {
    // console.error("[API] Erro ao alternar status do artigo:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ========== ROTAS DE COTAÃ‡Ã•ES ==========

// Listar cotaçÃµes de uma empresa
app.get("/make-server-7249dcd9/empresas/:id/cotacoes/proximo-numero", async (c) => {
  try {
    const empresaId = c.req.param("id");
    const dataReferencia = c.req.query("dataEmissao") || c.req.query("dataReferencia") || undefined;
    const exercicio = await exerciciosEconomicos.validarExercicioAberto(empresaId, dataReferencia, "cotacao");
    const cotacoesList = await cotacoes.listarCotacoesPorEmpresa(empresaId);
    const sequenciasDoAno = cotacoesList
      .filter((cotacao: any) => {
        const numeroDocumento = String(cotacao?.numeroDocumento || "");
        const formatoCurto = numeroDocumento.match(/COT\s*\/\s*(\d{4})\s*\/\s*(\d+)/i);
        const formatoFiscal = numeroDocumento.match(/(\d+)\s*\/\s*(\d{4})$/);
        const anoCotacao =
          (formatoCurto ? Number(formatoCurto[1]) : 0) ||
          (formatoFiscal ? Number(formatoFiscal[2]) : 0) ||
          Number(cotacao?.anoExercicio) ||
          Number(String(cotacao?.dataEmissao || "").slice(0, 4)) ||
          new Date(cotacao?.dataEmissao || 0).getFullYear();

        return anoCotacao === exercicio.ano;
      })
      .map((cotacao: any) => {
        const numeroDocumento = String(cotacao?.numeroDocumento || "");
        const formatoCurto = numeroDocumento.match(/COT\s*\/\s*\d{4}\s*\/\s*(\d+)/i);
        const formatoFiscal = numeroDocumento.match(/(\d+)\s*\/\s*\d{4}$/);
        return formatoCurto ? Number(formatoCurto[1]) : formatoFiscal ? Number(formatoFiscal[1]) : 0;
      })
      .filter((sequencia: number) => Number.isFinite(sequencia));

    return c.json({
      success: true,
      data: {
        ano: exercicio.ano,
        proximoNumero: Math.max(0, ...sequenciasDoAno) + 1,
      },
    });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.get("/make-server-7249dcd9/empresas/:id/cotacoes", async (c) => {
  try {
    const id = c.req.param("id");
    const cotacoesList = await cotacoes.listarCotacoesPorEmpresa(id);
    return responderListaPaginada(c, cotacoesList);
  } catch (error) {
    // console.error("[API] Erro ao listar cotaçÃµes:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar cotação por ID
app.get("/make-server-7249dcd9/cotacoes/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const cotacao = await cotacoes.buscarCotacaoPorId(id);

    if (!cotacao) {
      return c.json({ success: false, error: "Cotação não encontrada" }, 404);
    }

    return c.json({ success: true, data: cotacao });
  } catch (error) {
    // console.error("[API] Erro ao buscar cotação:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Criar nova cotação
app.post("/make-server-7249dcd9/cotacoes", async (c) => {
  try {
    const dadosCotacao = await lerBodyJsonSeguro(c);

    console.log('ðŸ” [POST /cotacoes] Iniciando criação de cotação');

    if (!dadosCotacao.empresaId) {
      return c.json({ success: false, error: "empresaId ï¿½ï¿½ obrigatório" }, 400);
    }

    if (!dadosCotacao.itens || dadosCotacao.itens.length === 0) {
      return c.json({ success: false, error: "A cotação deve ter pelo menos um item" }, 400);
    }

    if (!dadosCotacao.clienteId) {
      dadosCotacao.clienteId = '';
    }

    // âœ… NOVO: Capturar dados do usuário que está criando o documento
    console.log('ðŸ” [POST /cotacoes] Tentando capturar dados do usuário...');
    const { getUserFromRequest } = await import('./permission-middleware.tsx');
    const usuario = await getUserFromRequest(c);

    console.log('ðŸ” [POST /cotacoes] Usuário capturado:', usuario);

    if (usuario) {
      dadosCotacao.criadoPor = usuario.nome;
      dadosCotacao.criadoPorId = usuario.id;
      console.log('âœ… [POST /cotacoes] Dados do usuário adicionados:', {
        criadoPor: usuario.nome,
        criadoPorId: usuario.id
      });
    } else {
      console.warn('âš ï¸ [POST /cotacoes] Nenhum usuário encontrado - documento será criado sem criadoPor');
    }

    const novaCotacao = await cotacoes.criarCotacao(dadosCotacao);

    console.log('âœ… [POST /cotacoes] Cotação criada:', {
      id: novaCotacao.id,
      criadoPor: novaCotacao.criadoPor,
      criadoPorId: novaCotacao.criadoPorId
    });

    return c.json({ success: true, data: novaCotacao });
  } catch (error) {
    console.error("[API] Erro ao criar cotação:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Atualizar cotação
app.put("/make-server-7249dcd9/cotacoes/:id",
  requirePermission('faturacao.cotacao.editar'), // âœ… FIX: Usar novo formato de permissão
  async (c) => {
  try {
    const id = c.req.param("id");
    const dadosCotacao = await lerBodyJsonSeguro(c);

    const cotacaoExistente = await cotacoes.buscarCotacaoPorId(id);
    if (!cotacaoExistente) {
      return c.json({ success: false, error: "Cotação não encontrada" }, 404);
    }
    const validacaoEdicao = cotacoes.podeEditarCotacaoComAdiantamentos(cotacaoExistente);
    if (!validacaoEdicao.pode) {
      return c.json({ success: false, error: validacaoEdicao.motivo }, 400);
    }

    // âœ… NOVO: Capturar dados do usuário que está editando o documento
    const { getUserFromRequest } = await import('./permission-middleware.tsx');
    const usuario = await getUserFromRequest(c);

    if (usuario) {
      dadosCotacao.editadoPor = usuario.nome;
      dadosCotacao.editadoPorId = usuario.id;
    }

    const cotacaoAtualizada = await cotacoes.atualizarCotacao(id, dadosCotacao);

    return c.json({ success: true, data: cotacaoAtualizada });
  } catch (error) {
    console.error("[API] Erro ao atualizar cotação:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Excluir cotação
app.delete("/make-server-7249dcd9/cotacoes/:id",
  requirePermission('faturacao.cotacao.deletar'),
  async (c) => {
  try {
    const id = c.req.param("id");
    const body = await lerBodyJsonSeguro(c);
    await preencherUsuarioDocumento(c, body, 'editar');

    const cotacaoEliminada = await cotacoes.excluirCotacao(id, {
      motivo: body.motivo,
      usuarioId: body.usuarioAuditoriaId,
      usuarioNome: body.usuarioAuditoriaNome,
      usuarioEmail: body.usuarioAuditoriaEmail,
    });

    return c.json({
      success: true,
      data: cotacaoEliminada,
      message: "Cotação eliminada e número libertado com sucesso",
    });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 400);
  }
});

app.patch("/make-server-7249dcd9/cotacoes/:id/estado",
  requireAnyPermission('faturacao.cotacao.aprovar', 'faturacao.cotacao.rejeitar', 'faturacao.cotacao.editar'),
  async (c) => {
  try {
    const id = c.req.param("id");
    const { estado } = await lerBodyJsonSeguro(c);

    const cotacaoExistente = await cotacoes.buscarCotacaoPorId(id);
    if (!cotacaoExistente) {
      return c.json({ success: false, error: "Cotação não encontrada" }, 404);
    }
    const transicoesPermitidas: Record<string, string[]> = {
      pendente: ['aprovada', 'rejeitada', 'expirada', 'anulada'],
      aprovada: ['rejeitada', 'expirada', 'anulada'],
      rejeitada: ['aprovada', 'anulada'],
      expirada: ['aprovada', 'anulada'],
      convertida: [],
      anulada: [],
    };
    if (!transicoesPermitidas[cotacaoExistente.estado]?.includes(estado)) {
      return c.json({
        success: false,
        error: `Transição de ${cotacaoExistente.estado} para ${estado} não permitida.`,
      }, 400);
    }

    const cotacaoAtualizada = await cotacoes.alterarEstadoCotacao(id, estado);

    return c.json({ success: true, data: cotacaoAtualizada });
  } catch (error) {
    console.error("[API] Erro ao alterar estado da cotação:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar cotaçÃµes por cliente
app.get("/make-server-7249dcd9/empresas/:empresaId/clientes/:clienteId/cotacoes", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const clienteId = c.req.param("clienteId");

    const cotacoesList = await cotacoes.buscarCotacoesPorCliente(empresaId, clienteId);

    return c.json({ success: true, data: cotacoesList });
  } catch (error) {
    // console.error("[API] Erro ao buscar cotaçÃµes do cliente:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// âœ… NOVA: Verificar se pode editar cotação
app.get("/make-server-7249dcd9/cotacoes/:id/pode-editar", async (c) => {
  try {
    const id = c.req.param("id");
    const cotacao = await cotacoes.buscarCotacaoPorId(id);

    if (!cotacao) {
      return c.json({ success: false, error: "Cotação não encontrada" }, 404);
    }

    // âœ… ATUALIZADO: Usar nova função com verificação de adiantamentos
    const resultado = cotacoes.podeEditarCotacaoComAdiantamentos(cotacao);

    return c.json({ success: true, data: resultado });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// âœ… NOVA: Verificar se pode eliminar cotação
app.get("/make-server-7249dcd9/cotacoes/:id/pode-eliminar", async (c) => {
  try {
    const id = c.req.param("id");
    const cotacao = await cotacoes.buscarCotacaoPorId(id);

    if (!cotacao) {
      return c.json({ success: false, error: "Cotação não encontrada" }, 404);
    }

    const resultado = await cotacoes.podeEliminarCotacaoComAdiantamentos(cotacao);

    return c.json({ success: true, data: resultado });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.get("/make-server-7249dcd9/cotacoes/:id/pode-anular", async (c) => {
  try {
    const id = c.req.param("id");
    const cotacao = await cotacoes.buscarCotacaoPorId(id);

    if (!cotacao) {
      return c.json({ success: false, error: "Cotação não encontrada" }, 404);
    }

    const resultado = cotacoes.podeAnularCotacao(cotacao);

    return c.json({ success: true, data: resultado });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// âœ… NOVA: Calcular estado financeiro da cotação
app.get("/make-server-7249dcd9/cotacoes/:id/estado-financeiro", async (c) => {
  try {
    const id = c.req.param("id");
    const cotacao = await cotacoes.buscarCotacaoPorId(id);

    if (!cotacao) {
      return c.json({ success: false, error: "Cotação não encontrada" }, 404);
    }

    const estadoFinanceiro = cotacoes.calcularEstadoFinanceiro(cotacao);

    return c.json({ success: true, data: estadoFinanceiro });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// âœ… NOVA: Registrar adiantamento em cotação
app.post("/make-server-7249dcd9/cotacoes/:id/registrar-adiantamento", async (c) => {
  try {
    const id = c.req.param("id");
    const { adiantamentoId, valor } = await lerBodyJsonSeguro(c);

    console.log('[API] Registrando adiantamento:', { id, adiantamentoId, valor });

    if (!adiantamentoId || !valor) {
      console.error('[API] Parâmetros inválidos:', { adiantamentoId, valor });
      return c.json({ success: false, error: "adiantamentoId e valor são obrigatórios" }, 400);
    }

    const cotacaoAtualizada = await cotacoes.registrarAdiantamento(id, adiantamentoId, valor);

    console.log('[API] Adiantamento registrado com sucesso:', cotacaoAtualizada.id);
    return c.json({ success: true, data: cotacaoAtualizada, message: "Adiantamento registrado com sucesso" });
  } catch (error) {
    console.error("[API] Erro ao registrar adiantamento:", error);
    return c.json({ success: false, error: error.message || 'Erro desconhecido ao registrar adiantamento' }, 500);
  }
});

// ✅ Equivalente a /cotacoes/:id/registrar-adiantamento mas para Facturas
// (tipicamente Facturas Proforma, que sao guardadas como Factura e nao como
// Cotacao — o ecra de Adiantamentos permite associar a qualquer um dos dois).
app.post("/make-server-7249dcd9/facturas/:id/registrar-adiantamento", async (c) => {
  try {
    const id = c.req.param("id");
    const { adiantamentoId, valor } = await lerBodyJsonSeguro(c);

    if (!adiantamentoId || !valor) {
      return c.json({ success: false, error: "adiantamentoId e valor são obrigatórios" }, 400);
    }

    const facturaAtualizada = await facturas.registrarAdiantamento(id, adiantamentoId, valor);

    return c.json({ success: true, data: facturaAtualizada, message: "Adiantamento registrado com sucesso" });
  } catch (error) {
    console.error("[API] Erro ao registrar adiantamento na factura:", error);
    return c.json({ success: false, error: error.message || 'Erro desconhecido ao registrar adiantamento' }, 500);
  }
});

// âœ… NOVA: Anular cotação
app.post("/make-server-7249dcd9/cotacoes/:id/anular",
  requirePermission('faturacao.cotacao.editar'),
  async (c) => {
  try {
    const id = c.req.param("id");
    const { motivo } = await lerBodyJsonSeguro(c);

    if (!motivo || motivo.trim() === '') {
      return c.json({ success: false, error: "Motivo de anulação é obrigatório" }, 400);
    }

    const cotacaoAnulada = await cotacoes.anularCotacao(id, motivo);

    return c.json({ success: true, data: cotacaoAnulada, message: "Cotação anulada com sucesso" });
  } catch (error) {
    console.error("[API] Erro ao anular cotação:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// âœ… NOVA: Registrar documento originado de cotação
app.post("/make-server-7249dcd9/cotacoes/:id/registrar-documento", async (c) => {
  try {
    const id = c.req.param("id");
    const { documentoId, tipoDocumento } = await lerBodyJsonSeguro(c);

    if (!documentoId || !tipoDocumento) {
      return c.json({ success: false, error: "documentoId e tipoDocumento são obrigatórios" }, 400);
    }

    if (!['factura', 'adiantamento'].includes(tipoDocumento)) {
      return c.json({ success: false, error: "tipoDocumento deve ser 'factura' ou 'adiantamento'" }, 400);
    }

    const cotacaoAtualizada = await cotacoes.registrarDocumentoOriginado(id, documentoId, tipoDocumento);

    return c.json({ success: true, data: cotacaoAtualizada });
  } catch (error) {
    console.error("[API] Erro ao registrar documento originado:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Rota POST /migrar-formato-numeros movida para admin-router.tsx (admin-server-7249dcd9)

// ========== ROTAS DE FACTURAS ==========

// ========== ROTAS DE FACTURAS-RECIBO ==========

app.get("/make-server-7249dcd9/empresas/:id/facturas-recibo/proximo-numero", async (c) => {
  try {
    const empresaId = c.req.param("id");
    const serieId = c.req.query("serieId") || undefined;
    const serieNome = c.req.query("serieNome") || undefined;
    const serieCodigo = c.req.query("serieCodigo") || undefined;
    const serieFormato = c.req.query("serieFormato") || undefined;
    const dataReferencia = c.req.query("dataEmissao") || c.req.query("dataReferencia") || undefined;
    const serieReferencia = serieNome || serieCodigo || serieFormato
      ? {
          id: serieId,
          tipoDocumento: "factura_recibo",
          nome: serieNome,
          codigo: serieCodigo,
          formato: serieFormato,
        }
      : serieId;
    const exercicio = await exerciciosEconomicos.validarExercicioAberto(empresaId, dataReferencia, "factura-recibo");
    const numeroGerado = await facturas.preverProximoNumeroDocumentoFactura(empresaId, "factura_recibo", serieReferencia, exercicio.ano);

    return c.json({ success: true, data: { numeroDocumento: numeroGerado } });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.get("/make-server-7249dcd9/empresas/:id/facturas-recibo", validarAcessoMiddleware("faturacao-vendas"), async (c) => {
  try {
    const empresaId = c.req.param("id");
    const facturasList = await facturas.listarFacturasPorEmpresa(empresaId);
    const facturasRecibo = facturasList.filter((factura: any) => {
      const tipoActual = ((factura?.tipoDocumento || "factura") as string).trim().toLowerCase();
      return tipoActual === "factura_recibo";
    });

    return responderListaPaginada(c, facturasRecibo);
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.get("/make-server-7249dcd9/facturas-recibo/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const facturaRecibo = await facturas.buscarFacturaPorId(id);

    if (!facturaRecibo || ((facturaRecibo.tipoDocumento || "factura") as string).trim().toLowerCase() !== "factura_recibo") {
      return c.json({ success: false, error: "Factura-Recibo não encontrada" }, 404);
    }

    return c.json({ success: true, data: facturaRecibo });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.post("/make-server-7249dcd9/facturas-recibo", validarAcessoMiddleware("faturacao-vendas"), async (c) => {
  try {
    const dadosFacturaRecibo = await lerBodyJsonSeguro(c);
    await preencherUsuarioDocumento(c, dadosFacturaRecibo, 'criar');
    dadosFacturaRecibo.tipoDocumento = "factura_recibo";
    dadosFacturaRecibo.condicaoPagamento = "pronto_pagamento";
    dadosFacturaRecibo.dataVencimento = dadosFacturaRecibo.dataEmissao;
    dadosFacturaRecibo.dataPagamento = dadosFacturaRecibo.dataPagamento || dadosFacturaRecibo.dataEmissao;
    dadosFacturaRecibo.estado = "paga";

    if (!dadosFacturaRecibo.empresaId) {
      return c.json({ success: false, error: "empresaId é obrigatório" }, 400);
    }

    if (!dadosFacturaRecibo.clienteId) {
      return c.json({ success: false, error: "clienteId é obrigatório" }, 400);
    }

    if (!dadosFacturaRecibo.itens || dadosFacturaRecibo.itens.length === 0) {
      return c.json({ success: false, error: "A factura-recibo deve ter pelo menos um item" }, 400);
    }

    // ✅ A pre-validacao contabilistica tem de usar os totais calculados pelo
    // servidor (subtotal/totalImpostos/totalGeral), nao os que o formulario
    // enviou — sao dois calculos independentes que podem divergir por
    // arredondamento, e essa divergencia fazia o lancamento parecer
    // desequilibrado mesmo quando o documento que ia ser gravado batia certo.
    const dadosFacturaReciboPrevalidados = await aplicarTotaisFiscais(dadosFacturaRecibo);
    const prevalidacaoContabilidadeFacturaRecibo = await contabilizarDocumentoFiscalOperacional(
      {
        ...dadosFacturaReciboPrevalidados,
        id: dadosFacturaRecibo.id || `prevalidacao_factura_recibo_${Date.now()}`,
        numeroDocumento: dadosFacturaRecibo.numeroDocumento || 'Factura-Recibo em preparacao',
      },
      'factura_recibo',
      { previsualizar: true },
    );
    const erroContabilidadeFacturaRecibo = respostaErroContabilidadeObrigatoria(
      prevalidacaoContabilidadeFacturaRecibo,
      'factura-recibo',
    );
    if (erroContabilidadeFacturaRecibo) {
      return c.json(erroContabilidadeFacturaRecibo, 400);
    }

    const novaFacturaRecibo = await facturas.criarFactura(dadosFacturaRecibo);

    let resultadoConversaoCotacaoRecibo: any = { success: true, skipped: true };
    if (dadosFacturaRecibo.cotacaoId) {
      try {
        await cotacoes.registrarConversao(dadosFacturaRecibo.cotacaoId, novaFacturaRecibo.id, 'factura');
        resultadoConversaoCotacaoRecibo = { success: true };
      } catch (error: any) {
        // A criação da Factura-Recibo não deve falhar por causa disso, mas a falha
        // é registada como pendência de integração em vez de desaparecer em silêncio.
        console.error(`[API] Erro ao marcar cotação ${dadosFacturaRecibo.cotacaoId} como convertida:`, error);
        resultadoConversaoCotacaoRecibo = { success: false, error: error?.message || String(error) };
      }
    } else if (dadosFacturaRecibo.cotacaoReferencia) {
      // ✅ Mesmo motivo do endpoint /facturas — ver registrarConversaoProforma.
      try {
        await facturas.registrarConversaoProforma(dadosFacturaRecibo.empresaId, dadosFacturaRecibo.cotacaoReferencia, novaFacturaRecibo.id);
        resultadoConversaoCotacaoRecibo = { success: true };
      } catch (error: any) {
        console.error(`[API] Erro ao marcar proforma "${dadosFacturaRecibo.cotacaoReferencia}" como convertida:`, error);
        resultadoConversaoCotacaoRecibo = { success: false, error: error?.message || String(error) };
      }
    }

    await registrarAuditoriaFactura(c, 'criar', novaFacturaRecibo, { body: dadosFacturaRecibo });

    const resultadoContabilidadeFacturaRecibo = await contabilizarDocumentoFiscalOperacional(novaFacturaRecibo, 'factura_recibo');
    const resultadoCMVFacturaRecibo = await contabilizarMovimentosStockDocumento(
      novaFacturaRecibo.empresaId,
      novaFacturaRecibo.numeroDocumento,
      'Factura-Recibo',
      { criadoPor: dadosFacturaRecibo.criadoPor || dadosFacturaRecibo.usuarioId },
    );
    const facturaReciboComContabilidade = await anexarResultadoContabilidade(novaFacturaRecibo, {
      venda: resultadoContabilidadeFacturaRecibo,
      cmvmc: resultadoCMVFacturaRecibo,
      cotacao: resultadoConversaoCotacaoRecibo,
    });

    return responderDocumentoIntegrado(c, facturaReciboComContabilidade);
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.put("/make-server-7249dcd9/facturas-recibo/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const dadosFacturaRecibo = await lerBodyJsonSeguro(c);
    dadosFacturaRecibo.tipoDocumento = "factura_recibo";
    dadosFacturaRecibo.condicaoPagamento = "pronto_pagamento";
    dadosFacturaRecibo.dataVencimento = dadosFacturaRecibo.dataEmissao;
    dadosFacturaRecibo.dataPagamento = dadosFacturaRecibo.dataPagamento || dadosFacturaRecibo.dataEmissao;
    dadosFacturaRecibo.estado = "paga";

    const facturaReciboAtualizada = await facturas.atualizarFactura(id, dadosFacturaRecibo);

    // ✅ Mesma correcao aplicada a PUT /facturas/:id — atualizarFactura apaga
    // e recria os movimentos de stock sem nunca chamar a contabilidade,
    // deixando o lancamento de CMV antigo orfao e o novo sem lancamento.
    await removerLancamentosContabeisRascunhoDoDocumento({
      empresaId: facturaReciboAtualizada.empresaId,
      documentoId: facturaReciboAtualizada.id,
      numeroDocumento: facturaReciboAtualizada.numeroDocumento,
    }).catch(() => []);

    const resultadoContabilidadeFRecEditada = await contabilizarDocumentoFiscalOperacional(facturaReciboAtualizada, 'factura_recibo');
    const resultadoCMVFRecEditada = await contabilizarMovimentosStockDocumento(
      facturaReciboAtualizada.empresaId,
      facturaReciboAtualizada.numeroDocumento,
      'Factura-Recibo',
      { criadoPor: dadosFacturaRecibo.criadoPor || dadosFacturaRecibo.usuarioId },
    );
    const facturaReciboEditadaComContabilidade = await anexarResultadoContabilidade(facturaReciboAtualizada, {
      venda: resultadoContabilidadeFRecEditada,
      cmvmc: resultadoCMVFRecEditada,
    });

    return responderDocumentoIntegrado(c, facturaReciboEditadaComContabilidade);
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Eliminar Factura-Recibo - BLOQUEADO (Requisito Financas/AT: nenhum
// documento fiscal pode ser eliminado). Use POST /facturas/:id/anular
// (funciona para qualquer tipoDocumento, incluindo factura_recibo).
app.delete("/make-server-7249dcd9/facturas-recibo/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const body = await lerBodyJsonSeguro(c);
    await preencherUsuarioDocumento(c, body, 'editar');

    const facturaEliminada = await facturas.excluirFactura(id, {
      motivo: body.motivo,
      usuarioId: body.usuarioAuditoriaId,
      usuarioNome: body.usuarioAuditoriaNome,
      usuarioEmail: body.usuarioAuditoriaEmail,
    });

    return c.json({
      success: true,
      data: facturaEliminada,
      message: "Factura-Recibo eliminada e número libertado com sucesso",
    });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 400);
  }
});

// ðŸŽ¯ NOVO: Prever próximo número de factura (sem consumir a sequência)
app.get("/make-server-7249dcd9/empresas/:id/facturas/proximo-numero", async (c) => {
  try {
    const empresaId = c.req.param("id");
    const tipoDocumento = c.req.query("tipoDocumento") || "factura";
    const serieId = c.req.query("serieId") || undefined;
    const serieNome = c.req.query("serieNome") || undefined;
    const serieCodigo = c.req.query("serieCodigo") || undefined;
    const serieFormato = c.req.query("serieFormato") || undefined;
    const dataReferencia = c.req.query("dataEmissao") || c.req.query("dataReferencia") || undefined;
    const serieReferencia = serieNome || serieCodigo || serieFormato
      ? {
          id: serieId,
          tipoDocumento,
          nome: serieNome,
          codigo: serieCodigo,
          formato: serieFormato,
        }
      : serieId;
    const exercicio = await exerciciosEconomicos.validarExercicioAberto(empresaId, dataReferencia, String(tipoDocumento || "factura"));
    const numeroGerado = await facturas.preverProximoNumeroDocumentoFactura(empresaId, tipoDocumento, serieReferencia, exercicio.ano);

    return c.json({ success: true, data: { numeroDocumento: numeroGerado } });
  } catch (error) {
    // console.error("[API] Erro ao gerar número de factura:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Listar facturas de uma empresa
app.get("/make-server-7249dcd9/empresas/:id/facturas", validarAcessoMiddleware("faturacao-vendas"), async (c) => {
  try {
    const id = c.req.param("id");
    const tipoDocumento = (c.req.query("tipoDocumento") || "").trim().toLowerCase();
    const facturasList = await facturas.listarFacturasPorEmpresa(id);
    const facturasFiltradas = tipoDocumento
      ? facturasList.filter((factura: any) => {
          const tipoActual = ((factura?.tipoDocumento || "factura") as string).trim().toLowerCase();
          return tipoActual === tipoDocumento;
        })
      : facturasList;

    return responderListaPaginada(c, facturasFiltradas);
  } catch (error) {
    // console.error("[API] Erro ao listar facturas:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar factura por ID
app.get("/make-server-7249dcd9/facturas/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const factura = await facturas.buscarFacturaPorId(id);

    if (!factura) {
      return c.json({ success: false, error: "Factura não encontrada" }, 404);
    }

    return c.json({ success: true, data: factura });
  } catch (error) {
    // console.error("[API] Erro ao buscar factura:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Criar nova factura
app.post("/make-server-7249dcd9/facturas", validarAcessoMiddleware("faturacao-vendas"), async (c) => {
  try {
    // âœ… CORRIGIDO: Usar body cacheado se existir (já foi lido pelo middleware)
    const dadosFactura = await lerBodyJsonSeguro(c);
    await preencherUsuarioDocumento(c, dadosFactura, 'criar');

    if (!dadosFactura.empresaId) {
      return c.json({ success: false, error: "empresaId é obrigatório" }, 400);
    }

    if (!dadosFactura.clienteId) {
      return c.json({ success: false, error: "clienteId ï¿½ï¿½ obrigatório" }, 400);
    }

    if (!dadosFactura.itens || dadosFactura.itens.length === 0) {
      return c.json({ success: false, error: "A factura deve ter pelo menos um item" }, 400);
    }

    const tipoDocumentoCriacao = String(dadosFactura.tipoDocumento || 'factura').trim().toLowerCase().replace(/-/g, '_');
    const documentoEhProforma = tipoDocumentoCriacao === 'factura_proforma' || tipoDocumentoCriacao === 'proforma';
    const novaFactura = await facturas.criarFactura(dadosFactura);

    // NOVO: Se factura foi criada a partir de uma cotação, marcar cotação como CONVERTIDA
    // Usar cotacaoId (ID completo) em vez de cotacaoReferencia (número do documento)
    let resultadoConversaoCotacao: any = { success: true, skipped: true };
    if (dadosFactura.cotacaoId && !documentoEhProforma) {
      try {
        await cotacoes.registrarConversao(dadosFactura.cotacaoId, novaFactura.id, 'factura');
        resultadoConversaoCotacao = { success: true };
      } catch (error: any) {
        console.error(`[API] Erro ao marcar cotacao ${dadosFactura.cotacaoId} como convertida:`, error);
        resultadoConversaoCotacao = { success: false, error: error?.message || String(error) };
      }
    } else if (dadosFactura.cotacaoReferencia && !documentoEhProforma) {
      // ✅ Uma Factura Proforma nao preenche cotacaoId (so cotacaoReferencia,
      // texto livre) — ver registrarConversaoProforma para o porque.
      try {
        await facturas.registrarConversaoProforma(dadosFactura.empresaId, dadosFactura.cotacaoReferencia, novaFactura.id);
        resultadoConversaoCotacao = { success: true };
      } catch (error: any) {
        console.error(`[API] Erro ao marcar proforma "${dadosFactura.cotacaoReferencia}" como convertida:`, error);
        resultadoConversaoCotacao = { success: false, error: error?.message || String(error) };
      }
    }

    await registrarAuditoriaFactura(c, 'criar', novaFactura, { body: dadosFactura });

    if (documentoEhProforma) {
      return c.json({ success: true, data: novaFactura });
    }

    const resultadoContabilidadeFactura = await contabilizarDocumentoFiscalOperacional(novaFactura, 'fatura');
    const resultadoCMVFactura = await contabilizarMovimentosStockDocumento(
      novaFactura.empresaId,
      novaFactura.numeroDocumento,
      'Factura',
      { criadoPor: dadosFactura.criadoPor || dadosFactura.usuarioId },
    );
    const resultadoInterempresaFactura = await sincronizarCompraInterempresaVenda(
      novaFactura,
      novaFactura.tipoDocumento === 'factura_recibo' ? 'factura_recibo' : 'factura',
    );
    const facturaComContabilidade = await anexarResultadoContabilidade(novaFactura, {
      venda: resultadoContabilidadeFactura,
      cmvmc: resultadoCMVFactura,
      interempresa: resultadoInterempresaFactura,
      cotacao: resultadoConversaoCotacao,
    });

    return responderDocumentoIntegrado(c, facturaComContabilidade);
  } catch (error) {
    // console.error("[API] Erro ao criar factura:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Atualizar factura
app.put("/make-server-7249dcd9/facturas/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const dadosFactura = await lerBodyJsonSeguro(c);

    // ðŸ” VALIDAÃ‡ÃƒO OBRIGATÃ“RIA DE AUTORIZAÃ‡ÃƒO
    if (dadosFactura.usuario) {
      const facturaExistente = await facturas.buscarFacturaPorId(id);

      if (facturaExistente) {
        const authResult = await authorization.canEdit(
          dadosFactura.usuario,
          {
            id: facturaExistente.id,
            empresaId: facturaExistente.empresaId,
            tipo: 'factura',
            estado: facturaExistente.estado,
          }
        );

        if (!authResult.permitido) {
          return c.json({
            success: false,
            error: authResult.motivo,
            code: 'AUTHORIZATION_DENIED'
          }, 403);
        }
      }
    }

    const facturaAtualizada = await facturas.atualizarFactura(id, dadosFactura);

    // ✅ atualizarFactura sempre apaga e recria os movimentos de stock das
    // linhas de produto (mesmo so a mudar observacoes), mas nunca chamava a
    // contabilidade — o lancamento de CMV antigo (rascunho, porque
    // podeEditarFactura ja bloqueia se estiver lancado) ficava orfao a
    // apontar para um movimento apagado, o novo movimento nunca recebia
    // lancamento nenhum, e o lancamento de venda nao reflectia os valores
    // editados. Repete aqui exactamente o mesmo passo que a criacao (POST)
    // ja fazia, apos limpar os rascunhos desactualizados.
    const tipoDocumentoEditado = String(facturaAtualizada.tipoDocumento || 'factura').trim().toLowerCase().replace(/-/g, '_');
    const documentoEditadoEhProforma = tipoDocumentoEditado === 'factura_proforma' || tipoDocumentoEditado === 'proforma';

    if (documentoEditadoEhProforma) {
      return c.json({ success: true, data: facturaAtualizada });
    }

    await removerLancamentosContabeisRascunhoDoDocumento({
      empresaId: facturaAtualizada.empresaId,
      documentoId: facturaAtualizada.id,
      numeroDocumento: facturaAtualizada.numeroDocumento,
    }).catch(() => []);

    const resultadoContabilidadeFacturaEditada = await contabilizarDocumentoFiscalOperacional(facturaAtualizada, 'fatura');
    const resultadoCMVFacturaEditada = await contabilizarMovimentosStockDocumento(
      facturaAtualizada.empresaId,
      facturaAtualizada.numeroDocumento,
      'Factura',
      { criadoPor: dadosFactura.criadoPor || dadosFactura.usuarioId },
    );
    const facturaEditadaComContabilidade = await anexarResultadoContabilidade(facturaAtualizada, {
      venda: resultadoContabilidadeFacturaEditada,
      cmvmc: resultadoCMVFacturaEditada,
    });

    return responderDocumentoIntegrado(c, facturaEditadaComContabilidade);
  } catch (error) {
    // console.error("[API] Erro ao atualizar factura:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Excluir factura
// Eliminar factura - BLOQUEADO (Requisito Financas/AT: nenhum documento
// fiscal pode ser eliminado). excluirFactura() recusa sempre, ver
// facturas.tsx. Rota mantida (em vez de removida) para dar sempre uma
// mensagem clara em vez de 404.
app.delete("/make-server-7249dcd9/facturas/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const body = await lerBodyJsonSeguro(c);
    await preencherUsuarioDocumento(c, body, 'editar');

    const facturaExistente = await facturas.buscarFacturaPorId(id);
    if (!facturaExistente) {
      return c.json({ success: false, error: "Factura não encontrada" }, 404);
    }

    const facturaEliminada = await facturas.excluirFactura(id, {
      motivo: body.motivo,
      usuarioId: body.usuarioAuditoriaId,
      usuarioNome: body.usuarioAuditoriaNome,
      usuarioEmail: body.usuarioAuditoriaEmail,
    });
    await reverterCotacaoOrigemSeLivre(facturaExistente).catch(() => null);

    return c.json({
      success: true,
      data: facturaEliminada,
      message: "Factura eliminada e número libertado com sucesso",
    });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 400);
  }
});

// Anular factura - substitui a eliminacao. Preserva o documento, o numero
// e o historico.
app.post("/make-server-7249dcd9/facturas/:id/anular", async (c) => {
  try {
    const body = await lerBodyJsonSeguro(c, {});
    const facturaAnulada = await facturas.anularFactura(c.req.param("id"), body?.motivo);
    // Liberta a cotacao de origem (se ainda nao tiver outro documento activo
    // ligado a ela) para poder ser convertida de novo - a factura anulada
    // continua a existir como registo historico, so deixa de "ocupar" a
    // cotacao.
    await reverterCotacaoOrigemSeLivre(facturaAnulada).catch(() => null);
    return c.json({ success: true, data: facturaAnulada, message: "Factura anulada com sucesso" });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Alterar estado da factura
app.patch("/make-server-7249dcd9/facturas/:id/estado", async (c) => {
  try {
    const id = c.req.param("id");
    const { estado } = await lerBodyJsonSeguro(c);

    const facturaExistente = await facturas.buscarFacturaPorId(id);
    if (!facturaExistente) {
      return c.json({ success: false, error: "Factura não encontrada" }, 404);
    }
    if (facturaExistente.estado === 'anulado') {
      return c.json({ success: false, error: "Uma factura anulada não pode mudar de estado." }, 400);
    }
    if (!['pendente', 'vencida'].includes(String(estado))) {
      return c.json({
        success: false,
        error: "O estado pago, parcial ou anulado só pode resultar dos respectivos documentos fiscais.",
      }, 400);
    }
    const hoje = new Date().toISOString().slice(0, 10);
    const estadoEsperado = facturaExistente.dataVencimento < hoje ? 'vencida' : 'pendente';
    if (estado !== estadoEsperado) {
      return c.json({ success: false, error: `O estado correcto pela data de vencimento é ${estadoEsperado}.` }, 400);
    }

    const facturaAtualizada = await facturas.alterarEstadoFactura(id, estado);

    return c.json({ success: true, data: facturaAtualizada });
  } catch (error) {
    // console.error("[API] Erro ao alterar estado da factura:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// âœ… NOVA: Verificar se pode editar factura
app.get("/make-server-7249dcd9/facturas/:id/pode-editar", async (c) => {
  try {
    const id = c.req.param("id");
    const factura = await facturas.buscarFacturaPorId(id);

    if (!factura) {
      return c.json({ success: false, error: "Factura não encontrada" }, 404);
    }

    const resultado = await facturas.podeEditarFactura(factura);

    return c.json({ success: true, data: resultado });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// âœ… NOVA: Verificar se pode eliminar factura
app.get("/make-server-7249dcd9/facturas/:id/pode-eliminar", async (c) => {
  try {
    const id = c.req.param("id");
    const factura = await facturas.buscarFacturaPorId(id);

    if (!factura) {
      return c.json({ success: false, error: "Factura não encontrada" }, 404);
    }

    const resultado = await facturas.podeEliminarFactura(factura);

    return c.json({ success: true, data: resultado });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.get("/make-server-7249dcd9/facturas/:id/pode-anular", async (c) => {
  try {
    const id = c.req.param("id");
    const factura = await facturas.buscarFacturaPorId(id);

    if (!factura) {
      return c.json({ success: false, error: "Factura não encontrada" }, 404);
    }

    const resultado = await facturas.podeAnularFactura(factura);

    return c.json({ success: true, data: resultado });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar facturas por cliente
app.get("/make-server-7249dcd9/empresas/:empresaId/clientes/:clienteId/facturas", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const clienteId = c.req.param("clienteId");

    const facturasList = await facturas.buscarFacturasPorCliente(empresaId, clienteId);

    return c.json({ success: true, data: facturasList });
  } catch (error) {
    // console.error("[API] Erro ao buscar facturas do cliente:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar TODAS as facturas disponíveis (não pagas, sem recibos) de uma empresa
app.get("/make-server-7249dcd9/empresas/:empresaId/facturas-disponiveis", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const mostrarTodos = c.req.query("mostrarTodos") === "true" || c.req.query("mostrarTodos") === "1";

    console.log(`[Recibos] Buscando todas as facturas disponíveis para empresa ${empresaId}`);

    // Buscar todas as facturas da empresa
    const facturasList = await facturas.listarFacturasPorEmpresa(empresaId);

    // Se "mostrarTodos" estiver ativo, incluir também facturas pagas.
    // Mantemos fora apenas documentos anulados/cancelados ou sem valor.
    const facturasFiltradas = facturasList.filter((f: any) => {
      const estado = String(f.estado || '').toLowerCase();
      const tipoDocumento = String(f.tipoDocumento || 'factura').trim().toLowerCase().replace(/-/g, '_');

      if (tipoDocumento === 'factura_proforma' || tipoDocumento === 'proforma') {
        return false;
      }

      if (['anulado', 'cancelada', 'cancelado'].includes(estado)) {
        return false;
      }

      if (Number(f.totalGeral) <= 0) {
        return false;
      }

      if (mostrarTodos) {
        return true;
      }

      return !['paga', 'pago'].includes(estado);
    });

    // Buscar todos os recibos da empresa
    const todosRecibos = await recibos.listarRecibosPorEmpresa(empresaId);

    // Calcular o total pago por cada factura
    const pagamentosPorFactura = new Map<string, number>();

    todosRecibos.forEach((recibo: any) => {
      if (recibo.estado === 'anulado') return;

      if (recibo.pagamentos && Array.isArray(recibo.pagamentos)) {
        recibo.pagamentos.forEach((pag: any) => {
          if (pag.facturaId && pag.valorPago) {
            const atual = pagamentosPorFactura.get(pag.facturaId) || 0;
            pagamentosPorFactura.set(pag.facturaId, atual + Number(pag.valorPago));
          }
        });
      }

      if (recibo.itens && Array.isArray(recibo.itens)) {
        recibo.itens.forEach((item: any) => {
          if (item.facturaId && item.valorPago) {
            const atual = pagamentosPorFactura.get(item.facturaId) || 0;
            pagamentosPorFactura.set(item.facturaId, atual + Number(item.valorPago));
          }
        });
      }
    });

    // Filtrar apenas facturas não usadas totalmente em recibos (exceto a verificação de saldo que o front end deve fazer caso inclua a atual na edição)
    // Devolvemos todas as faturas em aberto ou associadas. Na verdade vamos devolver todas as em aberto + seu saldo.
    const facturasDisponiveis = facturasFiltradas.map((f: any) => {
      const totalPago = pagamentosPorFactura.get(f.id) || 0;
      const saldoEmAberto = Number(f.totalGeral) - totalPago;
      return { ...f, saldoEmAberto };
    });
    // Opcionalmente podemos filtrar pelo lado do backend também, mas como na edição
    // a fatura que já faz parte do recibo terá saldo 0 e deve ser exibida para não sumir
    // da interface, vamos permitir que faturas com saldo <= 0 também desçam se chamadas pela api,
    // e o frontend tratará de filtrar ou exibir (já implementado no frontend).
    // MAS por regra 1 não queremos pagas. A menos que a gente passe o reciboId pra exceção.
    // Para resolver isso de forma robusta e garantir que NÃƒO aparecem pagas num "novo recibo"
    // passamos tudo e o frontend faz a lógica baseada em "isEditing" que já criamos lá.

    return c.json({ success: true, data: facturasDisponiveis });
  } catch (error) {
    console.error("[API] Erro ao buscar todas facturas disponíveis:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar facturas disponíveis (não pagas, sem recibos) de um cliente
app.get("/make-server-7249dcd9/empresas/:empresaId/clientes/:clienteId/facturas-disponiveis", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const clienteId = c.req.param("clienteId");
    const mostrarTodos = c.req.query("mostrarTodos") === "true" || c.req.query("mostrarTodos") === "1";

    console.log(`[Recibos] Buscando facturas disponíveis para cliente ${clienteId}`);

    // Buscar todas as facturas do cliente
    const facturasList = await facturas.buscarFacturasPorCliente(empresaId, clienteId);

    // Se "mostrarTodos" estiver ativo, incluir também facturas pagas.
    // Mantemos fora apenas documentos anulados/cancelados ou sem valor.
    const facturasFiltradas = facturasList.filter((f: any) => {
      const estado = String(f.estado || '').toLowerCase();
      const tipoDocumento = String(f.tipoDocumento || 'factura').trim().toLowerCase().replace(/-/g, '_');

      if (tipoDocumento === 'factura_proforma' || tipoDocumento === 'proforma') {
        return false;
      }

      if (['anulado', 'cancelada', 'cancelado'].includes(estado)) {
        return false;
      }

      if (Number(f.totalGeral) <= 0) {
        return false;
      }

      if (mostrarTodos) {
        return true;
      }

      return !['paga', 'pago'].includes(estado);
    });

    // Buscar todos os recibos da empresa
    const todosRecibos = await recibos.listarRecibosPorEmpresa(empresaId);

    // Calcular o total pago por cada factura
    const pagamentosPorFactura = new Map<string, number>();

    todosRecibos.forEach((recibo: any) => {
      // Ignorar recibos anulados
      if (recibo.estado === 'anulado') return;

      if (recibo.pagamentos && Array.isArray(recibo.pagamentos)) {
        recibo.pagamentos.forEach((pag: any) => {
          if (pag.facturaId && pag.valorPago) {
            const atual = pagamentosPorFactura.get(pag.facturaId) || 0;
            pagamentosPorFactura.set(pag.facturaId, atual + Number(pag.valorPago));
          }
        });
      }

      // Compatibilidade retroativa
      if (recibo.itens && Array.isArray(recibo.itens)) {
        recibo.itens.forEach((item: any) => {
          if (item.facturaId && item.valorPago) {
            const atual = pagamentosPorFactura.get(item.facturaId) || 0;
            pagamentosPorFactura.set(item.facturaId, atual + Number(item.valorPago));
          }
        });
      }
    });

    // Devolvemos todas as faturas e seus saldos, o frontend filtra com base na regra de edição
    const facturasDisponiveis = facturasFiltradas.map((f: any) => {
      const totalPago = pagamentosPorFactura.get(f.id) || 0;
      const saldoEmAberto = Number(f.totalGeral) - totalPago;
      return { ...f, saldoEmAberto };
    });

    console.log(`[Recibos] Facturas processadas com saldo: ${facturasDisponiveis.length}`);

    return c.json({ success: true, data: facturasDisponiveis });
  } catch (error) {
    console.error("[API] Erro ao buscar facturas disponíveis:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// NOVO: Verificar e atualizar estados expirados (CotaçÃµes e Facturas)
app.post("/make-server-7249dcd9/verificar-estados-expirados", async (c) => {
  try {
    const { empresaId } = await lerBodyJsonSeguro(c);

    if (!empresaId) {
      return c.json({ success: false, error: "empresaId é obrigatório" }, 400);
    }

    // Validar acesso ao módulo de faturação (necessário para cotaçÃµes e facturas)
    if (empresaId !== "empresa_tonline") {
      const validacao = await subscricoes.validarAcessoModulo(empresaId, "faturacao-vendas");

      if (!validacao.permitido && !validacao.motivo?.includes("não possui subscrição")) {
        console.warn(`[API] âŒ Acesso negado ao verificar estados expirados - Empresa: ${empresaId}`);
        return c.json({
          success: false,
          error: validacao.motivo,
          bloqueado: true,
        }, 403);
      }
    }

    const hoje = new Date().toISOString().split('T')[0]; // YYYY-MM-DD
    let cotacoesAtualizadas = 0;
    let facturasAtualizadas = 0;

    // 1. VERIFICAR COTAÃ‡Ã•ES EXPIRADAS
    const todasCotacoes = await cotacoes.listarCotacoesPorEmpresa(empresaId);
    for (const cotacao of todasCotacoes) {
      // Se está pendente ou aprovada E a data de validade passou
      if ((cotacao.estado === 'pendente' || cotacao.estado === 'aprovada') &&
          cotacao.dataValidade < hoje) {
        await cotacoes.alterarEstadoCotacao(cotacao.id, 'expirada');
        cotacoesAtualizadas++;
      }
    }

    // 2. VERIFICAR FACTURAS VENCIDAS
    const todasFacturas = await facturas.listarFacturasPorEmpresa(empresaId);
    for (const factura of todasFacturas) {
      // Se está pendente E a data de vencimento passou
      if (factura.estado === 'pendente' && factura.dataVencimento < hoje) {
        await facturas.alterarEstadoFactura(factura.id, 'vencida');
        facturasAtualizadas++;
      }
    }

    return c.json({
      success: true,
      data: {
        cotacoesAtualizadas,
        facturasAtualizadas
      }
    });
  } catch (error) {
    // console.error("[API] Erro ao verificar estados expirados:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ========== ROTAS DE RECIBOS ==========

// ðŸŽ¯ NOVO: Prever próximo número de recibo (sem consumir a sequência)
app.get("/make-server-7249dcd9/empresas/:id/recibos/proximo-numero", async (c) => {
  try {
    const empresaId = c.req.param("id");
    const dataReferencia = c.req.query("dataEmissao") || c.req.query("dataReferencia") || undefined;
    const exercicio = await exerciciosEconomicos.validarExercicioAberto(empresaId, dataReferencia, "recibo");
    const numeroGerado = await recibos.preverProximoNumeroRecibo(empresaId, exercicio.ano);

    return c.json({
      success: true,
      data: { numeroDocumento: numeroGerado }
    });
  } catch (error) {
    console.error("[API] Erro ao prever número do recibo:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Listar recibos de uma empresa
app.get("/make-server-7249dcd9/empresas/:id/recibos", async (c) => {
  try {
    const id = c.req.param("id");
    console.log(`[RECIBOS] Listando recibos para empresa: ${id}`);
    const recibosList = await recibos.listarRecibosPorEmpresa(id);
    console.log(`[RECIBOS] Encontrados ${recibosList.length} recibos`);

    return responderListaPaginada(c, recibosList);
  } catch (error) {
    console.error("[API] Erro ao listar recibos:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar recibo por ID
app.get("/make-server-7249dcd9/recibos/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const recibo = await recibos.buscarReciboPorId(id);

    if (!recibo) {
      return c.json({ success: false, error: "Recibo não encontrado" }, 404);
    }

    return c.json({ success: true, data: recibo });
  } catch (error) {
    // console.error("[API] Erro ao buscar recibo:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// âŒ REMOVIDO: Rota de gerar número manualmente
// âœ… O número do recibo é gerado automaticamente no backend ao criar o documento
// Isso garante que números não sejam consumidos sem gravação

// Criar novo recibo
app.post("/make-server-7249dcd9/recibos", async (c) => {
  try {
    const dadosRecibo = await lerBodyJsonSeguro(c);

    // Não escrever clientes, pagamentos ou referências fiscais completas nos logs.

    if (!dadosRecibo.empresaId) {
      return c.json({ success: false, error: "empresaId é obrigatório" }, 400);
    }

    // âœ… FIX #8: Validação mais clara do clienteId
    if (!dadosRecibo.clienteId || String(dadosRecibo.clienteId).trim() === '') {
      console.error('âŒ [API POST /recibos] clienteId inválido:', dadosRecibo.clienteId);
      return c.json({
        success: false,
        error: "Cliente não foi selecionado. Por favor, selecione um cliente antes de gravar o recibo."
      }, 400);
    }

    // âœ… CORRIGIDO: Validar 'pagamentos' em vez de 'itens' (nomenclatura correta)
    const pagamentos = dadosRecibo.pagamentos || dadosRecibo.itens || [];
    console.log('ðŸ” [POST /recibos] Pagamentos extraídos:', pagamentos);
    console.log('ðŸ” [POST /recibos] Quantidade de pagamentos:', pagamentos.length);

    if (pagamentos.length === 0) {
      console.error('âŒ [POST /recibos] VALIDAÃ‡ÃƒO FALHOU - pagamentos.length === 0');
      return c.json({ success: false, error: "O recibo deve ter pelo menos um pagamento (factura ou adiantamento)" }, 400);
    }

    // Garantir que o campo pagamentos está presente no payload
    dadosRecibo.pagamentos = pagamentos;
    console.log('âœ… [POST /recibos] Validação de pagamentos passou! Continuando...');

    // âœ… NOVO: Capturar dados do usuário que está criando o documento
    console.log('ðŸ” [POST /recibos] Tentando capturar dados do usuário...');
    const { getUserFromRequest } = await import('./permission-middleware.tsx');
    const usuario = await getUserFromRequest(c);

    console.log('ðŸ” [POST /recibos] Usuário capturado:', usuario);

    if (usuario) {
      dadosRecibo.criadoPor = usuario.nome;
      dadosRecibo.criadoPorId = usuario.id;
      dadosRecibo.criadoPorNome = usuario.nome;
      dadosRecibo.criadoPorEmail = usuario.email;
      dadosRecibo.usuarioAuditoriaId = usuario.id;
      dadosRecibo.usuarioAuditoriaNome = usuario.nome;
      dadosRecibo.usuarioAuditoriaEmail = usuario.email;
      console.log('âœ… [POST /recibos] Dados do usuário adicionados:', {
        criadoPor: usuario.nome,
        criadoPorId: usuario.id
      });
    } else {
      console.warn('âš ï¸ [POST /recibos] Nenhum usuário encontrado - documento será criado sem criadoPor');
    }

    await preencherUsuarioDocumento(c, dadosRecibo, 'criar');

    const prevalidacaoContabilidadeRecibo = await contabilizarReciboOperacional(
      {
        ...dadosRecibo,
        id: dadosRecibo.id || `prevalidacao_recibo_${Date.now()}`,
        numeroDocumento: dadosRecibo.numeroDocumento || 'Recibo em preparacao',
      },
      { previsualizar: true },
    );
    const erroContabilidadeRecibo = respostaErroContabilidadeObrigatoria(prevalidacaoContabilidadeRecibo, 'recibo');
    if (erroContabilidadeRecibo) {
      return c.json(erroContabilidadeRecibo, 400);
    }

    const novoRecibo = await recibos.criarRecibo(dadosRecibo);

    const resultadoContabilidadeRecibo = await contabilizarReciboOperacional(novoRecibo);
    const erroContabilidadeReciboCriado = respostaErroContabilidadeObrigatoria(resultadoContabilidadeRecibo, 'recibo');
    if (erroContabilidadeReciboCriado) {
      await recibos.excluirRecibo(novoRecibo.id, {
        motivo: 'Rollback interno: falha na contabilizacao obrigatoria.',
        origem: 'rollback-contabilidade',
      }).catch(() => null);
      return c.json({
        ...erroContabilidadeReciboCriado,
        error: `${erroContabilidadeReciboCriado.error}. O recibo nao foi emitido e a numeracao foi libertada.`,
      }, 500);
    }

    console.log('âœ… [POST /recibos] Recibo criado:', {
      id: novoRecibo.id,
      criadoPor: novoRecibo.criadoPor,
      criadoPorId: novoRecibo.criadoPorId
    });

    // Se vier um campo legado facturaId, recalcular pelo saldo real em recibos.
    if (dadosRecibo.facturaId) {
      try {
        await facturas.recalcularEstadoFactura(dadosRecibo.facturaId);
      } catch (error) {
        resultadoConversaoCotacao = { success: false, error: error?.message || String(error) };
        // console.error(`[API] âš ï¸ Erro ao recalcular estado da factura:`, error);
        // Não falhar a criação do recibo por causa disso
      }
    }

    return c.json({ success: true, data: novoRecibo });
  } catch (error) {
    // console.error("[API] Erro ao criar recibo:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Atualizar recibo
app.get("/make-server-7249dcd9/recibos/:id/pode-editar", async (c) => {
  try {
    const resultado = await recibos.podeAlterarRecibo(c.req.param("id"), "editado");
    return c.json({ success: true, data: resultado });
  } catch (error) {
    return c.json({ success: false, error: error instanceof Error ? error.message : String(error) }, 500);
  }
});

app.get("/make-server-7249dcd9/recibos/:id/pode-eliminar", async (c) => {
  try {
    const resultado = await recibos.podeEliminarRecibo(c.req.param("id"));
    return c.json({ success: true, data: resultado });
  } catch (error) {
    return c.json({ success: false, error: error instanceof Error ? error.message : String(error) }, 500);
  }
});

app.get("/make-server-7249dcd9/recibos/:id/pode-anular", async (c) => {
  try {
    const resultado = await recibos.podeAnularRecibo(c.req.param("id"));
    return c.json({ success: true, data: resultado });
  } catch (error) {
    return c.json({ success: false, error: error instanceof Error ? error.message : String(error) }, 500);
  }
});

app.put("/make-server-7249dcd9/recibos/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const dadosRecibo = await lerBodyJsonSeguro(c);

    console.log('ðŸ” [PUT /recibos] Iniciando atualização de recibo');

    const reciboExistente = await recibos.buscarReciboPorId(id);
    if (!reciboExistente) {
      return c.json({ success: false, error: 'Recibo não encontrado' }, 404);
    }

    const lancamentoRecibo = await buscarLancamentoDocumentoContabil(reciboExistente.empresaId, id, 'recibo');
    if (lancamentoRecibo && lancamentoRecibo.estado === 'lancado') {
      return c.json({
        success: false,
        error: 'Este recibo ja tem lancamento contabil definitivo. Estorne o lancamento antes de alterar o recibo.',
      }, 400);
    }

    // âœ… NOVO: Capturar dados do usuário que está editando o documento
    const { getUserFromRequest } = await import('./permission-middleware.tsx');
    const usuario = await getUserFromRequest(c);

    console.log('ðŸ” [PUT /recibos] Usuário capturado:', usuario);

    if (usuario) {
      dadosRecibo.editadoPor = usuario.nome;
      dadosRecibo.editadoPorId = usuario.id;
      console.log('âœ… [PUT /recibos] Dados do usuário adicionados:', {
        editadoPor: usuario.nome,
        editadoPorId: usuario.id
      });
    } else {
      console.warn('âš ï¸ [PUT /recibos] Nenhum usuário encontrado - documento será atualizado sem editadoPor');
    }

    const reciboParaValidar = {
      ...reciboExistente,
      ...dadosRecibo,
      id,
      empresaId: reciboExistente.empresaId,
      clienteId: reciboExistente.clienteId,
      cliente: reciboExistente.cliente,
    };
    const prevalidacaoContabilidadeReciboAtualizado = await contabilizarReciboOperacional(
      reciboParaValidar,
      { previsualizar: true },
    );
    const erroContabilidadeReciboAtualizado = respostaErroContabilidadeObrigatoria(
      prevalidacaoContabilidadeReciboAtualizado,
      'recibo',
    );
    if (erroContabilidadeReciboAtualizado) {
      return c.json(erroContabilidadeReciboAtualizado, 400);
    }

    const reciboAtualizado = await recibos.atualizarRecibo(id, dadosRecibo);

    if (lancamentoRecibo && (lancamentoRecibo.estado || 'rascunho') === 'rascunho') {
      const resultadoContabilidadeRecibo = await contabilizarReciboOperacional(reciboAtualizado);
      const erroSincronizacaoRecibo = respostaErroContabilidadeObrigatoria(resultadoContabilidadeRecibo, 'recibo');
      if (erroSincronizacaoRecibo) {
        return c.json(erroSincronizacaoRecibo, 400);
      }
    }

    console.log('âœ… [PUT /recibos] Recibo atualizado:', {
      id: reciboAtualizado.id,
      editadoPor: reciboAtualizado.editadoPor,
      editadoPorId: reciboAtualizado.editadoPorId
    });

    return c.json({ success: true, data: reciboAtualizado });
  } catch (error) {
    console.error("[API] Erro ao atualizar recibo:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Eliminar recibo - BLOQUEADO (Requisito Financas/AT: nenhum documento
// fiscal pode ser eliminado). excluirRecibo() recusa sempre, ver
// recibos.tsx.
app.delete("/make-server-7249dcd9/recibos/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const body = await lerBodyJsonSeguro(c);
    await preencherUsuarioDocumento(c, body, 'editar');

    const reciboEliminado = await recibos.excluirRecibo(id, {
      motivo: body.motivo,
      usuarioId: body.usuarioAuditoriaId,
      usuarioNome: body.usuarioAuditoriaNome,
      usuarioEmail: body.usuarioAuditoriaEmail,
    });

    return c.json({
      success: true,
      data: reciboEliminado,
      message: "Recibo eliminado e número libertado com sucesso",
    });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 400);
  }
});

// Anular recibo - substitui a eliminacao. Preserva o documento, o numero
// e o historico.
app.post("/make-server-7249dcd9/recibos/:id/anular", async (c) => {
  try {
    const body = await lerBodyJsonSeguro(c, {});
    const reciboAnulado = await recibos.anularRecibo(c.req.param("id"), body?.motivo);
    return c.json({ success: true, data: reciboAnulado, message: "Recibo anulado com sucesso" });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar recibos por cliente
app.get("/make-server-7249dcd9/empresas/:empresaId/clientes/:clienteId/recibos", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const clienteId = c.req.param("clienteId");

    const recibosList = await recibos.buscarRecibosPorCliente(empresaId, clienteId);

    return c.json({ success: true, data: recibosList });
  } catch (error) {
    // console.error("[API] Erro ao buscar recibos do cliente:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar TODOS os adiantamentos disponíveis de uma empresa
app.get("/make-server-7249dcd9/empresas/:empresaId/adiantamentos-disponiveis", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");

    // Buscar todos os adiantamentos da empresa
    const resultAdiantamentos = await adiantamentos.getAdiantamentosByEmpresa(empresaId);
    if (!resultAdiantamentos.success) {
      return c.json({ success: false, error: resultAdiantamentos.error }, 500);
    }

    const todosAdiantamentos = resultAdiantamentos.data || [];

    // Buscar todos os recibos da empresa
    const todosRecibos = await recibos.listarRecibosPorEmpresa(empresaId);

    // Calcular o total usado de cada adiantamento
    const usoPorAdiantamento = new Map<string, number>();

    todosRecibos.forEach((recibo: any) => {
      if (recibo.estado === 'anulado') return;

      if (recibo.itens && Array.isArray(recibo.itens)) {
        recibo.itens.forEach((item: any) => {
          if (item.adiantamentoId && item.valorPago) {
            const atual = usoPorAdiantamento.get(item.adiantamentoId) || 0;
            usoPorAdiantamento.set(item.adiantamentoId, atual + Number(item.valorPago));
          }
        });
      }
      if (recibo.pagamentos && Array.isArray(recibo.pagamentos)) {
        recibo.pagamentos.forEach((pag: any) => {
          if (pag.adiantamentoId && pag.valorPago) {
            const atual = usoPorAdiantamento.get(pag.adiantamentoId) || 0;
            usoPorAdiantamento.set(pag.adiantamentoId, atual + Number(pag.valorPago));
          }
        });
      }
    });

    // Enviar todos os adiantamentos e deixar o frontend filtrar com base na edição
    const adiantamentosDisponiveis = todosAdiantamentos.map((a: any) => {
      const totalUsado = usoPorAdiantamento.get(a.id) || 0;
      const valorBase = Number(a.valor ?? a.totalGeral ?? 0);
      const saldoEmAberto = Math.max(0, valorBase - totalUsado);
      return { ...a, totalGeral: valorBase, saldoEmAberto };
    });

    return c.json({ success: true, data: adiantamentosDisponiveis });
  } catch (error) {
    console.error("[API] Erro ao buscar todos adiantamentos disponíveis:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar adiantamentos disponíveis (não usados em recibos) de um cliente
app.get("/make-server-7249dcd9/empresas/:empresaId/clientes/:clienteId/adiantamentos-disponiveis", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const clienteId = c.req.param("clienteId");

    // Buscar todos os adiantamentos da empresa
    const resultAdiantamentos = await adiantamentos.getAdiantamentosByEmpresa(empresaId);
    if (!resultAdiantamentos.success) {
      return c.json({ success: false, error: resultAdiantamentos.error }, 500);
    }

    // Filtrar adiantamentos do cliente
    const adiantamentosCliente = (resultAdiantamentos.data || []).filter(
      (a: any) => a.clienteId === clienteId
    );

    // Buscar todos os recibos da empresa
    const todosRecibos = await recibos.listarRecibosPorEmpresa(empresaId);

    // Calcular o total usado de cada adiantamento
    const usoPorAdiantamento = new Map<string, number>();

    todosRecibos.forEach((recibo: any) => {
      if (recibo.estado === 'anulado') return;

      if (recibo.itens && Array.isArray(recibo.itens)) {
        recibo.itens.forEach((item: any) => {
          if (item.adiantamentoId && item.valorPago) {
            const atual = usoPorAdiantamento.get(item.adiantamentoId) || 0;
            usoPorAdiantamento.set(item.adiantamentoId, atual + Number(item.valorPago));
          }
        });
      }
      if (recibo.pagamentos && Array.isArray(recibo.pagamentos)) {
        recibo.pagamentos.forEach((pag: any) => {
          if (pag.adiantamentoId && pag.valorPago) {
            const atual = usoPorAdiantamento.get(pag.adiantamentoId) || 0;
            usoPorAdiantamento.set(pag.adiantamentoId, atual + Number(pag.valorPago));
          }
        });
      }
    });

    // Enviar os adiantamentos com seus saldos e deixar o frontend tratar para permitir exibir em modo edição
    const adiantamentosDisponiveis = adiantamentosCliente.map((a: any) => {
      const totalUsado = usoPorAdiantamento.get(a.id) || 0;
      const valorBase = Number(a.valor ?? a.totalGeral ?? 0);
      const saldoEmAberto = Math.max(0, valorBase - totalUsado);
      return { ...a, totalGeral: valorBase, saldoEmAberto };
    });

    return c.json({ success: true, data: adiantamentosDisponiveis });
  } catch (error) {
    console.error("[API] Erro ao buscar adiantamentos disponíveis:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ========== ROTAS DE NOTAS DE CRÃ‰DITO E DÃ‰BITO ==========

app.get("/make-server-7249dcd9/empresas/:id/notas/proximo-numero", async (c) => {
  try {
    const empresaId = c.req.param("id");
    const tipo = (c.req.query("tipo") || "credito") as "credito" | "debito";

    if (!["credito", "debito"].includes(tipo)) {
      return c.json({ success: false, error: "tipo deve ser 'credito' ou 'debito'" }, 400);
    }

    const dataReferencia = c.req.query("dataEmissao") || c.req.query("dataReferencia") || undefined;
    const exercicio = await exerciciosEconomicos.validarExercicioAberto(empresaId, dataReferencia, `nota de ${tipo}`);
    const numeroDocumento = await notas.preverProximoNumeroNota(empresaId, tipo, exercicio.ano);
    return c.json({ success: true, data: { numeroDocumento } });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Listar notas de uma empresa
app.get("/make-server-7249dcd9/empresas/:id/notas", async (c) => {
  try {
    const empresaId = c.req.param("id");
    const result = await notas.getNotasByEmpresa(empresaId);

    if (!result.success) {
      return c.json({ success: false, error: result.error }, 500);
    }

    return responderListaPaginada(c, Array.isArray(result.data) ? result.data : []);
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar nota por ID
app.get("/make-server-7249dcd9/notas/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const result = await notas.getNotaById(id);

    if (!result.success) {
      return c.json({ success: false, error: result.error }, 404);
    }

    return c.json({ success: true, data: result.data });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Criar nova nota
app.post("/make-server-7249dcd9/notas", async (c) => {
  try {
    const dadosNota = await lerBodyJsonSeguro(c);
    await preencherUsuarioDocumento(c, dadosNota, 'criar');

    if (!dadosNota.empresaId) {
      return c.json({ success: false, error: "empresaId é obrigatório" }, 400);
    }

    if (!dadosNota.tipo || !['credito', 'debito'].includes(dadosNota.tipo)) {
      return c.json({ success: false, error: "tipo deve ser 'credito' ou 'debito'" }, 400);
    }

    if (!dadosNota.clienteId) {
      return c.json({ success: false, error: "clienteId é obrigatório" }, 400);
    }

    if (!dadosNota.itens || dadosNota.itens.length === 0) {
      return c.json({ success: false, error: "A nota deve ter pelo menos um item" }, 400);
    }

    const tipoContabilNota = dadosNota.tipo === 'credito' ? 'nota_credito' : 'nota_debito';
    // ✅ Ver nota em /facturas-recibo — a pre-validacao tem de usar os totais
    // calculados pelo servidor, nao os que o formulario enviou.
    const dadosNotaPrevalidados = await aplicarTotaisFiscais(dadosNota);
    const prevalidacaoNota = await contabilizarDocumentoFiscalOperacional(
      {
        ...dadosNotaPrevalidados,
        id: dadosNota.id || `prevalidacao_nota_${Date.now()}`,
        numeroDocumento: dadosNota.numeroDocumento || 'Nota em preparação',
      },
      tipoContabilNota,
      { previsualizar: true },
    );
    const erroPrevalidacaoNota = respostaErroContabilidadeObrigatoria(prevalidacaoNota, 'nota');
    if (erroPrevalidacaoNota) return c.json(erroPrevalidacaoNota, 400);

    const result = await notas.createNota(dadosNota);

    if (!result.success) {
      return c.json({ success: false, error: result.error }, 500);
    }

    const resultadoContabilidadeNota = await contabilizarDocumentoFiscalOperacional(result.data, tipoContabilNota);
    const erroContabilidadeNota = respostaErroContabilidadeObrigatoria(resultadoContabilidadeNota, 'nota');
    if (erroContabilidadeNota) {
      await notas.deleteNota(result.data.id, {
        motivo: 'Rollback interno: falha na contabilizacao obrigatoria.',
        origem: 'rollback-contabilidade',
      }).catch(() => null);
      return c.json({
        ...erroContabilidadeNota,
        error: `${erroContabilidadeNota.error}. A nota nao foi emitida e a numeracao foi libertada.`,
      }, 500);
    }

    // Nota de credito repoe stock (devolucao_cliente) — falta reverter o CMV
    // correspondente (debita Estoque/credita CMV), tal como a Factura/VD
    // contabilizam a saida. Sem isto o estorno de receita acontecia mas o
    // custo da venda original ficava por reverter.
    const resultadoCMVNota = await contabilizarMovimentosStockDocumento(
      result.data.empresaId,
      result.data.numeroDocumento,
      'Nota Crédito',
      { criadoPor: dadosNota.criadoPor || dadosNota.usuarioId },
    );
    const notaComContabilidade = await anexarResultadoContabilidade(result.data, {
      nota: resultadoContabilidadeNota,
      cmvmc: resultadoCMVNota,
    });

    return responderDocumentoIntegrado(c, notaComContabilidade);
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Atualizar nota
app.get("/make-server-7249dcd9/notas/:id/pode-editar", async (c) => {
  try {
    const resultado = await notas.podeAlterarNota(c.req.param("id"), "editada");
    return c.json({ success: true, data: resultado });
  } catch (error) {
    return c.json({ success: false, error: error instanceof Error ? error.message : String(error) }, 500);
  }
});

app.get("/make-server-7249dcd9/notas/:id/pode-eliminar", async (c) => {
  try {
    const resultado = await notas.podeEliminarNota(c.req.param("id"));
    return c.json({ success: true, data: resultado });
  } catch (error) {
    return c.json({ success: false, error: error instanceof Error ? error.message : String(error) }, 500);
  }
});

app.get("/make-server-7249dcd9/notas/:id/pode-anular", async (c) => {
  try {
    const resultado = await notas.podeAnularNota(c.req.param("id"));
    return c.json({ success: true, data: resultado });
  } catch (error) {
    return c.json({ success: false, error: error instanceof Error ? error.message : String(error) }, 500);
  }
});

app.put("/make-server-7249dcd9/notas/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const dadosNota = await lerBodyJsonSeguro(c);

    const result = await notas.updateNota(id, dadosNota);

    if (!result.success) {
      return c.json({ success: false, error: result.error }, 500);
    }

    return c.json({ success: true, data: result.data });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Eliminar nota - BLOQUEADO (Requisito Financas/AT: nenhum documento
// fiscal pode ser eliminado). deleteNota() recusa sempre, ver notas.tsx.
app.delete("/make-server-7249dcd9/notas/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const body = await lerBodyJsonSeguro(c);
    await preencherUsuarioDocumento(c, body, 'editar');

    const result = await notas.deleteNota(id, {
      motivo: body.motivo,
      usuarioId: body.usuarioAuditoriaId,
      usuarioNome: body.usuarioAuditoriaNome,
      usuarioEmail: body.usuarioAuditoriaEmail,
    });
    if (!result.success) {
      return c.json({ success: false, error: result.error }, 400);
    }
    return c.json({
      success: true,
      data: result.data,
      message: "Nota eliminada e número libertado com sucesso",
    });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Anular nota - substitui a eliminacao. Preserva o documento, o numero e
// o historico.
app.post("/make-server-7249dcd9/notas/:id/anular", async (c) => {
  try {
    const body = await lerBodyJsonSeguro(c, {});
    const result = await notas.anularNota(c.req.param("id"), body?.motivo);
    if (!result.success) {
      return c.json({ success: false, error: result.error }, 500);
    }
    return c.json({ success: true, data: result.data, message: "Nota anulada com sucesso" });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ========== ROTAS DE MOVIMENTOS DE STOCK ==========

// ========== ROTAS DE DOCUMENTOS OPERACIONAIS DE STOCK ==========

app.get("/make-server-7249dcd9/documentos-stock/tipos", async (c) => {
  try {
    const tipos = Object.entries(documentosStock.tiposDocumentoStock).map(([value, config]) => ({
      value,
      label: config.label,
      prefixo: config.prefixo,
      movimentoTipo: config.movimentoTipo,
      motivo: config.motivo,
      documentoTipoMovimento: config.documentoTipoMovimento,
    }));

    return c.json({ success: true, data: tipos });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.get("/make-server-7249dcd9/documentos-stock/:empresaId", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const tipo = c.req.query("tipo") as documentosStock.TipoDocumentoStock | undefined;
    const estado = c.req.query("estado") as documentosStock.EstadoDocumentoStock | undefined;
    const dataInicio = c.req.query("dataInicio");
    const dataFim = c.req.query("dataFim");
    const termo = c.req.query("termo");

    const documentos = await documentosStock.listarDocumentosStock(empresaId, {
      tipo,
      estado,
      dataInicio,
      dataFim,
      termo,
    });

    return c.json({ success: true, data: documentos });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.get("/make-server-7249dcd9/documentos-stock/documento/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const documento = await documentosStock.buscarDocumentoStockPorId(id);

    if (!documento) {
      return c.json({ success: false, error: "Documento nao encontrado" }, 404);
    }

    const escopo = await verificarEscopoEmpresaRequest(c, documento.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }

    return c.json({ success: true, data: documento });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.post("/make-server-7249dcd9/documentos-stock", async (c) => {
  try {
    const dados = await lerBodyJsonSeguro(c);
    const escopo = await verificarEscopoEmpresaRequest(c, dados.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const resultado = await documentosStock.criarDocumentoStock(dados);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    await registrarAuditoriaDocumentoStock(c, 'criar', resultado.data, {
      body: dados,
      detalhes: `${(await obterUsuarioAuditoriaRequest(c, dados)).nome || 'Sistema'} criou rascunho de ${labelDocumentoStock(resultado.data?.tipo)} com ${resultado.data?.totalLinhas || 0} linha(s). ${textoLinhasDocumentoStock(resultado.data?.linhas || [], 8)}`,
    });

    return c.json(resultado, 201);
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.patch("/make-server-7249dcd9/documentos-stock/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const dados = await lerBodyJsonSeguro(c);
    const documentoAntes = await documentosStock.buscarDocumentoStockPorId(id);
    if (!documentoAntes) {
      return c.json({ success: false, error: "Documento nao encontrado" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, documentoAntes.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const resultado = await documentosStock.atualizarDocumentoStock(id, dados);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    await registrarAuditoriaDocumentoStock(c, 'editar', resultado.data, {
      body: dados,
      antes: documentoAntes,
    });

    return c.json(resultado);
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.post("/make-server-7249dcd9/documentos-stock/:id/emitir", async (c) => {
  try {
    const id = c.req.param("id");
    const dados = await lerBodyJsonSeguro(c);
    const documentoAntes = await documentosStock.buscarDocumentoStockPorId(id);
    if (!documentoAntes) {
      return c.json({ success: false, error: "Documento nao encontrado" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, documentoAntes.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const resultado = await documentosStock.emitirDocumentoStock(id, dados);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    await registrarAuditoriaDocumentoStock(c, 'emitir', resultado.data, {
      body: dados,
      antes: documentoAntes,
      detalhes: `${(await obterUsuarioAuditoriaRequest(c, { ...(dados || {}), empresaId: resultado.data?.empresaId })).nome || 'Sistema'} emitiu ${labelDocumentoStock(resultado.data?.tipo)} ${resultado.data?.numero}. Foram gerados ${resultado.data?.movimentosIds?.length || 0} movimento(s) de stock. ${textoLinhasDocumentoStock(resultado.data?.linhas || [], 10)}`,
    });

    return c.json(resultado);
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.post("/make-server-7249dcd9/documentos-stock/:id/anular", async (c) => {
  try {
    const id = c.req.param("id");
    const dados = await lerBodyJsonSeguro(c);
    const documentoAntes = await documentosStock.buscarDocumentoStockPorId(id);
    if (!documentoAntes) {
      return c.json({ success: false, error: "Documento nao encontrado" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, documentoAntes.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const resultado = await documentosStock.anularDocumentoStock(id, dados);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    await registrarAuditoriaDocumentoStock(c, 'anular', resultado.data, {
      body: dados,
      antes: documentoAntes,
      nivel: 'aviso',
      detalhes: `${(await obterUsuarioAuditoriaRequest(c, { ...(dados || {}), empresaId: resultado.data?.empresaId })).nome || 'Sistema'} anulou ${labelDocumentoStock(resultado.data?.tipo)} ${resultado.data?.numero}. Motivo: ${resultado.data?.motivoAnulacao || 'nao informado'}. Reversoes geradas: ${resultado.data?.movimentosReversaoIds?.length || 0}.`,
    });

    return c.json(resultado);
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.delete("/make-server-7249dcd9/documentos-stock/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const documentoAntes = await documentosStock.buscarDocumentoStockPorId(id);
    if (!documentoAntes) {
      return c.json({ success: false, error: "Documento nao encontrado" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, documentoAntes.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const resultado = await documentosStock.eliminarDocumentoStock(id);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    await registrarAuditoriaDocumentoStock(c, 'deletar', documentoAntes, {
      body: { id, empresaId: documentoAntes?.empresaId },
      nivel: 'aviso',
    });

    return c.json(resultado);
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Listar movimentos de stock
app.get("/make-server-7249dcd9/movimentos-stock/:empresaId", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    console.log(`[API] ðŸ”µ Listando movimentos para empresa: ${empresaId}`);

    const tipo = c.req.query("tipo");
    const artigoId = c.req.query("artigoId");
    const dataInicio = c.req.query("dataInicio");
    const dataFim = c.req.query("dataFim");
    const motivo = c.req.query("motivo");
    const documentoTipo = c.req.query("documentoTipo");
    const documentoNumero = c.req.query("documentoNumero");
    const documentoId = c.req.query("documentoId");

    const filtros: any = {};
    if (tipo) filtros.tipo = tipo;
    if (artigoId) filtros.artigoId = artigoId;
    if (dataInicio) filtros.dataInicio = dataInicio;
    if (dataFim) filtros.dataFim = dataFim;
    if (motivo) filtros.motivo = motivo;
    if (documentoTipo) filtros.documentoTipo = documentoTipo;
    if (documentoNumero) filtros.documentoNumero = documentoNumero;
    if (documentoId) filtros.documentoId = documentoId;

    console.log(`[API] ðŸ”µ Filtros aplicados:`, filtros);

    const movimentos = await movimentosStock.listarMovimentos(empresaId, filtros);

    console.log(`[API] âœ… Movimentos encontrados: ${movimentos.length}`);
    if (movimentos.length > 0) {
      console.log(`[API] ðŸ” Primeiro movimento (debug armazém):`, {
        id: movimentos[0].id,
        artigoCodigo: movimentos[0].artigoCodigo,
        armazemId: movimentos[0].armazemId,
        armazemCodigo: movimentos[0].armazemCodigo,
        armazemNome: movimentos[0].armazemNome,
      });
    }

    return c.json({ success: true, data: movimentos });
  } catch (error) {
    console.error("[API] âŒ Erro ao listar movimentos:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar movimento por ID
app.get("/make-server-7249dcd9/movimentos-stock/movimento/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const movimento = await movimentosStock.buscarMovimentoPorId(id);

    if (!movimento) {
      return c.json({ success: false, error: "Movimento não encontrado" }, 404);
    }

    const escopo = await verificarEscopoEmpresaRequest(c, movimento.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }

    return c.json({ success: true, data: movimento });
  } catch (error) {
    // console.error("[API] Erro ao buscar movimento:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Criar novo movimento
app.post("/make-server-7249dcd9/movimentos-stock", async (c) => {
  try {
    const dados = await lerBodyJsonSeguro(c);
    const escopo = await verificarEscopoEmpresaRequest(c, dados.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const resultado = await movimentosStock.criarMovimento(dados);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    await registrarAuditoriaMovimentoStock(c, 'criar', resultado.data, { body: dados });

    const resultadoContabilidadeMovimento = await contabilizarMovimentoStockOperacional(resultado.data, {
      criadoPor: dados.responsavel || dados.criadoPor,
    });
    if (resultado.data) {
      resultado.data = await anexarResultadoContabilidade(resultado.data, { stock: resultadoContabilidadeMovimento });
    }

    return c.json(resultado, 201);
  } catch (error) {
    // console.error("[API] Erro ao criar movimento:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Deletar movimento
app.delete("/make-server-7249dcd9/movimentos-stock/:id", requirePermission("stock.movimento.deletar"), async (c) => {
  try {
    const id = c.req.param("id");
    const movimentoAntes = await movimentosStock.buscarMovimentoPorId(id);
    if (!movimentoAntes) {
      return c.json({ success: false, error: "Movimento não encontrado" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, movimentoAntes.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const resultado = await movimentosStock.deletarMovimento(id);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    await registrarAuditoriaMovimentoStock(c, 'deletar', movimentoAntes, {
      body: { id, empresaId: movimentoAntes?.empresaId },
      nivel: 'aviso',
      detalhes: `${(await obterUsuarioAuditoriaRequest(c, { empresaId: movimentoAntes?.empresaId })).nome || 'Sistema'} eliminou o movimento de stock ${movimentoAntes?.id} do artigo ${nomeArtigoAuditoria(movimentoAntes)}. O stock foi revertido pela rotina de eliminacao do movimento.`,
    });

    return c.json(resultado);
  } catch (error) {
    // console.error("[API] Erro ao deletar movimento:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});


app.post("/make-server-7249dcd9/movimentos-stock/:id/reverter", async (c) => {
  try {
    const id = c.req.param("id");
    const movimentoParaReverter = await movimentosStock.buscarMovimentoPorId(id);
    if (!movimentoParaReverter) {
      return c.json({ success: false, error: "Movimento não encontrado" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, movimentoParaReverter.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const dados = await lerBodyJsonSeguro(c);
    const resultado = await movimentosStock.reverterMovimentoOperacional(id, dados);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    await registrarAuditoriaMovimentoStock(c, 'reverter', resultado.data?.movimentoReversao, {
      body: dados,
      antes: resultado.data?.movimentoOriginal,
      detalhes: `${(await obterUsuarioAuditoriaRequest(c, { ...dados, empresaId: resultado.data?.movimentoOriginal?.empresaId })).nome || 'Sistema'} reverteu o movimento ${id} do artigo ${nomeArtigoAuditoria(resultado.data?.movimentoOriginal)}. Foi criado movimento de reposicao ${resultado.data?.movimentoReversao?.id} com quantidade ${quantidadeAuditoria(resultado.data?.movimentoReversao?.quantidade)}.`,
    });

    return c.json(resultado);
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});
// ðŸ—‘ï¸ APAGAR TODOS OS MOVIMENTOS SEM REVERTER STOCK
app.delete("/make-server-7249dcd9/movimentos-stock/apagar-todos-sem-reverter/:empresaId", requirePermission("stock.movimento.deletar"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    console.log(`[API] ðŸ—‘ï¸ Solicitação para apagar TODOS os movimentos de ${empresaId} SEM REVERTER STOCK`);

    const resultado = await movimentosStock.apagarTodosSemReverterStock(empresaId);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    return c.json({
      success: true,
      eliminados: resultado.eliminados,
      message: `${resultado.eliminados} movimentos apagados com sucesso (stock NÃƒO revertido)`
    });
  } catch (error) {
    console.error("[API] âŒ Erro ao apagar movimentos:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Obter resumo de movimentos por artigo
app.get("/make-server-7249dcd9/movimentos-stock/resumo/:empresaId/:artigoId", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const artigoId = c.req.param("artigoId");
    const resumo = await movimentosStock.obterResumoMovimentos(empresaId, artigoId);

    return c.json({ success: true, data: resumo });
  } catch (error) {
    // console.error("[API] Erro ao obter resumo de movimentos:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// DIAGNÃ“STICO: Verificar e recriar movimentos baseado nos artigos existentes
app.post("/make-server-7249dcd9/movimentos-stock/diagnosticar/:empresaId", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    console.log(`[DIAGNOSTICO] Iniciando diagnostico para empresa: ${empresaId}`);

    const todosMovimentos = await kv.getByPrefix("movimento_stock:");
    console.log(`[DIAGNOSTICO] Total de movimentos no banco: ${todosMovimentos.length}`);

    const movimentosDaEmpresa = todosMovimentos.filter((m: any) => m.empresaId === empresaId);
    console.log(`[DIAGNOSTICO] Movimentos da empresa: ${movimentosDaEmpresa.length}`);

    const todosArtigos = await kv.getByPrefix("artigo:");
    const artigosDaEmpresa = todosArtigos.filter((a: any) => a.empresaId === empresaId && a.tipo === 'produto');
    console.log(`[DIAGNOSTICO] Artigos da empresa: ${artigosDaEmpresa.length}`);

    // Tentar diferentes formatos de chave
    console.log(`[DIAGNOSTICO] Tentando buscar stocks com prefixo: stockarmazem_ (filtrando empresa ${empresaId})`);
    let todosStocks = (await kv.getByPrefix("stockarmazem_")).filter((stock: any) => stock.empresaId === empresaId);
    console.log(`[DIAGNOSTICO] Stocks com prefixo 1: ${todosStocks.length}`);

    if (todosStocks.length === 0) {
      console.log(`[DIAGNOSTICO] Tentando buscar TODOS os stocks com prefixo: stock_`);
      const todosStocksGlobal = await kv.getByPrefix("stock_");
      console.log(`[DIAGNOSTICO] Total de stocks GLOBAIS: ${todosStocksGlobal.length}`);
      console.log(`[DIAGNOSTICO] Primeiros 3 stocks GLOBAIS:`, todosStocksGlobal.slice(0, 3));

      // Filtrar manualmente por empresaId
      todosStocks = todosStocksGlobal.filter((s: any) => s.empresaId === empresaId);
      console.log(`[DIAGNOSTICO] Stocks filtrados para empresa ${empresaId}: ${todosStocks.length}`);
    }

    console.log(`[DIAGNOSTICO] Stocks-armazem FINAIS da empresa: ${todosStocks.length}`);

    if (todosStocks.length > 0) {
      console.log(`[DIAGNOSTICO] ESTRUTURA DO PRIMEIRO STOCK:`, JSON.stringify(todosStocks[0], null, 2));
    }

    // Buscar armazéns para ter os códigos
    const todosArmazens = await kv.getByPrefix("armazem:");
    const armazensDaEmpresa = todosArmazens.filter((a: any) => a.empresaId === empresaId);
    console.log(`[DIAGNOSTICO] Armazéns da empresa: ${armazensDaEmpresa.length}`);

    const relatorio = [];
    let movimentosCriados = 0;

    for (const stock of todosStocks) {
      const stockData = stock as any;

      // Buscar dados completos do artigo e armazém
      const artigo = artigosDaEmpresa.find((a: any) => a.id === stockData.artigoId);
      const armazem = armazensDaEmpresa.find((a: any) => a.id === stockData.armazemId);

      // ðŸŽ¯ CRÃTICO: Buscar quantidade ORIGINAL do artigo, não do stock-armazém
      // Ordem de prioridade: artigo.estoqueAtual > stockData.quantidadeDisponivel > 0
      const quantidadeOriginalArtigo = artigo?.estoqueAtual ?? 0;
      const quantidadeStockArmazem = stockData.quantidadeDisponivel ?? 0;
      const quantidadeFinal = quantidadeOriginalArtigo > 0 ? quantidadeOriginalArtigo : quantidadeStockArmazem;

      console.log(`[DIAGNOSTICO] Processando stock:`, {
        id: stockData.id,
        artigoId: stockData.artigoId,
        artigoCodigo: artigo?.codigo,
        armazemId: stockData.armazemId,
        armazemCodigo: armazem?.codigo,
        quantidadeOriginalArtigo: quantidadeOriginalArtigo,
        quantidadeStockArmazem: quantidadeStockArmazem,
        quantidadeFinal: quantidadeFinal,
      });

      const movimentoExistente = movimentosDaEmpresa.find((m: any) =>
        m.artigoId === stockData.artigoId &&
        m.armazemId === stockData.armazemId &&
        m.tipo === 'entrada'
      );

      const info: any = {
        artigoId: stockData.artigoId,
        artigoCodigo: artigo?.codigo || 'N/A',
        artigoDescricao: artigo?.descricao || artigo?.nome || 'N/A',
        armazemId: stockData.armazemId,
        armazemCodigo: armazem?.codigo || 'N/A',
        quantidadeOriginalArtigo: quantidadeOriginalArtigo,
        quantidadeStockArmazem: quantidadeStockArmazem,
        quantidadeFinal: quantidadeFinal,
        movimentoExiste: !!movimentoExistente,
      };

      relatorio.push(info);

      console.log(`[DIAGNOSTICO] Verificando se deve criar movimento:`, {
        movimentoExiste: !!movimentoExistente,
        quantidadeFinal: quantidadeFinal,
        artigoExiste: !!artigo,
        armazemExiste: !!armazem,
        deveCrear: !movimentoExistente && !!artigo && !!armazem,
      });

      // CRIAR MOVIMENTO com a quantidade CORRETA do artigo original
      if (!movimentoExistente && artigo && armazem) {
        console.log(`[DIAGNOSTICO] âœ… Criando movimento de entrada inicial para ${artigo.codigo}`);

        // ðŸŽ¯ USAR quantidade REAL do artigo! Se for 0, definir 100 como fallback
        const quantidadeMovimento = quantidadeFinal > 0 ? quantidadeFinal : 100;

        const resultado = await movimentosStock.criarMovimento({
          empresaId: empresaId,
          artigoId: stockData.artigoId,
          tipo: 'entrada',
          quantidade: quantidadeMovimento,
          motivo: 'recepcao',
          armazemId: stockData.armazemId,
          documentoTipo: 'Entrada Inicial',
          documentoNumero: 'AUTO',
          dataMovimento: stockData.criadoEm?.split('T')[0] || new Date().toISOString().split('T')[0],
          observacoes: `Entrada inicial - Quantidade original: ${quantidadeOriginalArtigo > 0 ? quantidadeOriginalArtigo : 'N/A'}, Stock armazém: ${quantidadeStockArmazem}`,
        });

        console.log(`[DIAGNOSTICO] Resultado da criação:`, resultado);

        if (resultado.success) {
          movimentosCriados++;
          info.movimentoCriado = true;
          info.quantidadeMovimento = quantidadeMovimento;
        } else {
          info.erroMovimento = resultado.error;
        }
      } else if (!artigo) {
        info.erro = 'Artigo não encontrado';
      } else if (!armazem) {
        info.erro = 'Armazém não encontrado';
      }
    }

    console.log(`[DIAGNOSTICO] Concluido. Movimentos criados: ${movimentosCriados}`);

    return c.json({
      success: true,
      data: {
        movimentosTotais: todosMovimentos.length,
        movimentosDaEmpresa: movimentosDaEmpresa.length,
        artigosDaEmpresa: artigosDaEmpresa.length,
        stocksArmazem: todosStocks.length,
        movimentosCriados,
        relatorio,
      }
    });
  } catch (error) {
    console.error("[DIAGNOSTICO] Erro:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ========== ROTAS DE ARMAZÃ‰NS ==========

// Listar armazéns
app.get("/make-server-7249dcd9/armazens/:empresaId", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const acessoListarArmazens = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!acessoListarArmazens.permitido) {
      return c.json({ success: false, error: acessoListarArmazens.error }, acessoListarArmazens.status as any);
    }
    // console.log("[API] ðŸ”µ Listando armazéns para empresa:", empresaId);

    const tipo = c.req.query("tipo") as any;
    const ativo = c.req.query("ativo");
    const busca = c.req.query("busca");

    const filtros: any = {};
    if (tipo) filtros.tipo = tipo;
    if (ativo !== undefined) filtros.ativo = ativo === "true";
    if (busca) filtros.busca = busca;

    // console.log("[API] ðŸ”µ Filtros aplicados:", filtros);

    const resultado = await armazens.listarArmazens(empresaId, filtros);

    // console.log("[API] âœ… Armazéns encontrados:", resultado.length);

    return c.json({ success: true, data: resultado });
  } catch (error) {
    // console.error("[API] âŒ Erro ao listar armazéns:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar armazém por ID
app.get("/make-server-7249dcd9/armazens/armazem/:id", async (c) => {
  try {
    const chamadorArmazem = await obterUsuarioAutenticadoRequest(c);
    if (!chamadorArmazem || chamadorArmazem.ativo === false) {
      return c.json({ success: false, error: "Utilizador nao autenticado" }, 401);
    }
    const id = c.req.param("id");
    const armazem = await armazens.buscarArmazemPorId(id);

    if (!armazem) {
      return c.json({ success: false, error: "Armazém não encontrado" }, 404);
    }
    if (!isUsuarioSuperAdminTonline(chamadorArmazem) && String(chamadorArmazem.empresaId || "") !== String(armazem.empresaId || "")) {
      return c.json({ success: false, error: "Nao tem permissao para aceder a esta empresa" }, 403);
    }

    return c.json({ success: true, data: armazem });
  } catch (error) {
    // console.error("[API] Erro ao buscar armazém:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar armazém por código
app.get("/make-server-7249dcd9/armazens/:empresaId/codigo/:codigo", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const acessoArmazemCodigo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!acessoArmazemCodigo.permitido) {
      return c.json({ success: false, error: acessoArmazemCodigo.error }, acessoArmazemCodigo.status as any);
    }
    const codigo = c.req.param("codigo");
    const armazem = await armazens.buscarArmazemPorCodigo(empresaId, codigo);

    if (!armazem) {
      return c.json({ success: false, error: "Armazém não encontrado" }, 404);
    }

    return c.json({ success: true, data: armazem });
  } catch (error) {
    // console.error("[API] Erro ao buscar armazém por código:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Criar novo armazém
app.post("/make-server-7249dcd9/armazens", async (c) => {
  try {
    const dados = await lerBodyJsonSeguro(c);
    const acessoCriarArmazem = await verificarEscopoEmpresaRequest(c, dados?.empresaId);
    if (!acessoCriarArmazem.permitido) {
      return c.json({ success: false, error: acessoCriarArmazem.error }, acessoCriarArmazem.status as any);
    }
    const resultado = await armazens.criarArmazem(dados);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    return c.json(resultado, 201);
  } catch (error) {
    // console.error("[API] Erro ao criar armazém:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Atualizar armazém
app.put("/make-server-7249dcd9/armazens/:id", async (c) => {
  try {
    const chamadorAtualizarArmazem = await obterUsuarioAutenticadoRequest(c);
    if (!chamadorAtualizarArmazem || chamadorAtualizarArmazem.ativo === false) {
      return c.json({ success: false, error: "Utilizador nao autenticado" }, 401);
    }
    const id = c.req.param("id");
    const armazemExistenteParaAtualizar = await armazens.buscarArmazemPorId(id);
    if (!armazemExistenteParaAtualizar) {
      return c.json({ success: false, error: "Armazém não encontrado" }, 404);
    }
    if (!isUsuarioSuperAdminTonline(chamadorAtualizarArmazem) && String(chamadorAtualizarArmazem.empresaId || "") !== String(armazemExistenteParaAtualizar.empresaId || "")) {
      return c.json({ success: false, error: "Nao tem permissao para aceder a esta empresa" }, 403);
    }
    const dados = await lerBodyJsonSeguro(c);
    const resultado = await armazens.atualizarArmazem(id, dados);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    return c.json(resultado);
  } catch (error) {
    // console.error("[API] Erro ao atualizar armazém:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Deletar armazém
app.delete("/make-server-7249dcd9/armazens/:id", async (c) => {
  try {
    const chamadorDeletarArmazem = await obterUsuarioAutenticadoRequest(c);
    if (!chamadorDeletarArmazem || chamadorDeletarArmazem.ativo === false) {
      return c.json({ success: false, error: "Utilizador nao autenticado" }, 401);
    }
    const id = c.req.param("id");
    const armazemExistenteParaDeletar = await armazens.buscarArmazemPorId(id);
    if (!armazemExistenteParaDeletar) {
      return c.json({ success: false, error: "Armazém não encontrado" }, 404);
    }
    if (!isUsuarioSuperAdminTonline(chamadorDeletarArmazem) && String(chamadorDeletarArmazem.empresaId || "") !== String(armazemExistenteParaDeletar.empresaId || "")) {
      return c.json({ success: false, error: "Nao tem permissao para aceder a esta empresa" }, 403);
    }
    const resultado = await armazens.deletarArmazem(id);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    return c.json(resultado);
  } catch (error) {
    // console.error("[API] Erro ao deletar armazém:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Alternar status ativo/inativo
app.patch("/make-server-7249dcd9/armazens/:id/status", async (c) => {
  try {
    const chamadorStatusArmazem = await obterUsuarioAutenticadoRequest(c);
    if (!chamadorStatusArmazem || chamadorStatusArmazem.ativo === false) {
      return c.json({ success: false, error: "Utilizador nao autenticado" }, 401);
    }
    const id = c.req.param("id");
    const armazemExistenteParaStatus = await armazens.buscarArmazemPorId(id);
    if (!armazemExistenteParaStatus) {
      return c.json({ success: false, error: "Armazém não encontrado" }, 404);
    }
    if (!isUsuarioSuperAdminTonline(chamadorStatusArmazem) && String(chamadorStatusArmazem.empresaId || "") !== String(armazemExistenteParaStatus.empresaId || "")) {
      return c.json({ success: false, error: "Nao tem permissao para aceder a esta empresa" }, 403);
    }
    const resultado = await armazens.alternarStatusArmazem(id);

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    return c.json(resultado);
  } catch (error) {
    // console.error("[API] Erro ao alternar status do armazém:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Obter estatísticas de armazéns
app.get("/make-server-7249dcd9/armazens/:empresaId/estatisticas", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const acessoEstatisticasArmazens = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!acessoEstatisticasArmazens.permitido) {
      return c.json({ success: false, error: acessoEstatisticasArmazens.error }, acessoEstatisticasArmazens.status as any);
    }
    const stats = await armazens.obterEstatisticasArmazens(empresaId);

    return c.json({ success: true, data: stats });
  } catch (error) {
    // console.error("[API] Erro ao obter estatísticas de armazéns:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ========== ROTAS DE STOCK POR ARMAZÃ‰M ==========

// Listar todo o stock de uma empresa (todos os armazéns) - DEVE VIR ANTES DA ROTA GENÃ‰RICA
app.get("/make-server-7249dcd9/stock-armazem/empresa/:empresaId", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    // console.log('[API] ðŸ“Š Listando stock para empresa:', empresaId);
    // console.log('[API] ðŸ” URL completa recebida:', c.req.url);
    // console.log('[API] ðŸ” Tipo do empresaId:', typeof empresaId);
    // console.log('[API] ðŸ” empresaId é vazio?', !empresaId);

    if (!empresaId) {
      // console.error('[API] âŒ empresaId não fornecido!');
      return c.json({ success: false, error: "empresaId é obrigatório" }, 400);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }

    const stocks = await stockArmazem.listarStockPorEmpresa(empresaId);
    // console.log('[API] âœ… Stock carregado:', stocks.length, 'registros');

    return c.json({ success: true, data: stocks });
  } catch (error) {
    // console.error("[API] Erro ao listar stock da empresa:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ðŸ” DEBUG: Ver TODOS os stocks no KV store
app.get("/make-server-7249dcd9/stock-lotes/empresa/:empresaId", validarAcessoMiddleware("stock-inventario"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const { artigoId, armazemId, somenteDisponivel, incluirExpirados } = c.req.query();

    const lotes = await stockLotes.listarLotes(empresaId, {
      artigoId: artigoId || undefined,
      armazemId: armazemId || undefined,
      somenteDisponivel: somenteDisponivel === "true",
      incluirExpirados: incluirExpirados === "true",
    });

    return c.json({ success: true, data: lotes });
  } catch (error) {
    console.error("[API] Erro ao listar stock por lote:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.get("/make-server-7249dcd9/stock-lotes/resumo/:empresaId/:artigoId", validarAcessoMiddleware("stock-inventario"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const artigoId = c.req.param("artigoId");
    const resumo = await stockLotes.obterResumoLotesArtigo(empresaId, artigoId);

    return c.json({ success: true, data: resumo });
  } catch (error) {
    console.error("[API] Erro ao resumir lotes do artigo:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.get("/make-server-7249dcd9/stock-lotes/alertas/:empresaId", validarAcessoMiddleware("stock-inventario"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const dias = Number(c.req.query("dias") || "30");
    const alertas = await stockLotes.listarAlertasValidade(empresaId, Number.isFinite(dias) ? dias : 30);

    return c.json({ success: true, data: alertas });
  } catch (error) {
    console.error("[API] Erro ao listar alertas de validade:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.post("/make-server-7249dcd9/stock-lotes", validarAcessoMiddleware("stock-inventario"), async (c) => {
  try {
    const dados = await lerBodyJsonSeguro(c);
    const lote = await stockLotes.upsertLote(dados);
    return c.json({ success: true, data: lote });
  } catch (error) {
    console.error("[API] Erro ao gravar lote:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.post("/make-server-7249dcd9/stock-lotes/:loteId/mover-para-quebra", validarAcessoMiddleware("stock-inventario"), async (c) => {
  try {
    const loteId = c.req.param("loteId");
    const dados = await lerBodyJsonSeguro(c);
    const {
      empresaId,
      quantidade,
      armazemDestinoId,
    } = dados;

    if (!empresaId) {
      return c.json({ success: false, error: "empresaId é obrigatório" }, 400);
    }

    const lote = await stockLotes.buscarLotePorId(loteId);
    if (!lote || lote.empresaId !== empresaId) {
      return c.json({ success: false, error: "Lote não encontrado" }, 404);
    }

    const armazemDestino = armazemDestinoId
      ? await armazens.buscarArmazemPorId(armazemDestinoId, empresaId)
      : (await armazens.obterOuCriarArmazemZonaQuebra(empresaId)).data;

    if (!armazemDestino) {
      return c.json({ success: false, error: "Não foi possível obter a zona de quebra" }, 400);
    }

    const resultado = await stockLotes.transferirLoteEntreArmazens({
      empresaId,
      loteId,
      armazemDestinoId: armazemDestino.id,
      quantidade,
    });

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    return c.json({
      success: true,
      data: {
        loteOrigem: resultado.loteOrigem,
        loteDestino: resultado.loteDestino,
        armazemDestino,
      },
    });
  } catch (error) {
    console.error("[API] Erro ao mover lote para zona de quebra:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.post("/make-server-7249dcd9/stock-lotes/:loteId/reverter-movimento-quebra", validarAcessoMiddleware("stock-inventario"), async (c) => {
  try {
    const loteId = c.req.param("loteId");
    const dados = await lerBodyJsonSeguro(c);
    const {
      empresaId,
      quantidade,
      armazemDestinoId,
    } = dados;

    if (!empresaId || !armazemDestinoId) {
      return c.json({ success: false, error: "empresaId e armazemDestinoId são obrigatórios" }, 400);
    }

    const lote = await stockLotes.buscarLotePorId(loteId);
    if (!lote || lote.empresaId !== empresaId) {
      return c.json({ success: false, error: "Lote não encontrado" }, 404);
    }

    const armazemDestino = await armazens.buscarArmazemPorId(armazemDestinoId, empresaId);
    if (!armazemDestino) {
      return c.json({ success: false, error: "Armazém de destino não encontrado" }, 404);
    }

    const resultado = await stockLotes.transferirLoteEntreArmazens({
      empresaId,
      loteId,
      armazemDestinoId: armazemDestino.id,
      quantidade,
    });

    if (!resultado.success) {
      return c.json(resultado, 400);
    }

    return c.json({
      success: true,
      data: {
        loteOrigem: resultado.loteOrigem,
        loteDestino: resultado.loteDestino,
        armazemDestino,
      },
    });
  } catch (error) {
    console.error("[API] Erro ao reverter movimento da zona de quebra:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.get("/make-server-7249dcd9/stock-validade/relatorio/:empresaId", validarAcessoMiddleware("stock-inventario"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const dias = Number(c.req.query("dias") || "30");
    const relatorio = await relatorioValidade.obterRelatorioValidadeOperacional(
      empresaId,
      Number.isFinite(dias) ? dias : 30,
    );

    return c.json({ success: true, data: relatorio });
  } catch (error) {
    console.error("[API] Erro ao gerar relatório operacional de validade:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.get("/make-server-7249dcd9/stock-armazem/debug/todos", async (c) => {
  try {
    const { getUserFromRequest } = await import('./permission-middleware.tsx');
    const usuarioDebugTodos = await getUserFromRequest(c);
    const nivelDebugTodos = String(usuarioDebugTodos?.nivel || '').trim().toLowerCase();
    if (!usuarioDebugTodos || (nivelDebugTodos !== 'super_admin' && nivelDebugTodos !== 'superadmin_tonline')) {
      return c.json({ success: false, error: 'Acesso restrito a super administradores' }, 403);
    }
    const todosStocks = await kv.getByPrefix("stockarmazem_");
    // console.log('[DEBUG] ðŸ“¦ Total de registros no KV:', todosStocks.length);

    // Agrupar por empresa
    const porEmpresa = {};
    todosStocks.forEach(s => {
      if (!porEmpresa[s.empresaId]) {
        porEmpresa[s.empresaId] = [];
      }
      porEmpresa[s.empresaId].push(s);
    });

    // console.log('[DEBUG] ðŸ“Š Stocks por empresa:', Object.keys(porEmpresa).map(empId => ({
    //   empresaId: empId,
    //   quantidade: porEmpresa[empId].length,
    //   totalQuantidade: porEmpresa[empId].reduce((sum, s) => sum + s.quantidade, 0)
    // })));

    return c.json({
      success: true,
      totalRegistros: todosStocks.length,
      porEmpresa: Object.keys(porEmpresa).map(empId => ({
        empresaId: empId,
        registros: porEmpresa[empId].length,
        totalQuantidade: porEmpresa[empId].reduce((sum, s) => sum + s.quantidade, 0),
        stocks: porEmpresa[empId]
      })),
      todosStocks
    });
  } catch (error) {
    // console.error("[DEBUG] Erro:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ðŸ” DEBUG: Testar mapa de stock para POS
app.get("/make-server-7249dcd9/debug/pos-stock/:empresaId", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const acessoPosStock = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!acessoPosStock.permitido) {
      return c.json({ success: false, error: acessoPosStock.error }, acessoPosStock.status as any);
    }

    console.log('ðŸ”§ [DEBUG POS] Testando stock para empresa:', empresaId);

    // 1. Buscar artigos ATIVOS
    const artigosAtivos = await artigos.listarArtigos(empresaId, { ativo: true });
    console.log('ðŸ”§ [DEBUG POS] Artigos ATIVOS:', artigosAtivos.length);

    // 2. Buscar TODOS os artigos (incluindo inativos)
    const todosArtigos = await artigos.listarArtigos(empresaId, {});
    console.log('ðŸ”§ [DEBUG POS] TODOS os artigos:', todosArtigos.length);

    // 3. Buscar stocks
    const todosStocks = await stockArmazem.listarStockPorEmpresa(empresaId);
    console.log('ðŸ”§ [DEBUG POS] Stocks encontrados:', todosStocks.length);

    // 4. Criar mapa de stock (apenas ativos)
    const artigosIds = artigosAtivos.map(a => a.id);
    const mapaStock = await stockArmazem.obterMapaStockArtigos(empresaId, artigosIds);
    console.log('ðŸ”§ [DEBUG POS] Mapa de stock criado com', Object.keys(mapaStock).length, 'entradas');

    // 5. Artigos com e sem stock (apenas ativos)
    const artigosComStock = artigosAtivos.filter(a => (mapaStock[a.id] || 0) > 0);
    const artigosSemStock = artigosAtivos.filter(a => (mapaStock[a.id] || 0) <= 0);

    console.log('ðŸ”§ [DEBUG POS] Artigos ATIVOS COM stock:', artigosComStock.length);
    console.log('ðŸ”§ [DEBUG POS] Artigos ATIVOS SEM stock:', artigosSemStock.length);

    // 6. Encontrar stocks "órfãos" (de artigos inativos/excluídos)
    const artigosComStockOrfao = todosStocks.filter(stock => {
      const artigo = todosArtigos.find(a => a.id === stock.artigoId);
      return !artigo || !artigo.ativo;
    });

    console.log('ðŸ”§ [DEBUG POS] Stocks Ã“RFÃƒOS (de artigos inativos):', artigosComStockOrfao.length);

    return c.json({
      success: true,
      empresaId,
      resumo: {
        totalArtigos: artigosAtivos.length,
        totalArtigosTodos: todosArtigos.length,
        totalStocks: todosStocks.length,
        artigosComStock: artigosComStock.length,
        artigosSemStock: artigosSemStock.length,
        stocksOrfaos: artigosComStockOrfao.length,
      },
      artigos: artigosAtivos.map(a => ({
        id: a.id,
        codigo: a.codigo,
        nome: a.nome,
        ativo: a.ativo,
        stockTotal: mapaStock[a.id] || 0,
      })),
      todosArtigos: todosArtigos.map(a => ({
        id: a.id,
        codigo: a.codigo,
        nome: a.nome,
        ativo: a.ativo,
        temStock: todosStocks.some(s => s.artigoId === a.id && s.quantidade > 0),
        stockTotal: todosStocks
          .filter(s => s.artigoId === a.id)
          .reduce((sum, s) => sum + (s.quantidade || 0), 0),
      })),
      stocks: todosStocks,
      stocksOrfaos: artigosComStockOrfao,
      mapaStock,
    });
  } catch (error) {
    console.error("ðŸ”§ [DEBUG POS] Erro:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// âœ… Obter estatísticas de TODOS os armazéns de uma empresa (ROTA ESPECÃFICA PRIMEIRO!)
app.get("/make-server-7249dcd9/stock-armazem/estatisticas/todos/:empresaId", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    // console.log('[API] ðŸ“Š Obtendo estatísticas de todos os armazéns para empresa:', empresaId);

    // Buscar todos os armazéns da empresa
    const armazensList = await armazens.listarArmazens(empresaId, {});
    // console.log('[API] ðŸ¢ Armazéns encontrados:', armazensList.length);

    const todosArtigos = await artigos.listarArtigos(empresaId, {});
    const artigosProdutoIds = new Set(
      todosArtigos
        .filter((artigo) => artigo.tipo === 'produto')
        .map((artigo) => artigo.id)
    );
    const todosStocks = await stockArmazem.listarStockPorEmpresa(empresaId);

    // Buscar estatísticas de cada armazém considerando apenas produtos
    const estatisticas = [];
    for (const armazem of armazensList) {
      // console.log('[API] ðŸ“Š Calculando estatísticas para armazém:', armazem.id, armazem.nome);
      const stocksProdutosDoArmazem = todosStocks.filter(
        (stock) => stock.armazemId === armazem.id && artigosProdutoIds.has(stock.artigoId)
      );
      const stats = {
        totalArtigos: stocksProdutosDoArmazem.length,
        quantidadeTotal: stocksProdutosDoArmazem.reduce((sum, stock) => sum + (stock.quantidade || 0), 0),
        quantidadeReservada: stocksProdutosDoArmazem.reduce((sum, stock) => sum + (stock.quantidadeReservada || 0), 0),
        quantidadeDisponivel: stocksProdutosDoArmazem.reduce((sum, stock) => sum + (stock.quantidadeDisponivel || 0), 0),
        valorTotal: stocksProdutosDoArmazem.reduce((sum, stock) => sum + ((stock.quantidade || 0) * (stock.custoMedio || 0)), 0),
      };
      // console.log('[API] ðŸ“Š Resultado:', stats);
      estatisticas.push({
        armazemId: armazem.id,
        armazemNome: armazem.nome,
        armazemCodigo: armazem.codigo,
        ...stats
      });
    }

    // console.log('[API] âœ… Estatísticas calculadas para', estatisticas.length, 'armazéns');
    return c.json({ success: true, data: estatisticas });
  } catch (error) {
    // console.error("[API] Erro ao obter estatísticas dos armazéns:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// âœ… Obter estatísticas de um armazém (DEVE VIR ANTES DA ROTA GENÃ‰RICA!)
app.get("/make-server-7249dcd9/stock-armazem/estatisticas/:armazemId", async (c) => {
  try {
    const armazemId = c.req.param("armazemId");
    const empresaId = c.req.query("empresaId"); // âœ… Pegar empresaId do query param
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    // console.log('[API] ðŸ“Š Obtendo estatísticas do armazém:', armazemId, 'Empresa:', empresaId);

    const armazem = empresaId ? await armazens.buscarArmazemPorId(armazemId, empresaId) : null;
    const stats = await stockArmazem.obterEstatisticasArmazem(armazem?.id || armazemId, empresaId);

    // console.log('[API] âœ… Estatísticas calculadas:', stats);
    return c.json({ success: true, data: stats });
  } catch (error) {
    // console.error("[API] Erro ao obter estatísticas do armazém:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// âœ… NOVA: Obter estatísticas completas para o Dashboard de Stock
app.get("/make-server-7249dcd9/stock-armazem/dashboard/estatisticas/:empresaId", validarAcessoMiddleware("stock-inventario"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    console.log('[API] ðŸ“Š Obtendo estatísticas do dashboard para empresa:', empresaId);

    // 1. Buscar todos os artigos
    const todosArtigos = await artigos.listarArtigos(empresaId, {});
    console.log('[API] ðŸ“¦ Total de artigos encontrados:', todosArtigos.length);

    // 2. Buscar todos os stocks
    const todosStocks = await stockArmazem.listarStockPorEmpresa(empresaId);
    console.log('[API] ðŸ“Š Total de registros de stock encontrados:', todosStocks.length);

    // 3. Calcular estatísticas
    const artigosProduto = todosArtigos.filter(a => a.tipo === 'produto');
    const totalArtigos = artigosProduto.length;
    const totalArtigosProdutoAtivos = artigosProduto.filter(a => a.ativo).length;
    const totalArtigosAtivos = totalArtigosProdutoAtivos;
    const totalArtigosProduto = artigosProduto.length;
    const totalArtigosServico = todosArtigos.filter(a => a.tipo === 'servico').length;
    const totalArtigosMateriaPrima = todosArtigos.filter(a => a.tipo === 'materia-prima').length;

    // 4. Calcular valor total em stock apenas para produtos
    let valorTotalStock = 0;
    for (const art of artigosProduto) {
      // Buscar quantidade total em todos os armazéns
      const stocksDoArtigo = todosStocks.filter(s => s.artigoId === art.id);
      const quantidadeTotal = stocksDoArtigo.reduce((sum, s) => sum + s.quantidade, 0);
      valorTotalStock += quantidadeTotal * (art.precoCompra || 0);
    }

    // 5. Identificar artigos em ruptura e baixo stock
    const artigosEmRuptura: any[] = [];
    const artigosBaixoStock: any[] = [];

    for (const art of artigosProduto) {
      // Buscar quantidade total em todos os armazéns
      const stocksDoArtigo = todosStocks.filter(s => s.artigoId === art.id);
      const quantidadeTotal = stocksDoArtigo.reduce((sum, s) => sum + s.quantidade, 0);

      // Verificar ruptura (quantidade <= 0)
      if (quantidadeTotal <= 0) {
        artigosEmRuptura.push({
          artigoId: art.id,
          artigoCodigo: art.codigo,
          artigoNome: art.nome,
          quantidade: quantidadeTotal,
          estoqueMinimo: art.estoqueMinimo || 0,
        });
      }
      // Verificar baixo stock (quantidade < estoqueMinimo)
      else if (art.estoqueMinimo && quantidadeTotal < art.estoqueMinimo) {
        artigosBaixoStock.push({
          artigoId: art.id,
          artigoCodigo: art.codigo,
          artigoNome: art.nome,
          quantidade: quantidadeTotal,
          estoqueMinimo: art.estoqueMinimo,
        });
      }
    }

    console.log('[API] âœ… Estatísticas calculadas:', {
      totalArtigos,
      totalArtigosAtivos,
      valorTotalStock,
      artigosEmRuptura: artigosEmRuptura.length,
      artigosBaixoStock: artigosBaixoStock.length,
    });

    return c.json({
      success: true,
      data: {
        totalArtigos,
        totalArtigosAtivos,
        totalArtigosProduto,
        totalArtigosProdutoAtivos,
        totalArtigosServico,
        totalArtigosMateriaPrima,
        valorTotalStock,
        artigosEmRuptura: artigosEmRuptura.length,
        artigosBaixoStock: artigosBaixoStock.length,
        listaArtigosEmRuptura: artigosEmRuptura.slice(0, 10), // Top 10
        listaArtigosBaixoStock: artigosBaixoStock.slice(0, 10).sort((a, b) => a.quantidade - b.quantidade), // Top 10 mais urgentes
      }
    });
  } catch (error) {
    console.error("[API] Erro ao obter estatísticas do dashboard:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// âœ… NOVA: Obter estatísticas completas para o Dashboard de Faturação
app.get("/make-server-7249dcd9/facturas/dashboard/estatisticas/:empresaId", validarAcessoMiddleware("faturacao-vendas"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    console.log('[API] ðŸ“Š Obtendo estatísticas do dashboard de faturação para empresa:', empresaId);

    // 1. Buscar todas as facturas
    const todasFacturas = (await facturas.listarFacturasPorEmpresa(empresaId)) || [];
    console.log('[API] ðŸ“„ Total de facturas encontradas:', todasFacturas.length);

    // 2. Buscar VDs (Vendas a Dinheiro)
    const resultVDs = await vendasDinheiro.getVDsByEmpresa(empresaId);
    const todasVDs = (resultVDs.success && resultVDs.data) ? resultVDs.data : [];
    console.log('[API] ðŸ’µ Total de VDs encontradas:', todasVDs.length);

    // 3. Buscar todos os recibos
    const todosRecibos = (await recibos.listarRecibosPorEmpresa(empresaId)) || [];
    console.log('[API] ðŸ§¾ Total de recibos encontrados:', todosRecibos.length);

    // 4. Datas para filtros
    const hoje = new Date().toISOString().split('T')[0];
    const mesAtual = new Date().toISOString().substring(0, 7);
    const mesAnterior = new Date();
    mesAnterior.setMonth(mesAnterior.getMonth() - 1);
    const mesAnteriorStr = mesAnterior.toISOString().substring(0, 7);

    // 5. Filtrar por período
    const facturasHoje = todasFacturas.filter((f: any) => f.dataEmissao?.startsWith(hoje));
    const facturasMes = todasFacturas.filter((f: any) => f.dataEmissao?.startsWith(mesAtual));
    const facturasMesAnterior = todasFacturas.filter((f: any) => f.dataEmissao?.startsWith(mesAnteriorStr));

    const vdsHoje = todasVDs.filter((v: any) => v.dataEmissao?.startsWith(hoje));
    const vdsMes = todasVDs.filter((v: any) => v.dataEmissao?.startsWith(mesAtual));
    const vdsMesAnterior = todasVDs.filter((v: any) => v.dataEmissao?.startsWith(mesAnteriorStr));

    // 6. Calcular totais de vendas
    const vendasHoje =
      facturasHoje.reduce((sum: number, f: any) => sum + (f.totalGeral || 0), 0) +
      vdsHoje.reduce((sum: number, v: any) => sum + (v.totalGeral || 0), 0);

    const vendasMes =
      facturasMes.reduce((sum: number, f: any) => sum + (f.totalGeral || 0), 0) +
      vdsMes.reduce((sum: number, v: any) => sum + (v.totalGeral || 0), 0);

    const vendasMesAnterior =
      facturasMesAnterior.reduce((sum: number, f: any) => sum + (f.totalGeral || 0), 0) +
      vdsMesAnterior.reduce((sum: number, v: any) => sum + (v.totalGeral || 0), 0);

    // 7. Calcular crescimento
    const crescimentoMes = vendasMesAnterior > 0
      ? ((vendasMes - vendasMesAnterior) / vendasMesAnterior) * 100
      : 0;

    // 8. Calcular ticket médio
    const totalTransacoesMes = facturasMes.length + vdsMes.length;
    const ticketMedio = totalTransacoesMes > 0 ? vendasMes / totalTransacoesMes : 0;

    // 9. Analisar métodos de pagamento (baseado em recibos)
    const metodoPagamento: Record<string, { valor: number; quantidade: number }> = {};

    todosRecibos.forEach((r: any) => {
      const metodo = r.metodoPagamento || 'Numerário';
      if (!metodoPagamento[metodo]) {
        metodoPagamento[metodo] = { valor: 0, quantidade: 0 };
      }
      metodoPagamento[metodo].valor += r.valorRecebido || 0;
      metodoPagamento[metodo].quantidade += 1;
    });

    // Converter para array e ordenar
    const metodosPagamentoArray = Object.entries(metodoPagamento)
      .map(([metodo, dados]) => ({
        metodo,
        valor: dados.valor,
        quantidade: dados.quantidade,
        percentual: vendasMes > 0 ? (dados.valor / vendasMes) * 100 : 0
      }))
      .sort((a, b) => b.valor - a.valor);

    // 10. Analisar produtos mais vendidos
    const produtosVendidos: Record<string, {
      artigoId: string;
      artigoCodigo: string;
      artigoNome: string;
      quantidade: number;
      valorTotal: number;
    }> = {};

    // Processar facturas
    facturasMes.forEach((f: any) => {
      if (f.itens && Array.isArray(f.itens)) {
        f.itens.forEach((item: any) => {
          const key = item.artigoId || item.artigo;
          if (!produtosVendidos[key]) {
            produtosVendidos[key] = {
              artigoId: item.artigoId || item.artigo,
              artigoCodigo: item.artigoCodigo || item.codigo || '-',
              artigoNome: item.artigoNome || item.descricao || 'Artigo',
              quantidade: 0,
              valorTotal: 0,
            };
          }
          produtosVendidos[key].quantidade += item.quantidade || 0;
          produtosVendidos[key].valorTotal += (item.quantidade || 0) * (item.precoUnitario || 0);
        });
      }
    });

    // Processar VDs
    vdsMes.forEach((v: any) => {
      if (v.itens && Array.isArray(v.itens)) {
        v.itens.forEach((item: any) => {
          const key = item.artigoId || item.artigo;
          if (!produtosVendidos[key]) {
            produtosVendidos[key] = {
              artigoId: item.artigoId || item.artigo,
              artigoCodigo: item.artigoCodigo || item.codigo || '-',
              artigoNome: item.artigoNome || item.descricao || 'Artigo',
              quantidade: 0,
              valorTotal: 0,
            };
          }
          produtosVendidos[key].quantidade += item.quantidade || 0;
          produtosVendidos[key].valorTotal += (item.quantidade || 0) * (item.precoUnitario || 0);
        });
      }
    });

    // Converter para array e ordenar por valor total (Top 5)
    const topProdutos = Object.values(produtosVendidos)
      .sort((a, b) => b.valorTotal - a.valorTotal)
      .slice(0, 5);

    console.log('[API] âœ… Estatísticas calculadas:', {
      vendasHoje,
      vendasMes,
      crescimentoMes,
      ticketMedio,
      metodoPagamento: metodosPagamentoArray.length,
      topProdutos: topProdutos.length,
    });

    return c.json({
      success: true,
      data: {
        vendasHoje,
        vendasMes,
        crescimentoMes,
        ticketMedio,
        facturasHoje: facturasHoje.length + vdsHoje.length,
        facturasMes: facturasMes.length + vdsMes.length,
        metodosPagamento: metodosPagamentoArray,
        topProdutos,
      }
    });
  } catch (error) {
    console.error("[API] Erro ao obter estatísticas do dashboard de faturação:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Obter stock de um artigo em um armazém
app.get("/make-server-7249dcd9/stock-armazem/:armazemId/:artigoId", async (c) => {
  try {
    const armazemId = c.req.param("armazemId");
    const artigoId = c.req.param("artigoId");

    // Precisamos do empresaId, vamos buscar do query param
    const empresaId = c.req.query("empresaId");
    if (!empresaId) {
      return c.json({ success: false, error: "empresaId é obrigatório" }, 400);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }

    const armazem = await armazens.buscarArmazemPorId(armazemId, empresaId);
    const stock = await stockArmazem.buscarStockArtigoArmazem(empresaId, artigoId, armazem?.id || armazemId);

    return c.json({ success: true, data: stock });
  } catch (error) {
    // console.error("[API] Erro ao obter stock do armazém:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// âœ… ENDPOINT DE TESTE PARA FORÃ‡AR ATUALIZAÃ‡ÃƒO DO CACHE
app.get("/make-server-7249dcd9/health-check-v5", async (c) => {
  return c.json({
    status: "OK",
    version: "v5.0-cache-buster",
    timestamp: new Date().toISOString(),
    message: "Edge function está ATUALIZADA!"
  });
});

// âœ…âœ…âœ… NOVA ROTA v2 - PARA CONTORNAR CACHE DO SUPABASE âœ…âœ…âœ…
app.get("/make-server-7249dcd9/stock-armazem-v2/armazem/:armazemId", async (c) => {
  const VERSION = "v6.0-nova-rota";
  // console.log(`[API] â­â­â­ ROTA V2 CHAMADA: stock-armazem-v2 - ${VERSION} â­â­â­`);
  try {
    const armazemId = c.req.param("armazemId");
    const empresaId = c.req.query("empresaId");

    // console.log('[API] ðŸ“¦ Listando stock do armazém:', armazemId);
    // console.log('[API] ðŸ¢ Para empresa:', empresaId);

    if (!empresaId) {
      // console.error('[API] âŒ empresaId não fornecido!');
      return c.json({ success: false, error: "empresaId é obrigatório" }, 400);
    }
    const escopoV2 = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopoV2.permitido) {
      return c.json({ success: false, error: escopoV2.error }, escopoV2.status as any);
    }

    const armazem = await armazens.buscarArmazemPorId(armazemId, empresaId);
    if (!armazem) {
      return c.json({ success: false, error: "Armazém não encontrado", version: VERSION }, 404);
    }
    const armazemIdCanonical = armazem.id;

    const todosStocks = await stockArmazem.listarStockPorArmazem(armazemIdCanonical);
    // console.log('[API] ðŸ” Total de stocks encontrados (TODOS):', todosStocks.length);

    const stocksDaEmpresa = todosStocks.filter(s => s.empresaId === empresaId);
    // console.log('[API] âœ… Stocks filtrados por empresa:', stocksDaEmpresa.length);

    // console.log('[API] ðŸ¢ Armazém encontrado:', armazem ? `${armazem.codigo} - ${armazem.nome}` : 'NÃƒO ENCONTRADO');

    const stocksEnriquecidos = await Promise.all(
      stocksDaEmpresa.map(async (stock) => {
        // console.log('[API] ðŸ” Buscando artigo:', stock.artigoId);
        const artigo = await artigos.buscarArtigoPorId(stock.artigoId);
        // console.log('[API] ðŸ“¦ Artigo encontrado:', artigo ? `${artigo.codigo} - ${artigo.nome}` : 'NÃƒO ENCONTRADO');

        return {
          id: stock.id,
          armazemId: stock.armazemId,
          armazemCodigo: armazem?.codigo || '',
          armazemNome: armazem?.nome || '',
          artigoId: stock.artigoId,
          artigoCodigo: artigo?.codigo || '',
          artigoNome: artigo?.nome || '',
          quantidade: stock.quantidade,
          dataUltimaAtualizacao: stock.atualizadoEm,
        };
      })
    );

    // console.log('[API] ðŸ“Š Stocks enriquecidos:', stocksEnriquecidos.length);
    // console.log('[API] ðŸ“Š Dados enriquecidos:', JSON.stringify(stocksEnriquecidos, null, 2));

    return c.json({
      success: true,
      data: stocksEnriquecidos,
      version: VERSION,
      timestamp: new Date().toISOString(),
      debugInfo: {
        totalStocks: todosStocks.length,
        stocksDaEmpresa: stocksDaEmpresa.length,
        stocksEnriquecidos: stocksEnriquecidos.length
      }
    });
  } catch (error) {
    // console.error("[API] Erro ao listar stock do armazém v2:", error);
    return c.json({ success: false, error: error.message, version: VERSION }, 500);
  }
});

// Listar todo o stock de um armazém - VERSÃƒO ATUALIZADA v5.0
app.get("/make-server-7249dcd9/stock-armazem/armazem/:armazemId", async (c) => {
  const VERSION = "v5.0-cache-buster"; // âœ… NOVA VERSÃƒO
  // console.log(`[API] â­â­â­ ROTA CHAMADA: stock-armazem/armazem/:armazemId - ${VERSION} â­â­â­`);
  try {
    const armazemId = c.req.param("armazemId");
    const empresaId = c.req.query("empresaId");

    // console.log('[API] ðŸ“¦ Listando stock do armazém:', armazemId);
    // console.log('[API] ðŸ¢ Para empresa:', empresaId);

    if (!empresaId) {
      // console.error('[API] âŒ empresaId não fornecido!');
      return c.json({ success: false, error: "empresaId é obrigatório" }, 400);
    }
    const escopoArmazem = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopoArmazem.permitido) {
      return c.json({ success: false, error: escopoArmazem.error }, escopoArmazem.status as any);
    }

    // Buscar stocks e filtrar por empresa
    const armazem = await armazens.buscarArmazemPorId(armazemId, empresaId);
    if (!armazem) {
      return c.json({ success: false, error: "Armazém não encontrado", version: VERSION }, 404);
    }
    const armazemIdCanonical = armazem.id;

    const todosStocks = await stockArmazem.listarStockPorArmazem(armazemIdCanonical);
    // console.log('[API] ðŸ” Total de stocks encontrados (TODOS):', todosStocks.length);

    const stocksDaEmpresa = todosStocks.filter(s => s.empresaId === empresaId);

    // console.log('[API] âœ… Stocks filtrados por empresa:', stocksDaEmpresa.length);

    // âœ… Enriquecer com dados dos artigos e armazém
    // console.log('[API] ðŸ¢ Armazém encontrado:', armazem ? `${armazem.codigo} - ${armazem.nome}` : 'NÃƒO ENCONTRADO');

    const stocksEnriquecidos = await Promise.all(
      stocksDaEmpresa.map(async (stock) => {
        // console.log('[API] ðŸ” Buscando artigo:', stock.artigoId);
        const artigo = await artigos.buscarArtigoPorId(stock.artigoId);
        // console.log('[API] ðŸ“¦ Artigo encontrado:', artigo ? `${artigo.codigo} - ${artigo.nome}` : 'NÃƒO ENCONTRADO');

        return {
          id: stock.id,
          armazemId: stock.armazemId,
          armazemCodigo: armazem?.codigo || '',
          armazemNome: armazem?.nome || '',
          artigoId: stock.artigoId,
          artigoCodigo: artigo?.codigo || '',
          artigoNome: artigo?.nome || '',
          quantidade: stock.quantidade,
          dataUltimaAtualizacao: stock.atualizadoEm,
        };
      })
    );

    // console.log('[API] ðŸ“Š Stocks enriquecidos:', stocksEnriquecidos.length);
    // console.log('[API] ðŸ“Š Dados enriquecidos:', JSON.stringify(stocksEnriquecidos, null, 2));

    // âœ… IMPORTANTE: Se não houver stocks, retornar array vazio (não null)
    return c.json({
      success: true,
      data: stocksEnriquecidos,
      version: VERSION,
      timestamp: new Date().toISOString(),
      debugInfo: {
        totalStocks: todosStocks.length,
        stocksDaEmpresa: stocksDaEmpresa.length,
        stocksEnriquecidos: stocksEnriquecidos.length
      }
    });
  } catch (error) {
    // console.error("[API] Erro ao listar stock do armazém:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Listar armazéns onde um artigo está disponível
app.get("/make-server-7249dcd9/stock-armazem/artigo/:artigoId", async (c) => {
  try {
    const artigoId = c.req.param("artigoId");
    const artigoParaArmazens = await artigos.buscarArtigoPorId(artigoId);
    if (!artigoParaArmazens) {
      return c.json({ success: false, error: "Artigo não encontrado" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, artigoParaArmazens.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const stocks = await stockArmazem.listarArmazensPorArtigo(artigoId);

    return c.json({ success: true, data: stocks });
  } catch (error) {
    // console.error("[API] Erro ao listar armazéns do artigo:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Obter resumo de stock de um artigo (todos os armazéns)
app.get("/make-server-7249dcd9/stock-armazem/resumo/:artigoId", async (c) => {
  try {
    const artigoId = c.req.param("artigoId");
    const artigoParaResumo = await artigos.buscarArtigoPorId(artigoId);
    if (!artigoParaResumo) {
      return c.json({ success: false, error: "Artigo não encontrado" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, artigoParaResumo.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const resumo = await stockArmazem.obterResumoStockArtigo(artigoId);

    return c.json({ success: true, data: resumo });
  } catch (error) {
    // console.error("[API] Erro ao obter resumo de stock:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Transferir stock entre armazéns
app.post("/make-server-7249dcd9/stock-armazem/transferir", async (c) => {
  try {
    const dados = await lerBodyJsonSeguro(c);

    // Validar dados obrigatórios
    if (!dados.empresaId || !dados.artigoId || !dados.armazemOrigemId || !dados.armazemDestinoId || !dados.quantidade) {
      return c.json({ success: false, error: "Dados obrigatórios faltando" }, 400);
    }

    const escopo = await verificarEscopoEmpresaRequest(c, dados.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }

    const armazemOrigem = await armazens.buscarArmazemPorId(dados.armazemOrigemId, dados.empresaId);
    const armazemDestino = await armazens.buscarArmazemPorId(dados.armazemDestinoId, dados.empresaId);
    if (!armazemOrigem || !armazemDestino) {
      return c.json({ success: false, error: "Armazem de origem ou destino nao encontrado" }, 404);
    }

    const resultado = await stockArmazem.transferirStock(
      dados.empresaId,
      dados.artigoId,
      armazemOrigem.id,
      armazemDestino.id,
      dados.quantidade
    );

    return c.json({ success: true, data: resultado });
  } catch (error) {
    // console.error("[API] Erro ao transferir stock:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ðŸ”§ MIGRAÃ‡ÃƒO: Popular stock-armazém baseado nos movimentos existentes
app.post("/make-server-7249dcd9/stock-armazem/migrar/:empresaId", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    // console.log('[API] ðŸ”§ Iniciando migração de stock-armazém para empresa:', empresaId);

    if (!empresaId) {
      return c.json({ success: false, error: "empresaId é obrigatório" }, 400);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }

    // Buscar todos os movimentos da empresa
    const movimentos = await movimentosStock.listarMovimentosPorEmpresa(empresaId);
    // console.log('[API] ðŸ“¦ Movimentos encontrados:', movimentos.length);

    let processados = 0;
    let erros = 0;

    // Processar cada movimento que tem armazém
    for (const movimento of movimentos) {
      if (movimento.armazemId && movimento.artigoId) {
        try {
          const quantidadeDelta = movimento.tipo === "entrada" ? movimento.quantidade : -movimento.quantidade;

          // console.log('[API] ðŸ“¦ Processando movimento:', {
          //   id: movimento.id,
          //   artigoId: movimento.artigoId,
          //   armazemId: movimento.armazemId,
          //   tipo: movimento.tipo,
          //   quantidade: movimento.quantidade,
          //   quantidadeDelta
          // });

          await stockArmazem.atualizarStockArmazem({
            empresaId: movimento.empresaId,
            armazemId: movimento.armazemId,
            armazemCodigo: movimento.armazemCodigo || '',
            armazemNome: movimento.armazemNome || '',
            artigoId: movimento.artigoId,
            artigoCodigo: movimento.artigoCodigo || '',
            artigoNome: movimento.artigoNome || '',
            quantidadeDelta,
          });

          processados++;
          // console.log('[API] âœ… Movimento processado');
        } catch (error) {
          // console.error('[API] âŒ Erro ao processar movimento:', movimento.id, error);
          erros++;
        }
      } else {
        // console.log('[API] âš ï¸ Movimento ignorado (sem armazém/artigo):', movimento.id);
      }
    }

    // console.log('[API] âœ… Migração concluída:', { processados, erros });

    return c.json({
      success: true,
      message: `Migração concluída: ${processados} movimentos processados, ${erros} erros`,
      processados,
      erros
    });

  } catch (error) {
    // console.error("[API] Erro na migração:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ========== ROTAS DO DASHBOARD DE COMPRAS ==========

// Buscar estatísticas gerais do dashboard de compras
app.get("/make-server-7249dcd9/empresas/:id/compras/stats", validarAcessoMiddleware("compras-fornecedores"), async (c) => {
  try {
    const empresaId = c.req.param("id");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }

    // Buscar fornecedores
    const todosFornecedores = await fornecedores.listarFornecedores(empresaId);
    const fornecedoresAtivos = todosFornecedores.filter(f => f.ativo);
    const fornecedoresInativos = todosFornecedores.filter(f => !f.ativo);

    // Buscar artigos
    const todosArtigos = await artigos.listarArtigos(empresaId);
    const artigosAtivos = todosArtigos.filter(a => a.ativo);
    const artigosInativos = todosArtigos.filter(a => !a.ativo);

    // Contar artigos sem fornecedor
    const artigosSemFornecedor = todosArtigos.filter(a => !a.fornecedorId || a.fornecedorId === '').length;

    // Calcular preço médio dos artigos
    const totalPrecos = todosArtigos.reduce((total, artigo) => {
      const precoCompra = artigo.precoCompra || 0;
      return total + precoCompra;
    }, 0);
    const precoMedioArtigo = todosArtigos.length > 0 ? totalPrecos / todosArtigos.length : 0;

    const stats = {
      totalFornecedores: todosFornecedores.length,
      fornecedoresAtivos: fornecedoresAtivos.length,
      fornecedoresInativos: fornecedoresInativos.length,
      totalArtigos: todosArtigos.length,
      artigosAtivos: artigosAtivos.length,
      artigosInativos: artigosInativos.length,
      artigosSemFornecedor: artigosSemFornecedor,
      precoMedioArtigo: precoMedioArtigo,
    };

    return c.json({ success: true, data: stats });
  } catch (error) {
    // console.error("[API] Erro ao buscar estatísticas de compras:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar artigos mais comprados para o dashboard
app.get("/make-server-7249dcd9/empresas/:id/compras/artigos-mais-comprados", validarAcessoMiddleware("compras-fornecedores"), async (c) => {
  try {
    const empresaId = c.req.param("id");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const todosArtigos = await artigos.listarArtigos(empresaId);

    // Ordenar por preço de compra (mais caros = mais importantes) e pegar os top 10
    const artigosMaisComprados = todosArtigos
      .filter(a => a.ativo && a.precoCompra > 0)
      .sort((a, b) => (b.precoCompra || 0) - (a.precoCompra || 0))
      .map(a => ({
        codigo: a.codigo,
        nome: a.nome,
        fornecedorNome: a.fornecedorNome || 'Sem fornecedor',
        precoCompra: a.precoCompra || 0,
      }))
      .slice(0, 10); // Top 10 artigos mais caros

    return c.json({ success: true, data: artigosMaisComprados });
  } catch (error) {
    // console.error("[API] Erro ao buscar artigos mais comprados:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar fornecedores mais utilizados
app.get("/make-server-7249dcd9/empresas/:id/compras/fornecedores-top", validarAcessoMiddleware("compras-fornecedores"), async (c) => {
  try {
    const empresaId = c.req.param("id");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const todosArtigos = await artigos.listarArtigos(empresaId);

    // Contar artigos por fornecedor
    const fornecedorCount: { [key: string]: { nome: string; count: number } } = {};

    todosArtigos.forEach(artigo => {
      if (artigo.fornecedorId && artigo.fornecedorNome) {
        if (!fornecedorCount[artigo.fornecedorId]) {
          fornecedorCount[artigo.fornecedorId] = {
            nome: artigo.fornecedorNome,
            count: 0,
          };
        }
        fornecedorCount[artigo.fornecedorId].count++;
      }
    });

    // Converter para array e ordenar
    const fornecedoresTop = Object.values(fornecedorCount)
      .map(f => ({
        fornecedorNome: f.nome,
        totalArtigos: f.count,
      }))
      .sort((a, b) => b.totalArtigos - a.totalArtigos)
      .slice(0, 5); // Top 5

    return c.json({ success: true, data: fornecedoresTop });
  } catch (error) {
    // console.error("[API] Erro ao buscar fornecedores mais utilizados:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar distribuição de estoque por tipo
app.get("/make-server-7249dcd9/empresas/:id/compras/estoque-por-tipo", validarAcessoMiddleware("compras-fornecedores"), async (c) => {
  try {
    const empresaId = c.req.param("id");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const todosArtigos = await artigos.listarArtigos(empresaId);

    // Agrupar por tipo
    const tipoCount: { [key: string]: { quantidade: number; valor: number } } = {
      'produto': { quantidade: 0, valor: 0 },
      'servico': { quantidade: 0, valor: 0 },
    };

    todosArtigos.forEach(artigo => {
      const tipo = artigo.tipo || 'produto';
      const estoque = artigo.estoqueAtual || 0;
      const precoCompra = artigo.precoCompra || 0;

      tipoCount[tipo].quantidade++;
      tipoCount[tipo].valor += estoque * precoCompra;
    });

    // Converter para array
    const estoquePorTipo = Object.entries(tipoCount).map(([tipo, data]) => ({
      tipo: tipo === 'produto' ? 'Produto' : 'Serviço',
      quantidade: data.quantidade,
      valor: data.valor,
    }));

    return c.json({ success: true, data: estoquePorTipo });
  } catch (error) {
    // console.error("[API] Erro ao buscar estoque por tipo:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ========== FIM ROTAS DO DASHBOARD DE COMPRAS ==========

// ========== ROTAS DE TRANSFERÃŠNCIAS ==========

// ðŸ”„ RESETAR STOCK-ARMAZEM COM BASE NOS ARTIGOS REAIS
app.post("/make-server-7249dcd9/stock-armazem/resetar-stocks/:empresaId", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");

    // console.log('[API] ðŸ”„ Iniciando RESET completo de stocks para:', empresaId);

    if (!empresaId) {
      return c.json({ success: false, error: "empresaId é obrigatório" }, 400);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }

    // 1. DELETAR TODOS os stocks antigos da empresa
    const todosStocksAntigos = await stockArmazem.listarStockPorEmpresa(empresaId);
    // console.log('[API] ðŸ—‘ï¸ Deletando', todosStocksAntigos.length, 'registros antigos...');

    for (const stock of todosStocksAntigos) {
      await stockArmazem.deletarStock(`stockarmazem_${stock.id.replace('stockarmazem_', '')}`);
    }

    // console.log('[API] âœ… Todos os registros antigos foram deletados');

    // 2. Buscar ARTIGOS REAIS da empresa
    const artigosLista = await artigos.listarArtigos(empresaId);
    // console.log('[API] ðŸ“¦ Artigos encontrados na tabela de artigos:', artigosLista.length);

    let criados = 0;
    let pulados = 0;

    // 3. Criar stocks CORRETOS baseados nos artigos reais
    for (const art of artigosLista) {
      // Pular artigos sem armazém ou com estoque negativo (mas permitir zero)
      if (!art.armazemId || (art.estoqueAtual !== undefined && art.estoqueAtual < 0)) {
        // console.log(`[API] â­ï¸ Pulando artigo ${art.codigo}: estoque=${art.estoqueAtual}, armazem=${art.armazemId}`);
        pulados++;
        continue;
      }

      // âœ… USAR UPSERT em vez de CRIAR para garantir que não duplica
      await stockArmazem.upsertStock({
        empresaId: empresaId,
        armazemId: art.armazemId,
        artigoId: art.id,
        quantidade: art.estoqueAtual || 0, // âœ… QUANTIDADE REAL DO ARTIGO (incluindo zero)
        quantidadeReservada: 0,
        custoMedio: art.precoCompra || 0,
        localizacao: '',
        lote: '',
      });

      // console.log(`[API] âœ… Stock criado/atualizado: ${art.codigo} â†’ ${art.estoqueAtual || 0} unidades no armazém ${art.armazemId}`);
      criados++;
    }

    // console.log('[API] ðŸŽ‰ RESET concluído!');
    // console.log(`[API] âœ… Stocks criados: ${criados}`);
    // console.log(`[API] â­ï¸ Artigos pulados: ${pulados}`);

    return c.json({
      success: true,
      message: `RESET concluído: ${criados} stocks criados, ${pulados} artigos pulados`,
      deletados: todosStocksAntigos.length,
      criados,
      pulados
    });
  } catch (error) {
    // console.error("[API] âŒ Erro ao resetar stocks:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ðŸ§¹ LIMPAR DUPLICADOS DE STOCK
app.post("/make-server-7249dcd9/stock-armazem/limpar-duplicados/:empresaId", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");

    // console.log('[API] ðŸ§¹ Iniciando limpeza de duplicados para:', empresaId);

    if (!empresaId) {
      return c.json({ success: false, error: "empresaId é obrigatório" }, 400);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }

    // 1. Buscar TODOS os stocks da empresa
    const todosStocks = await stockArmazem.listarStockPorEmpresa(empresaId);
    // console.log('[API] ðŸ“¦ Total de registros encontrados:', todosStocks.length);

    // 2. Agrupar por artigo + armazém
    const agrupados = new Map<string, typeof todosStocks>();

    for (const stock of todosStocks) {
      const chave = `${stock.artigoId}_${stock.armazemId}`;

      if (!agrupados.has(chave)) {
        agrupados.set(chave, []);
      }

      agrupados.get(chave)!.push(stock);
    }

    // console.log('[API] ðŸ“Š Grupos encontrados (artigo+armazém):', agrupados.size);

    let duplicadosRemovidos = 0;
    let consolidados = 0;

    // 3. Para cada grupo, consolidar
    for (const [chave, stocks] of agrupados.entries()) {
      if (stocks.length === 1) {
        // console.log(`[API] âœ… Grupo ${chave}: OK (1 registro)`);
        continue; // Não tem duplicados
      }

      // console.log(`[API] ðŸ” Grupo ${chave}: ${stocks.length} registros DUPLICADOS`);

      // Somar todas as quantidades
      const quantidadeTotal = stocks.reduce((sum, s) => sum + s.quantidade, 0);
      const quantidadeReservadaTotal = stocks.reduce((sum, s) => sum + (s.quantidadeReservada || 0), 0);

      // Pegar o mais recente como base
      const maisRecente = stocks.sort((a, b) =>
        new Date(b.atualizadoEm).getTime() - new Date(a.atualizadoEm).getTime()
      )[0];

      // console.log(`[API] ðŸ“Š Consolidando: ${stocks.length} registros â†’ Qtd total: ${quantidadeTotal}`);

      // Atualizar o mais recente com a quantidade SOMADA
      const stockConsolidado = {
        ...maisRecente,
        quantidade: quantidadeTotal,
        quantidadeReservada: quantidadeReservadaTotal,
        quantidadeDisponivel: quantidadeTotal - quantidadeReservadaTotal,
        atualizadoEm: new Date().toISOString(),
      };

      // Salvar o consolidado
      await kv.set(`stockarmazem_${maisRecente.id.replace('stockarmazem_', '')}`, stockConsolidado);

      // Deletar os duplicados (todos exceto o mais recente)
      for (const stock of stocks) {
        if (stock.id !== maisRecente.id) {
          await stockArmazem.deletarStock(`stockarmazem_${stock.id.replace('stockarmazem_', '')}`);
          duplicadosRemovidos++;
          // console.log(`[API] ðŸ—‘ï¸ Removido duplicado: ${stock.id}`);
        }
      }

      consolidados++;
    }

    // console.log('[API] ðŸŽ‰ Limpeza concluída!');
    // console.log(`[API] âœ… Grupos consolidados: ${consolidados}`);
    // console.log(`[API] ðŸ—‘ï¸ Duplicados removidos: ${duplicadosRemovidos}`);

    return c.json({
      success: true,
      message: `Limpeza concluída: ${consolidados} grupos consolidados, ${duplicadosRemovidos} duplicados removidos`,
      consolidados,
      duplicadosRemovidos,
      totalStocksAntes: todosStocks.length,
      totalStocksDepois: todosStocks.length - duplicadosRemovidos,
    });
  } catch (error) {
    // console.error("[API] Erro ao limpar duplicados:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ðŸ”„ MIGRAÃ‡ÃƒO: Sincronizar stocks de artigos para stock-armazem
app.post("/make-server-7249dcd9/stock-armazem/migrar-artigos/:empresaId", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }

    // console.log('[API] ðŸ”„ Iniciando migração de stocks para:', empresaId);

    if (!empresaId) {
      return c.json({ success: false, error: "empresaId é obrigatório" }, 400);
    }

    // Buscar todos os artigos da empresa
    const artigosLista = await artigos.listarArtigos(empresaId);
    // console.log('[API] ðŸ“¦ Artigos encontrados:', artigosLista.length);

    let migrados = 0;
    let pulados = 0;

    for (const art of artigosLista) {
      // Pular artigos sem armazém ou com estoque negativo (mas permitir zero)
      if (!art.armazemId || (art.estoqueAtual !== undefined && art.estoqueAtual < 0)) {
        pulados++;
        continue;
      }

      // Verificar se já existe stock-armazem para este artigo
      const stockExistente = await stockArmazem.buscarStockArtigoArmazem(empresaId, art.id, art.armazemId);

      if (stockExistente) {
        // console.log('[API] â­ï¸ Stock já existe para:', art.codigo);
        pulados++;
        continue;
      }

      // Criar registro de stock-armazem
      const novoStock = {
        empresaId: empresaId,
        armazemId: art.armazemId,
        artigoId: art.id,
        quantidade: art.estoqueAtual || 0, // âœ… Permitir zero
        custoMedio: art.precoCompra || 0,
        localizacao: '',
        lote: '',
      };

      await stockArmazem.criarStock(novoStock);
      // console.log('[API] âœ… Stock migrado para:', art.codigo, '-', art.estoqueAtual, 'unidades');
      migrados++;
    }

    // console.log('[API] ðŸŽ‰ Migração concluída:', migrados, 'migrados,', pulados, 'pulados');

    return c.json({
      success: true,
      message: `Migração concluída: ${migrados} artigos migrados, ${pulados} pulados`,
      migrados,
      pulados
    });
  } catch (error) {
    // console.error("[API] Erro ao migrar stocks:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Listar transferências
app.get("/make-server-7249dcd9/transferencias/:empresaId", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    // console.log(`[API] ðŸ”µ Listando transferências para empresa: ${empresaId}`);

    const artigoId = c.req.query("artigoId");
    const armazemOrigemId = c.req.query("armazemOrigemId");
    const armazemDestinoId = c.req.query("armazemDestinoId");
    const status = c.req.query("status");
    const dataInicio = c.req.query("dataInicio");
    const dataFim = c.req.query("dataFim");

    const filtros: any = {};
    if (artigoId) filtros.artigoId = artigoId;
    if (armazemOrigemId) filtros.armazemOrigemId = armazemOrigemId;
    if (armazemDestinoId) filtros.armazemDestinoId = armazemDestinoId;
    if (status) filtros.status = status;
    if (dataInicio) filtros.dataInicio = dataInicio;
    if (dataFim) filtros.dataFim = dataFim;

    // console.log(`[API] ðŸ“‹ Filtros aplicados:`, JSON.stringify(filtros, null, 2));

    const listaTransferencias = await transferencias.listarTransferencias(empresaId, filtros);

    // console.log(`[API] âœ… Transferências encontradas: ${listaTransferencias.length}`);
    // console.log(`[API] ðŸ“¦ Primeiras 2 transferências:`, JSON.stringify(listaTransferencias.slice(0, 2), null, 2));

    return c.json({ success: true, data: listaTransferencias });
  } catch (error) {
    // console.error("[API] âŒ Erro ao listar transferências:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// DEBUG: Listar todas as keys de transferências no KV
app.get("/make-server-7249dcd9/transferencias/debug/:empresaId", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    // console.log(`[API DEBUG] ðŸ” Listando todas as keys de transferências para: ${empresaId}`);

    const prefix = `transferencia:${empresaId}:`;
    const resultados = await kv.getByPrefixWithKeys(prefix);

    // console.log(`[API DEBUG] ðŸ“Š Total de resultados: ${resultados.length}`);
    // console.log(`[API DEBUG] ðŸ“¦ Resultados completos:`, JSON.stringify(resultados, null, 2));

    return c.json({
      success: true,
      total: resultados.length,
      prefix,
      resultados: resultados.map((r: any) => ({
        key: r.key,
        value: r.value
      }))
    });
  } catch (error) {
    // console.error("[API DEBUG] âŒ Erro:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar transferência por ID
app.get("/make-server-7249dcd9/transferencias/transferencia/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const transferencia = await transferencias.buscarTransferenciaPorId(id);

    if (!transferencia) {
      return c.json({ success: false, error: "Transferência não encontrada" }, 404);
    }

    const escopo = await verificarEscopoEmpresaRequest(c, transferencia.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }

    return c.json({ success: true, data: transferencia });
  } catch (error) {
    // console.error("[API] Erro ao buscar transferência:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Criar nova transferência
app.post("/make-server-7249dcd9/transferencias", async (c) => {
  try {
    const dados = await lerBodyJsonSeguro(c);
    const escopo = await verificarEscopoEmpresaRequest(c, dados.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    // console.log('[API] ðŸ”µ Criando transferência:', dados);

    const resultado = await transferencias.criarTransferencia(dados);

    if (!resultado.success) {
      return c.json({ success: false, error: resultado.error }, 400);
    }

    // console.log('[API] âœ… Transferência criada:', resultado.transferencia?.numero);

    return c.json({ success: true, data: resultado.transferencia });
  } catch (error) {
    // console.error("[API] âŒ Erro ao criar transferência:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Cancelar transferência
app.post("/make-server-7249dcd9/transferencias/:id/cancelar", async (c) => {
  try {
    const id = c.req.param("id");
    const transferenciaParaCancelar = await transferencias.buscarTransferenciaPorId(id);
    if (!transferenciaParaCancelar) {
      return c.json({ success: false, error: "Transferência não encontrada" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, transferenciaParaCancelar.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    // console.log('[API] ðŸ”µ Cancelando transferência:', id);

    const resultado = await transferencias.cancelarTransferencia(id);

    if (!resultado.success) {
      return c.json({ success: false, error: resultado.error }, 400);
    }

    console.log('[API] ï¿½ï¿½ï¿½ Transferência cancelada');

    return c.json({ success: true, message: "Transferência cancelada com sucesso" });
  } catch (error) {
    // console.error("[API] âŒ Erro ao cancelar transferência:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ========== FIM ROTAS DE TRANSFERÃŠNCIAS ==========

// ========== ROTAS DE INVENTÃRIOS FÃSICOS ==========

// Listar inventários
app.get("/make-server-7249dcd9/inventarios", async (c) => {
  try {
    const empresaId = c.req.query("empresaId");
    if (!empresaId) {
      return c.json({ success: false, error: "empresaId é obrigatório" }, 400);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }

    const armazemId = c.req.query("armazemId");
    const status = c.req.query("status");
    const dataInicio = c.req.query("dataInicio");
    const dataFim = c.req.query("dataFim");

    const inventarios = await inventariosModule.listarInventarios(empresaId, {
      armazemId,
      status,
      dataInicio,
      dataFim,
    });

    return c.json({ success: true, data: inventarios });
  } catch (error) {
    return c.json({ success: false, error: String(error) }, 500);
  }
});

// Buscar inventário por ID
app.get("/make-server-7249dcd9/inventarios/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const inventario = await inventariosModule.buscarInventarioPorId(id);

    if (!inventario) {
      return c.json({ success: false, error: "Inventário não encontrado" }, 404);
    }

    const escopo = await verificarEscopoEmpresaRequest(c, inventario.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }

    return c.json({ success: true, data: inventario });
  } catch (error) {
    return c.json({ success: false, error: String(error) }, 500);
  }
});

// Criar inventário
app.post("/make-server-7249dcd9/inventarios", async (c) => {
  try {
    const dados = await lerBodyJsonSeguro(c);
    const escopo = await verificarEscopoEmpresaRequest(c, dados?.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    if (dados?.empresaId && dados?.armazemId) {
      const referenciaArmazem = String(dados.armazemId).trim();
      const candidatosArmazem = Array.from(new Set([
        referenciaArmazem,
        referenciaArmazem.startsWith("armazem:") ? referenciaArmazem.slice("armazem:".length) : referenciaArmazem,
        referenciaArmazem.includes(" - ") ? referenciaArmazem.split(" - ")[0].trim() : referenciaArmazem,
      ].filter(Boolean)));

      let armazemResolvido: any = null;
      for (const candidato of candidatosArmazem) {
        armazemResolvido =
          await armazens.buscarArmazemPorId(candidato, dados.empresaId) ||
          await armazens.buscarArmazemPorCodigo(dados.empresaId, candidato);
        if (armazemResolvido) break;
      }

      if (!armazemResolvido) {
        const listaArmazens = await armazens.listarArmazens(dados.empresaId);
        const referenciaUpper = referenciaArmazem.toUpperCase();
        armazemResolvido = listaArmazens.find((arm: any) => {
          const codigo = String(arm.codigo || "").toUpperCase();
          const nome = String(arm.nome || "").toUpperCase();
          return (
            arm.id === referenciaArmazem ||
            `armazem:${arm.id}` === referenciaArmazem ||
            codigo === referenciaUpper ||
            nome === referenciaUpper ||
            `${codigo} - ${nome}` === referenciaUpper
          );
        });
      }

      if (armazemResolvido?.id) {
        dados.armazemId = armazemResolvido.id;
      }
    }

    const resultado = await inventariosModule.criarInventario(dados);

    if (!resultado.success) {
      return c.json({ success: false, error: resultado.error }, 400);
    }

    await registrarAuditoriaInventario(c, 'criar', resultado.inventario, {
      body: dados,
      extraResumo: {
        artigosSelecionados: Array.isArray(dados.artigosIds) ? dados.artigosIds.length : 'Todos com stock',
      },
      detalhes: `${(await obterUsuarioAuditoriaRequest(c, dados)).nome || 'Sistema'} criou inventario ${resultado.inventario?.numero} no ${nomeArmazemAuditoria(resultado.inventario)}. Tipo: ${resultado.inventario?.tipo}; responsavel: ${resultado.inventario?.responsavel || 'nao informado'}; artigos incluidos: ${resultado.inventario?.totalArtigos || resultado.inventario?.linhas?.length || 0}. ${textoLinhasInventario(resultado.inventario?.linhas || [], 8)}`,
    });

    return c.json({ success: true, data: resultado.inventario });
  } catch (error) {
    return c.json({ success: false, error: String(error) }, 500);
  }
});

// Atualizar inventário
app.put("/make-server-7249dcd9/inventarios/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const dados = await lerBodyJsonSeguro(c);
    const inventarioAntes = await inventariosModule.buscarInventarioPorId(id);
    if (!inventarioAntes) {
      return c.json({ success: false, error: "Inventário não encontrado" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, inventarioAntes.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }

    const resultado = await inventariosModule.atualizarInventario(id, dados);

    if (!resultado.success) {
      return c.json({ success: false, error: resultado.error }, 400);
    }

    await registrarAuditoriaInventario(c, 'editar', resultado.inventario, {
      body: dados,
      antes: inventarioAntes,
      detalhes: `${(await obterUsuarioAuditoriaRequest(c, { ...dados, empresaId: resultado.inventario?.empresaId || inventarioAntes?.empresaId })).nome || 'Sistema'} editou inventario ${resultado.inventario?.numero || id}. Campos alterados: ${auditoria.alteracoesParaTexto(auditoria.compararObjetosLegivel(inventarioAntes, resultado.inventario, { limite: 60 }))}`,
    });

    return c.json({ success: true, data: resultado.inventario });
  } catch (error) {
    return c.json({ success: false, error: String(error) }, 500);
  }
});

// Atualizar linha do inventário
app.put("/make-server-7249dcd9/inventarios/:id/linhas/:linhaId", async (c) => {
  try {
    const id = c.req.param("id");
    const linhaId = c.req.param("linhaId");
    const dados = await lerBodyJsonSeguro(c);
    const inventarioAntes = await inventariosModule.buscarInventarioPorId(id);
    if (!inventarioAntes) {
      return c.json({ success: false, error: "Inventário não encontrado" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, inventarioAntes.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }

    const resultado = await inventariosModule.atualizarLinhaInventario(id, linhaId, dados);

    if (!resultado.success) {
      return c.json({ success: false, error: resultado.error }, 400);
    }

    await registrarAuditoriaLinhaInventario(c, inventarioAntes, resultado.inventario, linhaId, dados);

    return c.json({ success: true, data: resultado.inventario });
  } catch (error) {
    return c.json({ success: false, error: String(error) }, 500);
  }
});

// Iniciar contagem (transição RASCUNHO â†’ EM_CONTAGEM)
app.post("/make-server-7249dcd9/inventarios/:id/iniciar-contagem", async (c) => {
  try {
    const id = c.req.param("id");
    const inventarioAntes = await inventariosModule.buscarInventarioPorId(id);
    if (!inventarioAntes) {
      return c.json({ success: false, error: "Inventário não encontrado" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, inventarioAntes.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }

    const resultado = await inventariosModule.iniciarContagem(id);

    if (!resultado.success) {
      return c.json({ success: false, error: resultado.error }, 400);
    }

    await registrarAuditoriaInventario(c, 'iniciar_contagem', resultado.inventario, {
      antes: inventarioAntes,
      detalhes: `${(await obterUsuarioAuditoriaRequest(c, { empresaId: resultado.inventario?.empresaId || inventarioAntes?.empresaId })).nome || 'Sistema'} iniciou a contagem do inventario ${resultado.inventario?.numero || id}. O inventario passou de rascunho para em contagem e ficou pronto para registar as quantidades fisicas.`,
    });

    return c.json({ success: true, inventario: resultado.inventario, message: "Contagem iniciada com sucesso" });
  } catch (error) {
    return c.json({ success: false, error: String(error) }, 500);
  }
});

// Finalizar inventário (aplicar ajustes)
app.post("/make-server-7249dcd9/inventarios/:id/finalizar", async (c) => {
  try {
    const id = c.req.param("id");
    const inventarioAntes = await inventariosModule.buscarInventarioPorId(id);
    if (!inventarioAntes) {
      return c.json({ success: false, error: "Inventário não encontrado" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, inventarioAntes.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const ajustes = (inventarioAntes?.linhas || []).filter((linha: any) => Number(linha.diferenca || 0) !== 0);
    const entradas = ajustes.filter((linha: any) => Number(linha.diferenca || 0) > 0).length;
    const saidas = ajustes.filter((linha: any) => Number(linha.diferenca || 0) < 0).length;

    const resultado = await inventariosModule.finalizarInventario(id);

    if (!resultado.success) {
      return c.json({ success: false, error: resultado.error }, 400);
    }

    const inventarioDepois = await inventariosModule.buscarInventarioPorId(id);
    await registrarAuditoriaInventario(c, 'finalizar_inventario', inventarioDepois || inventarioAntes, {
      antes: inventarioAntes,
      extraResumo: {
        ajustesAplicados: ajustes.length,
        entradas,
        saidas,
      },
      nivel: ajustes.some((linha: any) => Number(linha.diferenca || 0) < 0) ? 'aviso' : 'info',
      detalhes: `${(await obterUsuarioAuditoriaRequest(c, { empresaId: inventarioAntes?.empresaId })).nome || 'Sistema'} finalizou inventario ${inventarioAntes?.numero || id}. Foram aplicados ${ajustes.length} ajuste(s) de stock: ${entradas} entrada(s) e ${saidas} saida(s). ${textoLinhasInventario(ajustes, 10)}`,
    });

    const resultadoContabilidadeInventario = await contabilizarMovimentosStockDocumento(
      inventarioDepois?.empresaId || inventarioAntes?.empresaId,
      inventarioDepois?.numero || inventarioAntes?.numero,
      'Inventario Fisico',
      { criadoPor: inventarioDepois?.responsavel || inventarioAntes?.responsavel },
    );

    // ✅ Antes disto o resultado da contabilizacao era so anexado ao campo
    // "contabilidade" da resposta e o success do topo ficava sempre true,
    // mesmo quando resultadoContabilidadeInventario.success===false — o
    // frontend so olha para data.success, por isso uma falha (ex: mapeamento
    // em falta) ficava invisivel e sem registo de pendencia. Agora usa o
    // mesmo mecanismo (anexarResultadoContabilidade + responderDocumentoIntegrado)
    // ja usado por facturas/VD/notas para registar a pendencia e avisar o utilizador.
    const inventarioComContabilidade = await anexarResultadoContabilidade(
      inventarioDepois || inventarioAntes,
      { movimentosStock: resultadoContabilidadeInventario },
    );

    return responderDocumentoIntegrado(c, inventarioComContabilidade);
  } catch (error) {
    return c.json({ success: false, error: String(error) }, 500);
  }
});

// Cancelar inventário
app.post("/make-server-7249dcd9/inventarios/:id/cancelar", async (c) => {
  try {
    const id = c.req.param("id");
    const inventarioAntes = await inventariosModule.buscarInventarioPorId(id);
    if (!inventarioAntes) {
      return c.json({ success: false, error: "Inventário não encontrado" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, inventarioAntes.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }

    const resultado = await inventariosModule.cancelarInventario(id);

    if (!resultado.success) {
      return c.json({ success: false, error: resultado.error }, 400);
    }

    await registrarAuditoriaInventario(c, 'cancelar', { ...inventarioAntes, status: 'cancelado' }, {
      antes: inventarioAntes,
      nivel: 'aviso',
      detalhes: `${(await obterUsuarioAuditoriaRequest(c, { empresaId: inventarioAntes?.empresaId })).nome || 'Sistema'} cancelou inventario ${inventarioAntes?.numero || id}. Nenhum ajuste de stock foi aplicado por esta acao.`,
    });

    return c.json({ success: true, message: "Inventario cancelado" });
  } catch (error) {
    return c.json({ success: false, error: String(error) }, 500);
  }
});

// Excluir inventário
app.delete("/make-server-7249dcd9/inventarios/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const inventarioAntes = await inventariosModule.buscarInventarioPorId(id);
    if (!inventarioAntes) {
      return c.json({ success: false, error: "Inventário não encontrado" }, 404);
    }
    const escopo = await verificarEscopoEmpresaRequest(c, inventarioAntes.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }

    const resultado = await inventariosModule.excluirInventario(id);

    if (!resultado.success) {
      return c.json({ success: false, error: resultado.error }, 400);
    }

    await registrarAuditoriaInventario(c, 'deletar', inventarioAntes, {
      nivel: 'aviso',
      detalhes: `${(await obterUsuarioAuditoriaRequest(c, { empresaId: inventarioAntes?.empresaId })).nome || 'Sistema'} eliminou inventario ${inventarioAntes?.numero || id}. O registo do inventario foi removido do sistema.`,
    });

    return c.json({ success: true, message: "Inventario excluido" });
  } catch (error) {
    return c.json({ success: false, error: String(error) }, 500);
  }
});

// ========== FIM ROTAS DE INVENTÃRIOS ==========

// ðŸ” DEBUG: Verificar inconsistências de stock
app.get("/make-server-7249dcd9/debug/inconsistencias-stock/:empresaId", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const acessoInconsistencias = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!acessoInconsistencias.permitido) {
      return c.json({ success: false, error: acessoInconsistencias.error }, acessoInconsistencias.status as any);
    }
    // console.log(`[API DEBUG] ðŸ” Verificando inconsistências de stock para empresa ${empresaId}...`);

    // Buscar todos os artigos da empresa
    const todosArtigos = await artigos.listarArtigos(empresaId);
    const artigosProduto = todosArtigos.filter(a => a.tipo === 'produto');

    const inconsistencias = [];

    for (const artigo of artigosProduto) {
      // Obter stock total baseado nos armazéns
      const stockTotal = await stockArmazem.obterStockTotalArtigo(empresaId, artigo.id);

      // Buscar stocks nos armazéns
      const stocksArmazens = await stockArmazem.listarArmazensPorArtigo(artigo.id);

      // Buscar movimentos
      const movimentos = await movimentosStock.listarMovimentos(empresaId, { artigoId: artigo.id });
      const totalEntradas = movimentos.filter(m => m.tipo === 'entrada').reduce((sum, m) => sum + m.quantidade, 0);
      const totalSaidas = movimentos.filter(m => m.tipo === 'saida').reduce((sum, m) => sum + m.quantidade, 0);
      const saldoMovimentos = totalEntradas - totalSaidas;

      // Verificar se há inconsistência
      const estoqueAtual = artigo.estoqueAtual || 0;

      if (estoqueAtual !== stockTotal || estoqueAtual !== saldoMovimentos) {
        inconsistencias.push({
          artigo: {
            id: artigo.id,
            codigo: artigo.codigo,
            nome: artigo.nome,
          },
          estoqueArtigo: estoqueAtual,
          stockArmazens: stockTotal,
          saldoMovimentos,
          armazens: stocksArmazens.map(s => ({
            armazemId: s.armazemId,
            quantidade: s.quantidade,
          })),
          movimentos: {
            entradas: totalEntradas,
            saidas: totalSaidas,
            total: movimentos.length,
          },
          inconsistente: true,
        });
      }
    }

    // console.log(`[API DEBUG] âœ… Verificação concluída: ${inconsistencias.length} inconsistências encontradas`);

    return c.json({
      success: true,
      total: artigosProduto.length,
      inconsistencias: inconsistencias.length,
      detalhes: inconsistencias,
    });
  } catch (error) {
    console.error("[API DEBUG] âŒ Erro ao verificar inconsistências:", error);
    return c.json({ success: false, error: String(error) }, 500);
  }
});

// ðŸ—‘ï¸ DEBUG: Eliminar TODOS os movimentos de stock de uma empresa
app.delete("/make-server-7249dcd9/debug/limpar-movimentos/:empresaId", async (c) => {
  try {
    const acessoLimparMovStock = await validarSuperAdminTonlineRequest(c);
    if (!acessoLimparMovStock.permitido) return acessoLimparMovStock.resposta;

    const empresaId = c.req.param("empresaId");
    console.log(`[API DEBUG] ðŸ—‘ï¸ Eliminando TODOS os movimentos de stock para empresa ${empresaId}...`);

    // Buscar todos os movimentos da empresa
    const todosMovimentos = await kv.getByPrefix("movimento_stock:");
    const movimentosDaEmpresa = todosMovimentos.filter((m: any) => m.empresaId === empresaId);

    console.log(`[API DEBUG] ðŸ“Š Total de movimentos encontrados: ${movimentosDaEmpresa.length}`);

    // Eliminar cada movimento
    let eliminados = 0;
    for (const movimento of movimentosDaEmpresa) {
      await kv.del(`movimento_stock:${movimento.id}`);
      await kv.del(`movimento_stock:${movimento.empresaId}:${movimento.id}`);
      eliminados++;
    }

    console.log(`[API DEBUG] âœ… ${eliminados} movimentos eliminados com sucesso!`);

    return c.json({
      success: true,
      movimentosEliminados: eliminados,
      message: `${eliminados} movimentos de stock eliminados com sucesso`,
    });
  } catch (error) {
    console.error("[API DEBUG] âŒ Erro ao eliminar movimentos:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ðŸ”„ RECALCULAR STOCKS TOTAIS DOS ARTIGOS BASEADO NOS ARMAZÃ‰NS
app.post("/make-server-7249dcd9/artigos/recalcular-stocks/:empresaId", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const acessoRecalcular = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!acessoRecalcular.permitido) {
      return c.json({ success: false, error: acessoRecalcular.error }, acessoRecalcular.status as any);
    }
    // console.log(`[API] ðŸ”„ Recalculando stocks totais para empresa ${empresaId}...`);

    // Buscar todos os artigos da empresa
    const todosArtigos = await artigos.listarArtigos(empresaId);
    const artigosProduto = todosArtigos.filter(a => a.tipo === 'produto');

    // console.log(`[API] ðŸ“¦ ${artigosProduto.length} produtos encontrados`);

    let atualizados = 0;
    let erros = 0;
    const detalhes = [];

    for (const artigo of artigosProduto) {
      try {
        // Obter stock total do artigo baseado na soma de todos os armazéns
        const stockTotal = await stockArmazem.obterStockTotalArtigo(empresaId, artigo.id);

        // Atualizar o campo estoqueAtual do artigo
        const resultado = await artigos.atualizarEstoque(artigo.id, stockTotal, 'definir');

        if (resultado.success) {
          atualizados++;
          detalhes.push({
            codigo: artigo.codigo,
            nome: artigo.nome,
            stockAnterior: artigo.estoqueAtual || 0,
            stockNovo: stockTotal,
            diferenca: stockTotal - (artigo.estoqueAtual || 0)
          });
          // console.log(`[API] âœ… ${artigo.codigo}: ${artigo.estoqueAtual || 0} â†’ ${stockTotal}`);
        } else {
          erros++;
          // console.error(`[API] âŒ Erro ao atualizar ${artigo.codigo}:`, resultado.error);
        }
      } catch (error) {
        erros++;
        // console.error(`[API] âŒ Erro ao processar ${artigo.codigo}:`, error);
      }
    }

    // console.log(`[API] âœ… Recalculação concluída: ${atualizados} atualizados, ${erros} erros`);

    return c.json({
      success: true,
      message: `Stocks recalculados com sucesso!`,
      atualizados,
      erros,
      total: artigosProduto.length,
      detalhes
    });
  } catch (error) {
    // console.error("[API] âŒ Erro ao recalcular stocks:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ðŸ”§ CORRIGIR STOCKS BASEADO NOS MOVIMENTOS (fonte da verdade)
app.post("/make-server-7249dcd9/artigos/corrigir-stocks-movimentos/:empresaId", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const acessoCorrigirStocks = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!acessoCorrigirStocks.permitido) {
      return c.json({ success: false, error: acessoCorrigirStocks.error }, acessoCorrigirStocks.status as any);
    }
    // console.log(`[API] ðŸ”§ CORREÃ‡ÃƒO DE STOCKS baseada em movimentos para empresa ${empresaId}...`);

    // Buscar todos os artigos da empresa
    const todosArtigos = await artigos.listarArtigos(empresaId);
    const artigosProduto = todosArtigos.filter(a => a.tipo === 'produto');

    // console.log(`[API] ðŸ“¦ ${artigosProduto.length} produtos encontrados`);

    let artigosCorrigidos = 0;
    let armazensCriados = 0;
    let erros = 0;
    const detalhes = [];

    for (const artigo of artigosProduto) {
      try {
        // console.log(`\n[API] ðŸ“¦ Processando artigo: ${artigo.codigo} - ${artigo.nome}`);

        // Buscar TODOS os movimentos deste artigo
        const movimentos = await movimentosStock.listarMovimentos(empresaId);
        const movimentosArtigo = movimentos.filter(m => m.artigoId === artigo.id);

        // console.log(`[API] ðŸ“Š ${movimentosArtigo.length} movimentos encontrados`);

        if (movimentosArtigo.length === 0) {
          // console.log(`[API] âš ï¸  Nenhum movimento encontrado, pulando...`);
          continue;
        }

        // Agrupar movimentos por armazém
        const movimentosPorArmazem = new Map();

        for (const mov of movimentosArtigo) {
          const armazemId = mov.armazemId;
          if (!armazemId) continue;

          if (!movimentosPorArmazem.has(armazemId)) {
            movimentosPorArmazem.set(armazemId, []);
          }
          movimentosPorArmazem.get(armazemId).push(mov);
        }

        // console.log(`[API] ðŸ¢ Armazéns com movimentos: ${movimentosPorArmazem.size}`);

        let stockTotalRecalculado = 0;

        // Para cada armazém, recalcular o stock baseado nos movimentos
        for (const [armazemId, movs] of movimentosPorArmazem.entries()) {
          let stockNoArmazem = 0;

          for (const mov of movs) {
            if (mov.tipo === 'entrada') {
              stockNoArmazem += mov.quantidade;
            } else if (mov.tipo === 'saida') {
              stockNoArmazem -= mov.quantidade;
            }
          }

          // console.log(`[API]   - Armazém ${armazemId}: ${stockArmazem} unidades (${movs.length} movimentos)`);

          // Atualizar stock por armazém com o formato canónico atual
          await stockArmazem.upsertStock({
            empresaId,
            artigoId: artigo.id,
            armazemId,
            quantidade: stockNoArmazem,
          });

          armazensCriados++;
          stockTotalRecalculado += stockNoArmazem;
        }

        // console.log(`[API] ðŸ“Š Stock total recalculado: ${stockTotalRecalculado}`);

        // Atualizar o artigo com o stock correto
        const resultado = await artigos.atualizarEstoque(artigo.id, stockTotalRecalculado, 'definir');

        if (resultado.success) {
          artigosCorrigidos++;
          detalhes.push({
            codigo: artigo.codigo,
            nome: artigo.nome,
            stockAnterior: artigo.estoqueAtual || 0,
            stockNovo: stockTotalRecalculado,
            diferenca: stockTotalRecalculado - (artigo.estoqueAtual || 0),
            armazens: movimentosPorArmazem.size
          });
          // console.log(`[API] âœ… ${artigo.codigo}: ${artigo.estoqueAtual || 0} â†’ ${stockTotalRecalculado}`);
        } else {
          erros++;
          // console.error(`[API] ï¿½ï¿½ï¿½ Erro ao atualizar ${artigo.codigo}:`, resultado.error);
        }
      } catch (error) {
        erros++;
        // console.error(`[API] âŒ Erro ao processar ${artigo.codigo}:`, error);
      }
    }

    console.log(`[API] âœ… CORREÃ‡ÃƒO CONCLUÃDA:`);
    console.log(`[API]   - ${artigosCorrigidos} artigos corrigidos`);
    console.log(`[API]   - ${armazensCriados} registros de armazém criados/atualizados`);
    console.log(`[API]   - ${erros} erros`);

    return c.json({
      success: true,
      message: `Stocks corrigidos baseado nos movimentos!`,
      artigosCorrigidos,
      armazensCriados,
      erros,
      total: artigosProduto.length,
      detalhes
    });
  } catch (error) {
    // console.error("[API] âŒ Erro ao corrigir stocks:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ========== ROTAS DE VENDAS A DINHEIRO (VD) ==========

// Listar VDs de uma empresa
app.get("/make-server-7249dcd9/empresas/:id/vendas-dinheiro", validarAcessoMiddleware("faturacao-vendas"), async (c) => {
  try {
    const empresaId = c.req.param("id");
    const result = await vendasDinheiro.getVDsByEmpresa(empresaId);

    if (!result.success) {
      return c.json({ success: false, error: result.error }, 500);
    }

    return responderListaPaginada(c, Array.isArray(result.data) ? result.data : []);
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar VD por ID
app.get("/make-server-7249dcd9/vendas-dinheiro/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const result = await vendasDinheiro.getVDById(id);

    if (!result.success) {
      return c.json({ success: false, error: result.error }, 404);
    }

    return c.json({ success: true, data: result.data });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Criar VD (rota genérica - mantida por compatibilidade)
app.post("/make-server-7249dcd9/vendas-dinheiro", async (c) => {
  try {
    const dadosVD = await lerBodyJsonSeguro(c);
    await preencherUsuarioDocumento(c, dadosVD, 'criar');
    // ✅ Ver nota em /facturas-recibo — a pre-validacao tem de usar os totais
    // calculados pelo servidor, nao os que o formulario enviou.
    const dadosVDPrevalidados = await aplicarTotaisFiscais(dadosVD, { permitirIsencaoGenerica: true });
    const prevalidacaoContabilidadeVD = await contabilizarDocumentoFiscalOperacional(
      {
        ...dadosVDPrevalidados,
        id: dadosVD.id || `prevalidacao_vd_${Date.now()}`,
        numeroDocumento: dadosVD.numeroDocumento || 'Venda a Dinheiro em preparacao',
      },
      'venda_dinheiro',
      { previsualizar: true },
    );
    const erroContabilidadeVD = respostaErroContabilidadeObrigatoria(prevalidacaoContabilidadeVD, 'venda a dinheiro');
    if (erroContabilidadeVD) {
      return c.json(erroContabilidadeVD, 400);
    }

    const result = await vendasDinheiro.criarVendaDinheiro(dadosVD);

    if (!result.success) {
      return c.json({ success: false, error: result.error }, 500);
    }

    const resultadoContabilidadeVD = await contabilizarDocumentoFiscalOperacional(result.data, 'venda_dinheiro');
    const resultadoCMVVD = await contabilizarMovimentosStockDocumento(
      result.data?.empresaId,
      result.data?.numeroDocumento,
      'Venda a Dinheiro',
      { criadoPor: dadosVD.criadoPor || dadosVD.usuarioAuditoriaId },
    );
    const resultadoInterempresaVD = await sincronizarCompraInterempresaVenda(result.data, 'venda_dinheiro');
    const vdComContabilidade = await anexarResultadoContabilidade(result.data, {
      venda: resultadoContabilidadeVD,
      cmvmc: resultadoCMVVD,
      interempresa: resultadoInterempresaVD,
      ...movimentosVDParaPendencia(result.data),
    });

    return responderDocumentoIntegrado(c, vdComContabilidade);
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Criar VD por empresa (rota específica usada pelo VDForm)
app.post("/make-server-7249dcd9/empresas/:empresaId/vendas-dinheiro", validarAcessoMiddleware("faturacao-vendas"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const dadosVD = await lerBodyJsonSeguro(c);
    await preencherUsuarioDocumento(c, dadosVD, 'criar');

    // Garantir que o empresaId do payload coincide com o da rota
    dadosVD.empresaId = empresaId;

    // ✅ Ver nota em /facturas-recibo — a pre-validacao tem de usar os totais
    // calculados pelo servidor, nao os que o formulario enviou.
    const dadosVDEmpresaPrevalidados = await aplicarTotaisFiscais(dadosVD, { permitirIsencaoGenerica: true });
    const prevalidacaoContabilidadeVDEmpresa = await contabilizarDocumentoFiscalOperacional(
      {
        ...dadosVDEmpresaPrevalidados,
        id: dadosVD.id || `prevalidacao_vd_${Date.now()}`,
        numeroDocumento: dadosVD.numeroDocumento || 'Venda a Dinheiro em preparacao',
      },
      'venda_dinheiro',
      { previsualizar: true },
    );
    const erroContabilidadeVDEmpresa = respostaErroContabilidadeObrigatoria(
      prevalidacaoContabilidadeVDEmpresa,
      'venda a dinheiro',
    );
    if (erroContabilidadeVDEmpresa) {
      return c.json(erroContabilidadeVDEmpresa, 400);
    }

    console.log("[VD POST] Criando VD para empresa:", empresaId);
    const result = await vendasDinheiro.criarVendaDinheiro(dadosVD);

    if (!result.success) {
      return c.json({ success: false, error: result.error }, 500);
    }

    // ✅ Contabilidade, movimentos de stock (CMV) e sincronizacao interempresa
    // NAO correm neste pedido. Medido em producao: tentar "correr em segundo
    // plano" dentro do mesmo pedido (mesmo com EdgeRuntime.waitUntil) nao
    // acelera a resposta ao POS -- o Supabase Edge Runtime so fecha a ligacao
    // HTTP depois de toda a invocacao terminar. Em vez disso, fica so
    // registado numa fila leve (uma escrita rapida) e um cron processa-o a
    // parte minutos depois (ver /vendas-dinheiro/processar-pendencias e a
    // migracao SQL do agendamento). O operador do POS so espera pela venda
    // em si.
    await vendasDinheiro.enfileirarProcessamentoVD(result.data, {
      criadoPor: dadosVD.criadoPor || dadosVD.usuarioAuditoriaId,
    });

    return c.json({ success: true, data: result.data });
  } catch (error) {
    console.error("[VD POST] Erro:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Chamada pelo cron (com X-Vd-Pendencias-Secret, sem sessao de utilizador)
// para terminar, a parte do pedido do POS, a contabilidade/CMV/sincronizacao
// interempresa das Vendas a Dinheiro criadas recentemente. Ver
// vendasDinheiro.enfileirarProcessamentoVD (onde a fila e alimentada) e a
// migracao SQL "processar_pendencias_vd_automatico" (onde o agendamento e
// criado).
app.post("/make-server-7249dcd9/vendas-dinheiro/processar-pendencias", async (c) => {
  try {
    const segredoConfigurado = Deno.env.get("VD_PENDENCIAS_CRON_SECRET");
    const segredoFornecido = c.req.header("X-Vd-Pendencias-Secret");
    const autenticadoPorSegredo = !!segredoConfigurado && segredoFornecido === segredoConfigurado;

    if (!autenticadoPorSegredo) {
      const acesso = await validarSuperAdminTonlineRequest(c);
      if (!acesso.permitido) return acesso.resposta;
    }

    const fila = await vendasDinheiro.listarFilaProcessamentoVD();
    const resultados: Array<{ numeroDocumento: string; success: boolean; desistiu?: boolean }> = [];

    for (const { key, value: item } of fila) {
      try {
        const vd = await vendasDinheiro.getVDPorId(item.empresaId, item.documentoId);
        if (!vd) {
          // Documento ja nao existe (ex.: anulado e removido) — nada a processar.
          await vendasDinheiro.removerFilaProcessamentoVD(key);
          resultados.push({ numeroDocumento: item.numeroDocumento, success: true });
          continue;
        }

        const resultadoContabilidadeVDEmpresa = await contabilizarDocumentoFiscalOperacional(vd, 'venda_dinheiro');
        const resultadoCMVVDEmpresa = await contabilizarMovimentosStockDocumento(
          vd?.empresaId,
          vd?.numeroDocumento,
          'Venda a Dinheiro',
          { criadoPor: item.criadoPor },
        );
        const resultadoInterempresaVDEmpresa = await sincronizarCompraInterempresaVenda(vd, 'venda_dinheiro');
        await anexarResultadoContabilidade(vd, {
          venda: resultadoContabilidadeVDEmpresa,
          cmvmc: resultadoCMVVDEmpresa,
          interempresa: resultadoInterempresaVDEmpresa,
          ...movimentosVDParaPendencia(vd),
        });

        const falhou = [resultadoContabilidadeVDEmpresa, resultadoCMVVDEmpresa, resultadoInterempresaVDEmpresa]
          .some((resultado) => resultado && resultado.success === false);

        if (falhou) {
          const { desistir } = await vendasDinheiro.registarTentativaFilaProcessamentoVD(
            key,
            item,
            'Uma ou mais integracoes falharam — ver pendencia fiscal do documento',
          );
          resultados.push({ numeroDocumento: item.numeroDocumento, success: false, desistiu: desistir });
        } else {
          await vendasDinheiro.removerFilaProcessamentoVD(key);
          resultados.push({ numeroDocumento: item.numeroDocumento, success: true });
        }
      } catch (erro: any) {
        const { desistir } = await vendasDinheiro.registarTentativaFilaProcessamentoVD(key, item, String(erro?.message || erro));
        resultados.push({ numeroDocumento: item.numeroDocumento, success: false, desistiu: desistir });
      }
    }

    return c.json({ success: true, processados: resultados.length, resultados });
  } catch (error: any) {
    console.error("[VD PENDENCIAS] Erro:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Atualizar VD
app.put("/make-server-7249dcd9/vendas-dinheiro/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const dadosVD = await lerBodyJsonSeguro(c);

    console.log("ðŸ”µ [ROTA PUT] VD recebido:", {
      id,
      clienteId: dadosVD.clienteId,
      numeroItens: dadosVD.itens?.length,
    });

    const result = await vendasDinheiro.atualizarVD(id, dadosVD);

    console.log("ðŸ”µ [ROTA PUT] Resultado:", {
      success: result.success,
      temCliente: !!result.data?.cliente,
      clienteNome: result.data?.cliente?.nome,
    });

    if (!result.success) {
      return c.json({ success: false, error: result.error }, 500);
    }

    return c.json({ success: true, data: result.data });
  } catch (error) {
    console.error("âŒ [ROTA PUT] Erro:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Anular VD
app.post("/make-server-7249dcd9/vendas-dinheiro/:id/anular", async (c) => {
  try {
    const id = c.req.param("id");
    const { motivo } = await lerBodyJsonSeguro(c);

    const result = await vendasDinheiro.anularVD(id, motivo);

    if (!result.success) {
      return c.json({ success: false, error: result.error }, 500);
    }

    return c.json({ success: true, data: result.data });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Excluir VD
app.delete("/make-server-7249dcd9/vendas-dinheiro/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const body = await lerBodyJsonSeguro(c);
    await preencherUsuarioDocumento(c, body, 'editar');

    const result = await vendasDinheiro.excluirVD(id, {
      motivo: body.motivo,
      usuarioId: body.usuarioAuditoriaId,
      usuarioNome: body.usuarioAuditoriaNome,
      usuarioEmail: body.usuarioAuditoriaEmail,
    });

    if (!result.success) {
      return c.json({ success: false, error: result.error }, 400);
    }

    return c.json({ success: true, data: result.data, message: "VD eliminada e número libertado com sucesso" });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ðŸ”§ DEBUG: Diagnóstico de VD (verificar se cliente está sendo retornado)
app.get("/make-server-7249dcd9/debug/vd/:id", async (c) => {
  try {
    const acessoDebugVd = await validarSuperAdminTonlineRequest(c);
    if (!acessoDebugVd.permitido) return acessoDebugVd.resposta;

    const id = c.req.param("id");
    const result = await vendasDinheiro.getVDById(id);

    return c.json({
      success: result.success,
      vdId: id,
      temCliente: !!result.data?.cliente,
      clienteId: result.data?.clienteId,
      cliente: result.data?.cliente,
      numeroDocumento: result.data?.numeroDocumento,
      totalGeral: result.data?.totalGeral,
      timestamp: new Date().toISOString()
    });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ðŸ”§ DEBUG: Ver RAW da VD no banco
app.get("/make-server-7249dcd9/debug/vd-raw/:id", async (c) => {
  try {
    const acessoDebugVdRaw = await validarSuperAdminTonlineRequest(c);
    if (!acessoDebugVdRaw.permitido) return acessoDebugVdRaw.resposta;

    const id = c.req.param("id");
    const supabaseUrl = Deno.env.get("SUPABASE_URL") ?? "";
    const supabaseServiceKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? "";
    const supabase = createClient(supabaseUrl, supabaseServiceKey);

    // Buscar RAW do banco
    const { data, error } = await supabase
      .from("kv_store_7249dcd9")
      .select("*")
      .eq("key", id)
      .single();

    if (error) {
      console.error(`âŒ [DEBUG] VD ${id} não encontrada:`, error);
      return c.json({
        success: false,
        error: error.message,
        vdId: id,
        existeNoBanco: false,
        mensagem: 'Esta VD não existe no banco de dados. Ela pode ter sido excluída ou nunca foi salva corretamente.'
      });
    }

    return c.json({
      success: true,
      vdId: id,
      existeNoBanco: true,
      raw: data,
      value: data?.value,
      clienteIdNaVD: data?.value?.clienteId,
      temClienteIdSalvo: !!data?.value?.clienteId,
      timestamp: new Date().toISOString()
    });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ========== ROTAS DE ADIANTAMENTOS ==========

// Listar Adiantamentos de uma empresa
app.get("/make-server-7249dcd9/empresas/:id/adiantamentos", async (c) => {
  try {
    const empresaId = c.req.param("id");
    const result = await adiantamentos.getAdiantamentosByEmpresa(empresaId);

    if (!result.success) {
      return c.json({ success: false, error: result.error }, 500);
    }

    return responderListaPaginada(c, Array.isArray(result.data) ? result.data : []);
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar Adiantamentos disponíveis de um cliente - DUPLICADO REMOVIDO PARA EVITAR CONFLITOS (A rota já está definida acima)
// Removida pois a rota /make-server-7249dcd9/empresas/:empresaId/clientes/:clienteId/adiantamentos-disponiveis já existe
// Se houver chamadas dependentes desta versão específica, elas usarão a versão lá de cima que calcula o saldo.

// Buscar Adiantamento por ID
app.get("/make-server-7249dcd9/adiantamentos/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const result = await adiantamentos.getAdiantamentoById(id);

    if (!result.success) {
      return c.json({ success: false, error: result.error }, 404);
    }

    return c.json({ success: true, data: result.data });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Prever próximo número de adiantamento
app.get("/make-server-7249dcd9/empresas/:empresaId/adiantamentos/proximo-numero", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const dataReferencia = c.req.query("dataEmissao") || c.req.query("dataReferencia") || undefined;
    const exercicio = await exerciciosEconomicos.validarExercicioAberto(empresaId, dataReferencia, "adiantamento");
    const numeroDocumento = await adiantamentos.preverProximoNumeroAdiantamento(empresaId, exercicio.ano);
    return c.json({ success: true, data: { numeroDocumento } });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Criar Adiantamento
app.post("/make-server-7249dcd9/adiantamentos", async (c) => {
  try {
    const dadosAdiantamento = await lerBodyJsonSeguro(c);
    await preencherUsuarioDocumento(c, dadosAdiantamento, 'criar');

    const documentoAdiantamento = {
      ...dadosAdiantamento,
      totalGeral: Number(dadosAdiantamento.totalGeral ?? dadosAdiantamento.valor ?? 0),
      subtotal: Number(dadosAdiantamento.subtotal ?? dadosAdiantamento.valor ?? 0),
      id: dadosAdiantamento.id || `prevalidacao_adiantamento_${Date.now()}`,
      numeroDocumento: dadosAdiantamento.numeroDocumento || 'Adiantamento em preparação',
    };
    const prevalidacaoAdiantamento = await contabilizarDocumentoFiscalOperacional(
      documentoAdiantamento,
      'adiantamento',
      { previsualizar: true },
    );
    const erroPrevalidacaoAdiantamento = respostaErroContabilidadeObrigatoria(prevalidacaoAdiantamento, 'adiantamento');
    if (erroPrevalidacaoAdiantamento) return c.json(erroPrevalidacaoAdiantamento, 400);

    const result = await adiantamentos.criarAdiantamento(dadosAdiantamento);

    if (!result.success) {
      return c.json({ success: false, error: result.error }, 500);
    }

    const resultadoContabilidadeAdiantamento = await contabilizarDocumentoFiscalOperacional(
      {
        ...result.data,
        totalGeral: Number(result.data.totalGeral ?? result.data.valor ?? 0),
        subtotal: Number(result.data.subtotal ?? result.data.valor ?? 0),
      },
      'adiantamento',
    );
    const erroContabilidadeAdiantamento = respostaErroContabilidadeObrigatoria(
      resultadoContabilidadeAdiantamento,
      'adiantamento',
    );
    if (erroContabilidadeAdiantamento) {
      await adiantamentos.excluirAdiantamento(result.data.id, {
        motivo: 'Rollback interno: falha na contabilizacao obrigatoria.',
        origem: 'rollback-contabilidade',
      }).catch(() => null);
      return c.json({
        ...erroContabilidadeAdiantamento,
        error: `${erroContabilidadeAdiantamento.error}. O adiantamento nao foi emitido e a numeracao foi libertada.`,
      }, 500);
    }

    return c.json({ success: true, data: result.data });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// âœ… NOVO: Atualizar Adiantamento
app.get("/make-server-7249dcd9/adiantamentos/:id/pode-editar", async (c) => {
  try {
    const resultado = await adiantamentos.podeAlterarAdiantamento(c.req.param("id"), "editado");
    return c.json({ success: true, data: resultado });
  } catch (error) {
    return c.json({ success: false, error: error instanceof Error ? error.message : String(error) }, 500);
  }
});

app.get("/make-server-7249dcd9/adiantamentos/:id/pode-eliminar", async (c) => {
  try {
    const resultado = await adiantamentos.podeAlterarAdiantamento(c.req.param("id"), "eliminado");
    return c.json({ success: true, data: resultado });
  } catch (error) {
    return c.json({ success: false, error: error instanceof Error ? error.message : String(error) }, 500);
  }
});

app.put("/make-server-7249dcd9/adiantamentos/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const dadosAdiantamento = await lerBodyJsonSeguro(c);
    const result = await adiantamentos.atualizarAdiantamento(id, dadosAdiantamento);

    if (!result.success) {
      return c.json({ success: false, error: result.error }, 400);
    }

    return c.json({ success: true, data: result.data });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Aplicar Adiantamento em Fatura
app.post("/make-server-7249dcd9/adiantamentos/:id/aplicar", async (c) => {
  try {
    const id = c.req.param("id");
    const { facturaId, facturaNumero, valorAplicar } = await lerBodyJsonSeguro(c);

    const result = await adiantamentos.aplicarAdiantamentoEmFactura(
      id,
      facturaId,
      facturaNumero,
      valorAplicar
    );

    if (!result.success) {
      return c.json({ success: false, error: result.error }, 500);
    }

    return c.json({ success: true, data: result.data });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Aplicar Adiantamento em Recibo (NOVA ROTA)
app.post("/make-server-7249dcd9/adiantamentos/:id/aplicar-recibo", async (c) => {
  try {
    const id = c.req.param("id");
    const { reciboId, reciboNumero, valorAplicar } = await lerBodyJsonSeguro(c);

    const result = await adiantamentos.aplicarAdiantamentoEmRecibo(
      id,
      reciboId,
      reciboNumero,
      valorAplicar
    );

    if (!result.success) {
      return c.json({ success: false, error: result.error }, 500);
    }

    return c.json({ success: true, data: result.data });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Anular Adiantamento
app.post("/make-server-7249dcd9/adiantamentos/:id/anular", async (c) => {
  try {
    const id = c.req.param("id");
    const { motivo } = await lerBodyJsonSeguro(c);

    const result = await adiantamentos.anularAdiantamento(id, motivo);

    if (!result.success) {
      return c.json({ success: false, error: result.error }, 500);
    }

    return c.json({ success: true, data: result.data });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Excluir Adiantamento
app.delete("/make-server-7249dcd9/adiantamentos/:id", async (c) => {
  try {
    const id = c.req.param("id");
    const body = await lerBodyJsonSeguro(c);
    await preencherUsuarioDocumento(c, body, 'editar');
    const result = await adiantamentos.excluirAdiantamento(id, {
      motivo: body.motivo,
      usuarioId: body.usuarioAuditoriaId,
      usuarioNome: body.usuarioAuditoriaNome,
      usuarioEmail: body.usuarioAuditoriaEmail,
    });

    if (!result.success) {
      return c.json({ success: false, error: result.error }, 500);
    }

    return c.json({ success: true, message: "Adiantamento eliminado e numero libertado com sucesso" });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ðŸ”„ MIGRAR ADIANTAMENTOS ANTIGOS (pagamentos -> itens)
app.post("/make-server-7249dcd9/empresas/:empresaId/adiantamentos/migrar", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const result = await adiantamentos.migrarAdiantamentosAntigos(empresaId);

    if (!result.success) {
      return c.json({ success: false, error: result.error }, 500);
    }

    return c.json({ success: true, data: result.data });
  } catch (error) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ========== SAFT - EXPORTAÃ‡ÃƒO FISCAL ==========
app.route("/make-server-7249dcd9/saft", saftRouter);

// ========== RASCUNHOS - SISTEMA DE AUTO-SAVE ==========
app.route("/make-server-7249dcd9/rascunhos", rascunhosRouter);

// ========== SAFT SEED - DADOS DE TESTE ==========
// ðŸŒ± Rota para popular banco com dados de teste realistas
app.post("/make-server-7249dcd9/saft/seed", async (c) => {
  try {
    const { empresaId } = await lerBodyJsonSeguro(c, {});

    if (!empresaId) {
      return c.json({ success: false, error: "empresaId é obrigatório" }, 400);
    }

    await saftSeed.seedSaftTestData(empresaId);

    return c.json({
      success: true,
      message: "Dados de teste gerados com sucesso! Verifique os logs para detalhes.",
    });
  } catch (error: any) {
    console.error("[SAFT Seed] Erro:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.post("/make-server-7249dcd9/saft/clean-seed", async (c) => {
  try {
    const { empresaId } = await lerBodyJsonSeguro(c, {});

    if (!empresaId) {
      return c.json({ success: false, error: "empresaId é obrigatório" }, 400);
    }

    await saftSeed.cleanSaftTestData(empresaId);

    return c.json({
      success: true,
      message: "Dados de teste removidos com sucesso!",
    });
  } catch (error: any) {
    console.error("[SAFT Clean] Erro:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ========== ROTAS DE PERMISSÃ•ES E USUÃRIOS ==========

// Rotas /debug/verificar-empresaid, /debug/migrar-usuario, /debug/corrigir-tenant movidas para admin-router.tsx (admin-server-7249dcd9)
// âœ… NOVO: Debug de usuário específico (busca por nome ou email)
app.get("/make-server-7249dcd9/debug/usuario/:busca", async (c) => {
  try {
    const acessoDebugUsuario = await validarSuperAdminTonlineRequest(c);
    if (!acessoDebugUsuario.permitido) return acessoDebugUsuario.resposta;

    const busca = c.req.param("busca");
    console.log(`ðŸ” [DEBUG] Buscando usuário: ${busca}`);

    const supabase = createClient(
      Deno.env.get('SUPABASE_URL') ?? '',
      Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? ''
    );

    // Buscar todos os usuários
    const { data: todosUsuarios, error } = await supabase
      .from('kv_store_7249dcd9')
      .select('*')
      .like('key', 'usuario:%');

    if (error) {
      return c.json({ success: false, error: error.message }, 500);
    }

    // Filtrar por nome ou email
    const usuariosEncontrados = todosUsuarios?.filter((item: any) => {
      const usuario = item.value;
      return usuario.nome?.toLowerCase().includes(busca.toLowerCase()) ||
             usuario.email?.toLowerCase().includes(busca.toLowerCase());
    }) || [];

    console.log(`ðŸ“Š [DEBUG] Encontrados ${usuariosEncontrados.length} usuários`);

    // Formatar resposta detalhada
    const usuariosFormatados = usuariosEncontrados.map((item: any) => ({
      chave: item.key,
      dados: {
        id: item.value.id,
        empresaId: item.value.empresaId,
        authUserId: item.value.authUserId,
        nome: item.value.nome,
        email: item.value.email,
        nivel: item.value.nivel,
        permissoes: item.value.permissoes,
        permissoesModulos: item.value.permissoesModulos,
        modulosPermitidos: item.value.modulosPermitidos,
        ativo: item.value.ativo,
        dataCriacao: item.value.dataCriacao,
        criadoPor: item.value.criadoPor
      }
    }));

    return c.json({
      success: true,
      busca: busca,
      total: usuariosFormatados.length,
      usuarios: usuariosFormatados
    });
  } catch (error: any) {
    console.error('âŒ [DEBUG] Erro:', error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Rotas /debug/diagnosticar-usuario e /debug/reparar-usuario movidas para admin-router.tsx (admin-server-7249dcd9)

// âœ… NOVO: Buscar TODOS os usuários do sistema de permissÃµes (apenas Super Admin)
app.get("/make-server-7249dcd9/usuarios", async (c) => {
  try {
    const acessoListarUsuarios = await validarSuperAdminTonlineRequest(c);
    if (!acessoListarUsuarios.permitido) return acessoListarUsuarios.resposta;

    console.log('ðŸ” [/usuarios] Buscando todos os usuários do sistema de permissÃµes...');
    const result = await permissoes.buscarTodosUsuariosPermissoes();
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Buscar usuários de uma empresa (com sincronização automática)
// Rota GET /empresas/:empresaId/usuarios-permissoes movida para admin-router.tsx (admin-server-7249dcd9)
// Buscar usuário por Auth ID
// ✅ Usada por todos os utilizadores logo apos o login para carregar as
// suas proprias permissoes — so aceita a propria sessao (ou super-admin),
// nunca esteve protegida antes, o que deixava o perfil completo de
// qualquer utilizador (nivel, permissoes, empresaId) acessivel a quem
// soubesse o respectivo authUserId (UUID).
app.get("/make-server-7249dcd9/usuarios-permissoes/auth/:authUserId", async (c) => {
  try {
    const authUserId = c.req.param("authUserId");
    const chamador = await obterUsuarioAutenticadoRequest(c);

    if (!chamador) {
      return c.json({ success: false, error: "Sessao invalida ou expirada" }, 401);
    }

    if (chamador.authUserId !== authUserId && !isUsuarioSuperAdminTonline(chamador)) {
      return c.json({ success: false, error: "Nao tem permissao para consultar este utilizador" }, 403);
    }

    const result = await permissoes.buscarUsuarioPorAuthId(authUserId);
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.post("/make-server-7249dcd9/empresas/:empresaId/pos-supervisor/validar-codigo", async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const acessoPosSupervisor = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!acessoPosSupervisor.permitido) {
      return c.json({ success: false, error: acessoPosSupervisor.error }, acessoPosSupervisor.status as any);
    }
    const body = await c.req.json();
    const result = await permissoes.buscarSupervisorPorCodigo(empresaId, body.codigoSupervisor || body.codigo || "");
    return c.json(result, result.success ? 200 : 400);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Rotas /usuarios-permissoes/migrar-auth-ids, POST /usuarios-permissoes, PATCH permissoes/desativar/permissoes-modulos movidas para admin-router.tsx (admin-server-7249dcd9)

// Verificar se pode editar documento
app.post("/make-server-7249dcd9/verificar-permissao/editar", async (c) => {
  try {
    // Seguranca: o utilizador vem sempre do token da sessao, nunca do corpo do
    // pedido (um corpo com um "usuario" fabricado nao deve poder ser usado
    // para simular um utilizador com mais permissoes).
    const chamadorVerifEditar = await obterUsuarioAutenticadoRequest(c);
    if (!chamadorVerifEditar || chamadorVerifEditar.ativo === false) {
      return c.json({ success: false, error: "Utilizador nao autenticado" }, 401);
    }
    const body = await c.req.json();
    const { documentoId, tipoDocumento } = body;
    const result = await permissoes.verificarPodeEditar(chamadorVerifEditar, documentoId, tipoDocumento);
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Verificar se pode deletar documento
app.post("/make-server-7249dcd9/verificar-permissao/deletar", async (c) => {
  try {
    const chamadorVerifDeletar = await obterUsuarioAutenticadoRequest(c);
    if (!chamadorVerifDeletar || chamadorVerifDeletar.ativo === false) {
      return c.json({ success: false, error: "Utilizador nao autenticado" }, 401);
    }
    const body = await c.req.json();
    const { documentoId, tipoDocumento } = body;
    const result = await permissoes.verificarPodeDeletar(chamadorVerifDeletar, documentoId, tipoDocumento);
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ========== NOVA MATRIZ DE PERMISSÃ•ES ==========

// âœ… NOVO: Endpoint para retornar permissÃµes do usuário no formato da nova matriz
app.get("/make-server-7249dcd9/usuarios/permissoes/:usuarioId", async (c) => {
  try {
    const chamadorPermissoesUsuario = await obterUsuarioAutenticadoRequest(c);
    if (!chamadorPermissoesUsuario || chamadorPermissoesUsuario.ativo === false) {
      return c.json({ success: false, error: "Utilizador nao autenticado" }, 401);
    }
    const usuarioId = c.req.param("usuarioId");
    if (
      chamadorPermissoesUsuario.id !== usuarioId &&
      chamadorPermissoesUsuario.authUserId !== usuarioId &&
      !isUsuarioSuperAdminTonline(chamadorPermissoesUsuario)
    ) {
      return c.json({ success: false, error: "Nao tem permissao para consultar este utilizador" }, 403);
    }

    console.log('ðŸ” [/usuarios/permissoes/:usuarioId] Buscando permissÃµes para:', usuarioId);

    // Buscar usuário por diferentes critérios
    let usuario = null;

    // Tentar buscar por chave direta
    const chavesUsuario = await kv.getByPrefix('usuario:');
    for (const item of chavesUsuario) {
      if (item.key.includes('email:')) continue; // Pular índices de email

      const u = item.value;
      if (u.id === usuarioId || u.authUserId === usuarioId) {
        usuario = u;
        break;
      }
    }

    if (!usuario) {
      return c.json({
        success: false,
        error: 'Usuário não encontrado',
        permissions: []
      }, 404);
    }

    console.log('âœ… [/usuarios/permissoes/:usuarioId] Usuário encontrado:', {
      email: usuario.email,
      nivel: usuario.nivel,
      ativo: usuario.ativo,
      temPermissoesModulos: !!usuario.permissoesModulos
    });

    // Super Admin tem TODAS as permissÃµes
    if (usuario.nivel === 'super_admin') {
      return c.json({
        success: true,
        permissions: ['*'], // Wildcard = acesso total
        userLevel: 'super_admin'
      });
    }

    // Mapear permissÃµes para nova matriz
    const permissionsMap: Record<string, boolean> = {};

    // ========== PRIORIDADE 1: PERMISSÃ•ES POR MÃ“DULO (NOVA) ==========
    // Se existir permissoesModulos, ela tem PRIORIDADE sobre permissÃµes antigas
    if (usuario.permissoesModulos) {
      console.log('ðŸ“‹ [/usuarios/permissoes/:usuarioId] Mapeando permissoesModulos...');

      const modulosMap = usuario.permissoesModulos;

      // FATURAÃ‡ÃƒO
      if (modulosMap.faturacao) {
        if (modulosMap.faturacao.cotacao) {
          permissionsMap['faturacao.cotacao.criar'] = modulosMap.faturacao.cotacao.criar;
          permissionsMap['faturacao.cotacao.editar'] = modulosMap.faturacao.cotacao.editar;
          permissionsMap['faturacao.cotacao.deletar'] = modulosMap.faturacao.cotacao.deletar;
          permissionsMap['faturacao.cotacao.anular'] = modulosMap.faturacao.cotacao.anular;
          permissionsMap['faturacao.cotacao.visualizar'] = modulosMap.faturacao.cotacao.visualizar;
        }
        if (modulosMap.faturacao.factura) {
          permissionsMap['faturacao.factura.criar'] = modulosMap.faturacao.factura.criar;
          permissionsMap['faturacao.factura.editar'] = modulosMap.faturacao.factura.editar;
          permissionsMap['faturacao.factura.deletar'] = modulosMap.faturacao.factura.deletar;
          permissionsMap['faturacao.factura.anular'] = modulosMap.faturacao.factura.anular;
          permissionsMap['faturacao.factura.visualizar'] = modulosMap.faturacao.factura.visualizar;
        }
        if (modulosMap.faturacao.recibo) {
          permissionsMap['faturacao.recibo.criar'] = modulosMap.faturacao.recibo.criar;
          permissionsMap['faturacao.recibo.editar'] = modulosMap.faturacao.recibo.editar;
          permissionsMap['faturacao.recibo.deletar'] = modulosMap.faturacao.recibo.deletar;
          permissionsMap['faturacao.recibo.anular'] = modulosMap.faturacao.recibo.anular;
          permissionsMap['faturacao.recibo.visualizar'] = modulosMap.faturacao.recibo.visualizar;
        }
        if (modulosMap.faturacao.vd) {
          permissionsMap['faturacao.vd.criar'] = modulosMap.faturacao.vd.criar;
          permissionsMap['faturacao.vd.editar'] = modulosMap.faturacao.vd.editar;
          permissionsMap['faturacao.vd.deletar'] = modulosMap.faturacao.vd.deletar;
          permissionsMap['faturacao.vd.anular'] = modulosMap.faturacao.vd.anular;
          permissionsMap['faturacao.vd.visualizar'] = modulosMap.faturacao.vd.visualizar;
        }
        if (modulosMap.faturacao.notaCredito) {
          permissionsMap['faturacao.nota_credito.criar'] = modulosMap.faturacao.notaCredito.criar;
          permissionsMap['faturacao.nota_credito.editar'] = modulosMap.faturacao.notaCredito.editar;
          permissionsMap['faturacao.nota_credito.deletar'] = modulosMap.faturacao.notaCredito.deletar;
          permissionsMap['faturacao.nota_credito.anular'] = modulosMap.faturacao.notaCredito.anular;
          permissionsMap['faturacao.nota_credito.visualizar'] = modulosMap.faturacao.notaCredito.visualizar;
        }
        if (modulosMap.faturacao.notaDebito) {
          permissionsMap['faturacao.nota_debito.criar'] = modulosMap.faturacao.notaDebito.criar;
          permissionsMap['faturacao.nota_debito.editar'] = modulosMap.faturacao.notaDebito.editar;
          permissionsMap['faturacao.nota_debito.deletar'] = modulosMap.faturacao.notaDebito.deletar;
          permissionsMap['faturacao.nota_debito.anular'] = modulosMap.faturacao.notaDebito.anular;
          permissionsMap['faturacao.nota_debito.visualizar'] = modulosMap.faturacao.notaDebito.visualizar;
        }
      }

      // VENDAS
      if (modulosMap.vendas) {
        if (modulosMap.vendas.vendaDinheiro) {
          permissionsMap['vendas.vd.criar'] = modulosMap.vendas.vendaDinheiro.criar;
          permissionsMap['vendas.vd.editar'] = modulosMap.vendas.vendaDinheiro.editar;
          permissionsMap['vendas.vd.deletar'] = modulosMap.vendas.vendaDinheiro.deletar;
          permissionsMap['vendas.vd.anular'] = modulosMap.vendas.vendaDinheiro.anular;
          permissionsMap['vendas.vd.visualizar'] = modulosMap.vendas.vendaDinheiro.visualizar;
        }
        if (modulosMap.vendas.adiantamento) {
          permissionsMap['vendas.adiantamento.criar'] = modulosMap.vendas.adiantamento.criar;
          permissionsMap['vendas.adiantamento.editar'] = modulosMap.vendas.adiantamento.editar;
          permissionsMap['vendas.adiantamento.deletar'] = modulosMap.vendas.adiantamento.deletar;
          permissionsMap['vendas.adiantamento.anular'] = modulosMap.vendas.adiantamento.anular;
          permissionsMap['vendas.adiantamento.visualizar'] = modulosMap.vendas.adiantamento.visualizar;
        }
        // POS sempre acessível se tem permissão de vendas
        permissionsMap['vendas.pos.acessar'] = true;
      }

      // STOCK
      if (modulosMap.stock) {
        if (modulosMap.stock.movimentos) {
          permissionsMap['stock.movimento.criar'] = modulosMap.stock.movimentos.criar;
          permissionsMap['stock.movimento.editar'] = modulosMap.stock.movimentos.editar;
          permissionsMap['stock.movimento.deletar'] = modulosMap.stock.movimentos.deletar;
          permissionsMap['stock.movimento.visualizar'] = modulosMap.stock.movimentos.visualizar;
        }
        if (modulosMap.stock.transferencias) {
          permissionsMap['stock.transferencia.criar'] = modulosMap.stock.transferencias.criar;
          permissionsMap['stock.transferencia.editar'] = modulosMap.stock.transferencias.editar;
          permissionsMap['stock.transferencia.deletar'] = modulosMap.stock.transferencias.deletar;
          permissionsMap['stock.transferencia.visualizar'] = modulosMap.stock.transferencias.visualizar;
        }
        if (modulosMap.stock.inventario) {
          permissionsMap['stock.inventario.criar'] = modulosMap.stock.inventario.criar;
          permissionsMap['stock.inventario.editar'] = modulosMap.stock.inventario.editar;
          permissionsMap['stock.inventario.deletar'] = modulosMap.stock.inventario.deletar;
          permissionsMap['stock.inventario.visualizar'] = modulosMap.stock.inventario.visualizar;
        }
      }

      // COMPRAS
      if (modulosMap.compras) {
        if (modulosMap.compras.encomendaFornecedor) {
          permissionsMap['compras.encomenda.criar'] = modulosMap.compras.encomendaFornecedor.criar;
          permissionsMap['compras.encomenda.editar'] = modulosMap.compras.encomendaFornecedor.editar;
          permissionsMap['compras.encomenda.deletar'] = modulosMap.compras.encomendaFornecedor.deletar;
          permissionsMap['compras.encomenda.visualizar'] = modulosMap.compras.encomendaFornecedor.visualizar;
        }
        if (modulosMap.compras.entradaFornecedor) {
          permissionsMap['compras.entrada.criar'] = modulosMap.compras.entradaFornecedor.criar;
          permissionsMap['compras.entrada.editar'] = modulosMap.compras.entradaFornecedor.editar;
          permissionsMap['compras.entrada.deletar'] = modulosMap.compras.entradaFornecedor.deletar;
          permissionsMap['compras.entrada.visualizar'] = modulosMap.compras.entradaFornecedor.visualizar;
        }
      }

      // TERCEIROS
      if (modulosMap.terceiros) {
        if (modulosMap.terceiros.clientes) {
          permissionsMap['terceiros.cliente.criar'] = modulosMap.terceiros.clientes.criar;
          permissionsMap['terceiros.cliente.editar'] = modulosMap.terceiros.clientes.editar;
          permissionsMap['terceiros.cliente.deletar'] = modulosMap.terceiros.clientes.deletar;
          permissionsMap['terceiros.cliente.visualizar'] = modulosMap.terceiros.clientes.visualizar;
        }
        if (modulosMap.terceiros.fornecedores) {
          permissionsMap['terceiros.fornecedor.criar'] = modulosMap.terceiros.fornecedores.criar;
          permissionsMap['terceiros.fornecedor.editar'] = modulosMap.terceiros.fornecedores.editar;
          permissionsMap['terceiros.fornecedor.deletar'] = modulosMap.terceiros.fornecedores.deletar;
          permissionsMap['terceiros.fornecedor.visualizar'] = modulosMap.terceiros.fornecedores.visualizar;
        }
        if (modulosMap.terceiros.artigos) {
          permissionsMap['terceiros.artigo.criar'] = modulosMap.terceiros.artigos.criar;
          permissionsMap['terceiros.artigo.editar'] = modulosMap.terceiros.artigos.editar;
          permissionsMap['terceiros.artigo.deletar'] = modulosMap.terceiros.artigos.deletar;
          permissionsMap['terceiros.artigo.visualizar'] = modulosMap.terceiros.artigos.visualizar;
        }
        if (modulosMap.terceiros.armazens) {
          permissionsMap['terceiros.armazem.criar'] = modulosMap.terceiros.armazens.criar;
          permissionsMap['terceiros.armazem.editar'] = modulosMap.terceiros.armazens.editar;
          permissionsMap['terceiros.armazem.deletar'] = modulosMap.terceiros.armazens.deletar;
          permissionsMap['terceiros.armazem.visualizar'] = modulosMap.terceiros.armazens.visualizar;
        }
      }

      // RELATÃ“RIOS
      if (modulosMap.relatorios) {
        if (modulosMap.relatorios.contaCorrente) {
          permissionsMap['relatorios.conta_corrente.visualizar'] = modulosMap.relatorios.contaCorrente.visualizar;
        }
        if (modulosMap.relatorios.dividasAberto) {
          permissionsMap['relatorios.dividas_aberto.visualizar'] = modulosMap.relatorios.dividasAberto.visualizar;
        }
        if (modulosMap.relatorios.historicoDocumentos) {
          permissionsMap['relatorios.historico_documentos.visualizar'] = modulosMap.relatorios.historicoDocumentos.visualizar;
        }
        if (modulosMap.relatorios.pagamentosRecebidos) {
          permissionsMap['relatorios.pagamentos.visualizar'] = modulosMap.relatorios.pagamentosRecebidos.visualizar;
        }
        if (modulosMap.relatorios.limiteCredito) {
          permissionsMap['relatorios.limite_credito.visualizar'] = modulosMap.relatorios.limiteCredito.visualizar;
        }
        if (modulosMap.relatorios.mapaIdade) {
          permissionsMap['relatorios.mapa_idade.visualizar'] = modulosMap.relatorios.mapaIdade.visualizar;
        }
        if (modulosMap.relatorios.clientesInativos) {
          permissionsMap['relatorios.clientes_inativos.visualizar'] = modulosMap.relatorios.clientesInativos.visualizar;
        }
      }

      console.log('âœ… [/usuarios/permissoes/:usuarioId] Mapeadas permissÃµes de módulos');
    }

    // ========== PRIORIDADE 2: PERMISSÃ•ES ANTIGAS (FALLBACK) ==========
    // Apenas aplicar permissÃµes antigas se NÃƒO existir permissoesModulos

    // PermissÃµes genéricas
    if (usuario.permissoes?.criarDocumento && !usuario.permissoesModulos) {
      // Faturação
      permissionsMap['faturacao.cotacao.criar'] = true;
      permissionsMap['faturacao.factura.criar'] = true;
      permissionsMap['faturacao.recibo.criar'] = true;
      permissionsMap['faturacao.vd.criar'] = true;
      permissionsMap['faturacao.nota_credito.criar'] = true;
      permissionsMap['faturacao.nota_debito.criar'] = true;

      // Vendas
      permissionsMap['vendas.adiantamento.criar'] = true;

      // Stock
      permissionsMap['stock.movimento.criar'] = true;
      permissionsMap['stock.transferencia.criar'] = true;
      permissionsMap['stock.inventario.criar'] = true;

      // Compras
      permissionsMap['compras.encomenda.criar'] = true;
      permissionsMap['compras.entrada.criar'] = true;

      // Terceiros
      permissionsMap['terceiros.cliente.criar'] = true;
      permissionsMap['terceiros.fornecedor.criar'] = true;
      permissionsMap['terceiros.artigo.criar'] = true;

      // Contabilidade
      permissionsMap['contabilidade.lancamento.criar'] = true;
    }

    if (usuario.permissoes?.editarDocumentoPendente && !usuario.permissoesModulos) {
      permissionsMap['faturacao.cotacao.editar'] = true;
      permissionsMap['faturacao.factura.editar'] = true;
      permissionsMap['faturacao.recibo.editar'] = true;
      permissionsMap['faturacao.vd.editar'] = true;
      permissionsMap['faturacao.nota_credito.editar'] = true;
      permissionsMap['faturacao.nota_debito.editar'] = true;
      permissionsMap['vendas.adiantamento.editar'] = true;
      permissionsMap['stock.movimento.editar'] = true;
      permissionsMap['stock.transferencia.editar'] = true;
      permissionsMap['stock.inventario.editar'] = true;
      permissionsMap['compras.encomenda.editar'] = true;
      permissionsMap['compras.entrada.editar'] = true;
      permissionsMap['terceiros.cliente.editar'] = true;
      permissionsMap['terceiros.fornecedor.editar'] = true;
      permissionsMap['terceiros.artigo.editar'] = true;
      permissionsMap['contabilidade.lancamento.editar'] = true;
      permissionsMap['faturacao.cotacao.aprovar'] = true;
    }

    if (usuario.permissoes?.editarDocumentoEmitido) {
      permissionsMap['faturacao.factura.editar_emitida'] = true;
    }

    if (usuario.permissoes?.deletarDocumento && !usuario.permissoesModulos) {
      permissionsMap['faturacao.cotacao.deletar'] = true;
      permissionsMap['faturacao.factura.deletar'] = true;
      permissionsMap['faturacao.recibo.deletar'] = true;
      permissionsMap['faturacao.vd.deletar'] = true;
      permissionsMap['faturacao.nota_credito.deletar'] = true;
      permissionsMap['faturacao.nota_debito.deletar'] = true;
      permissionsMap['vendas.adiantamento.deletar'] = true;
      permissionsMap['stock.movimento.deletar'] = true;
      permissionsMap['stock.transferencia.deletar'] = true;
      permissionsMap['compras.encomenda.deletar'] = true;
      permissionsMap['compras.entrada.deletar'] = true;
      permissionsMap['terceiros.cliente.deletar'] = true;
      permissionsMap['terceiros.fornecedor.deletar'] = true;
      permissionsMap['terceiros.artigo.deletar'] = true;
      permissionsMap['contabilidade.lancamento.deletar'] = true;
    }

    if (usuario.permissoes?.anularDocumento && !usuario.permissoesModulos) {
      permissionsMap['faturacao.factura.anular'] = true;
      permissionsMap['faturacao.recibo.anular'] = true;
      permissionsMap['faturacao.vd.anular'] = true;
    }

    // PermissÃµes de sistema (sempre aplicar, não estão em módulos)
    if (usuario.permissoes?.configurarEmpresa) {
      permissionsMap['menu.config_empresa'] = true;
      permissionsMap['sistema.configurar_empresa'] = true;
      permissionsMap['menu.migrar_dados'] = true;
      permissionsMap['menu.gestao_modulos'] = true;
      permissionsMap['contabilidade.plano_contas.editar'] = true;
      // Se não tem permissoesModulos, dar acesso a armazéns
      if (!usuario.permissoesModulos) {
        permissionsMap['terceiros.armazem.criar'] = true;
        permissionsMap['terceiros.armazem.editar'] = true;
        permissionsMap['terceiros.armazem.deletar'] = true;
      }
    }

    if (usuario.permissoes?.concederPermissoes) {
      permissionsMap['menu.permissoes_utilizadores'] = true;
      permissionsMap['sistema.conceder_permissoes'] = true;
    }

    if (usuario.permissoes?.gerenciarUsuarios) {
      permissionsMap['sistema.gerenciar_usuarios'] = true;
    }

    if (usuario.permissoes?.visualizarLogs) {
      permissionsMap['menu.logs_auditoria'] = true;
      permissionsMap['sistema.visualizar_logs'] = true;
    }

    if (usuario.permissoes?.exportarSAFT) {
      permissionsMap['menu.exportar_saft'] = true;
    }

    // PermissÃµes de visualização (só dar automaticamente se NÃƒO tem permissoesModulos)
    if (!usuario.permissoesModulos) {
      permissionsMap['faturacao.cotacao.visualizar'] = true;
      permissionsMap['faturacao.factura.visualizar'] = true;
      permissionsMap['faturacao.recibo.visualizar'] = true;
      permissionsMap['faturacao.vd.visualizar'] = true;
      permissionsMap['faturacao.nota_credito.visualizar'] = true;
      permissionsMap['faturacao.nota_debito.visualizar'] = true;
      permissionsMap['vendas.adiantamento.visualizar'] = true;
      permissionsMap['vendas.pos.acessar'] = true;
      permissionsMap['stock.movimento.visualizar'] = true;
      permissionsMap['stock.transferencia.visualizar'] = true;
      permissionsMap['stock.inventario.visualizar'] = true;
      permissionsMap['terceiros.cliente.visualizar'] = true;
      permissionsMap['terceiros.fornecedor.visualizar'] = true;
      permissionsMap['terceiros.artigo.visualizar'] = true;
      permissionsMap['terceiros.armazem.visualizar'] = true;

      // Relatórios (todos podem visualizar)
      permissionsMap['relatorios.conta_corrente.visualizar'] = true;
      permissionsMap['relatorios.dividas_aberto.visualizar'] = true;
      permissionsMap['relatorios.historico_documentos.visualizar'] = true;
      permissionsMap['relatorios.pagamentos.visualizar'] = true;
      permissionsMap['relatorios.limite_credito.visualizar'] = true;
      permissionsMap['relatorios.mapa_idade.visualizar'] = true;
      permissionsMap['relatorios.clientes_inativos.visualizar'] = true;
    }

    // Contabilidade sempre acessível para visualização
    permissionsMap['contabilidade.balancete.visualizar'] = true;
    permissionsMap['contabilidade.demonstracoes.visualizar'] = true;

    // Converter para array de chaves
    const permissions = Object.keys(permissionsMap).filter(key => permissionsMap[key]);

    console.log(`âœ… [/usuarios/permissoes/:usuarioId] Retornando ${permissions.length} permissÃµes`);
    console.log(`   Fonte: ${usuario.permissoesModulos ? 'PERMISSOES_MODULOS (NOVA)' : 'PERMISSOES_ANTIGAS (FALLBACK)'}`);

    return c.json({
      success: true,
      permissions,
      userLevel: usuario.nivel
    });

  } catch (error: any) {
    console.error('âŒ [/usuarios/permissoes/:usuarioId] Erro:', error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ðŸ” DEBUG: Rota temporária para verificar permissÃµes salvas no banco
app.get("/make-server-7249dcd9/debug/usuario/:usuarioId/permissoes-raw", async (c) => {
  try {
    const acessoDebugPermissoesRaw = await validarSuperAdminTonlineRequest(c);
    if (!acessoDebugPermissoesRaw.permitido) return acessoDebugPermissoesRaw.resposta;

    const usuarioId = c.req.param("usuarioId");

    console.log('ðŸ” [DEBUG] Buscando dados RAW do usuário:', usuarioId);
    console.log('ðŸ” [DEBUG] Tipo do usuarioId:', typeof usuarioId);

    // Buscar usuário
    const chavesUsuario = await kv.getByPrefix('usuario:');
    console.log(`ðŸ” [DEBUG] Total de chaves encontradas: ${chavesUsuario.length}`);

    let usuario = null;
    let chaveEncontrada = null;

    for (const item of chavesUsuario) {
      // Verificar se item.key existe antes de usar includes
      if (!item.key || item.key.includes('email:')) continue;

      const u = item.value;

      // Log detalhado da comparação
      console.log('ðŸ” [DEBUG] Comparando:', {
        itemKey: item.key,
        itemValueId: u?.id,
        itemValueEmail: u?.email,
        itemValueAuthUserId: u?.authUserId,
        buscando: usuarioId,
        match1: u?.id === usuarioId,
        match2: u?.authUserId === usuarioId,
        match3: item.key === usuarioId,
        match4: u?.email === usuarioId
      });

      if (u && (u.id === usuarioId || u.authUserId === usuarioId || item.key === usuarioId || u.email === usuarioId)) {
        usuario = u;
        chaveEncontrada = item.key;
        console.log('âœ… [DEBUG] Usuário encontrado na chave:', item.key);
        break;
      }
    }

    if (!usuario) {
      console.log('âŒ [DEBUG] Nenhum usuário encontrado após percorrer todas as chaves');
      return c.json({
        success: false,
        error: 'Usuário não encontrado',
        usuarioIdBuscado: usuarioId,
        totalChavesVerificadas: chavesUsuario.length,
        usuariosDisponiveis: chavesUsuario
          .filter(u => u.key && !u.key.includes('email:'))
          .map(u => ({
            key: u.key,
            email: u.value?.email,
            nome: u.value?.nome
          }))
      }, 404);
    }

    // Retornar dados completos do usuário
    return c.json({
      success: true,
      chave: chaveEncontrada,
      usuario: {
        id: usuario.id,
        email: usuario.email,
        nome: usuario.nome,
        nivel: usuario.nivel,
        permissoes: usuario.permissoes,
        permissoesModulos: usuario.permissoesModulos,
        temPermissoesModulos: !!usuario.permissoesModulos,
        estruturaPermissoesModulos: usuario.permissoesModulos ? Object.keys(usuario.permissoesModulos) : null
      }
    });

  } catch (error: any) {
    console.error('âŒ [DEBUG] Erro:', error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ðŸ” DEBUG: Listar todos os usuários do sistema
app.get("/make-server-7249dcd9/debug/usuarios/listar", async (c) => {
  try {
    const acessoDebugListar = await validarSuperAdminTonlineRequest(c);
    if (!acessoDebugListar.permitido) return acessoDebugListar.resposta;

    console.log('ðŸ” [DEBUG] Listando todos os usuários do sistema...');

    const chavesUsuario = await kv.getByPrefix('usuario:');

    const usuarios = chavesUsuario
      .filter(item => item.key && !item.key.includes('email:'))
      .map(item => ({
        key: item.key,
        id: item.value?.id,
        authUserId: item.value?.authUserId,
        email: item.value?.email,
        nome: item.value?.nome,
        nivel: item.value?.nivel,
        empresaId: item.value?.empresaId,
        temPermissoesModulos: !!item.value?.permissoesModulos
      }));

    console.log(`âœ… [DEBUG] Encontrados ${usuarios.length} usuários`);

    return c.json({
      success: true,
      total: usuarios.length,
      usuarios
    });

  } catch (error: any) {
    console.error('âŒ [DEBUG] Erro ao listar usuários:', error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ========== ROTAS DE AUTORIZAÃ‡ÃƒO (NOVO SISTEMA CENTRALIZADO) ==========

// Rota central de autorização - can(usuario, acao, documento?)
app.post("/make-server-7249dcd9/authorization/can", async (c) => {
  try {
    const body = await c.req.json();
    const { usuario, acao, documento } = body;

    const result = await authorization.can(usuario, acao, documento);
    return c.json(result);
  } catch (error: any) {
    console.error('âŒ Erro na rota de autorização:', error);
    return c.json({
      permitido: false,
      motivo: 'Erro ao verificar autorização: ' + error.message
    }, 500);
  }
});

// Rotas de conveniência
app.post("/make-server-7249dcd9/authorization/can-create", async (c) => {
  try {
    const { usuario, tipo } = await c.req.json();
    const result = await authorization.canCreate(usuario, tipo);
    return c.json(result);
  } catch (error: any) {
    return c.json({ permitido: false, motivo: error.message }, 500);
  }
});

app.post("/make-server-7249dcd9/authorization/can-edit", async (c) => {
  try {
    const { usuario, documento } = await c.req.json();
    const result = await authorization.canEdit(usuario, documento);
    return c.json(result);
  } catch (error: any) {
    return c.json({ permitido: false, motivo: error.message }, 500);
  }
});

app.post("/make-server-7249dcd9/authorization/can-delete", async (c) => {
  try {
    const { usuario, documento } = await c.req.json();
    const result = await authorization.canDelete(usuario, documento);
    return c.json(result);
  } catch (error: any) {
    return c.json({ permitido: false, motivo: error.message }, 500);
  }
});

// ========== ROTAS DE AUDITORIA ==========

// Rotas GET /empresas/:empresaId/auditoria, /auditoria/documento/:id, /auditoria/usuario/:id, /empresas/:empresaId/auditoria/estatisticas movidas para admin-router.tsx (admin-server-7249dcd9)

// Registrar log manualmente
app.post("/make-server-7249dcd9/auditoria", async (c) => {
  try {
    const log = await c.req.json();
    const result = await auditoria.registrarLog(log);
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ===================================================================
// ðŸ¢ ROTAS DE CONTABILIDADE
// ===================================================================

// Inicializar contabilidade para uma empresa (cria plano de contas, diários e mapeamentos)
app.post("/make-server-7249dcd9/empresas/:empresaId/contabilidade/inicializar", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    console.log(`[API] Inicializando contabilidade para empresa: ${empresaId}`);

    // 1. Inicializar plano de contas
    const contasResult = await contabilidade.inicializarPlanoContas(empresaId);
    if (!contasResult.success) {
      return c.json(contasResult, 400);
    }

    // 2. Inicializar diários
    const diariosResult = await contabilidade.inicializarDiarios(empresaId);
    if (!diariosResult.success) {
      return c.json(diariosResult, 400);
    }

    // 3. Inicializar mapeamentos base
    const mapeamentosResult = await contabilidade.inicializarMapeamentosBase(empresaId);
    if (!mapeamentosResult.success) {
      return c.json(mapeamentosResult, 400);
    }

    console.log(`[API] âœ… Contabilidade inicializada para empresa: ${empresaId}`);
    return c.json({
      success: true,
      data: {
        contas: contasResult.data,
        diarios: diariosResult.data,
        mapeamentos: mapeamentosResult.data,
      },
    });
  } catch (error: any) {
    console.error("[API] âŒ Erro ao inicializar contabilidade:", error);
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Obter plano de contas
app.get("/make-server-7249dcd9/empresas/:empresaId/contas", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const result = await contabilidade.obterContas(empresaId);
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Criar conta contábil
app.post("/make-server-7249dcd9/empresas/:empresaId/contas", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const dados = await c.req.json();
    const result = await contabilidade.criarConta({ ...dados, empresaId });
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Atualizar conta contábil escopada por empresa
app.put("/make-server-7249dcd9/empresas/:empresaId/contas/:id", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const id = c.req.param("id");
    const dados = await c.req.json();
    const result = await contabilidade.atualizarContaSegura(id, dados, empresaId);
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Atualizar conta contábil (rota legada sem empresaId na URL — valida o
// escopo a partir da propria conta, ja que nao ha empresaId no caminho)
app.put("/make-server-7249dcd9/contas/:id", async (c) => {
  try {
    const chamador = await obterUsuarioAutenticadoRequest(c);
    if (!chamador || chamador.ativo === false) {
      return c.json({ success: false, error: "Utilizador nao autenticado" }, 401);
    }
    const id = c.req.param("id");
    const contaExistente = await kv.get(id) as { empresaId?: string } | null;
    if (!contaExistente) {
      return c.json({ success: false, error: "Conta nao encontrada" }, 404);
    }
    if (!isUsuarioSuperAdminTonline(chamador) && String(chamador.empresaId || "") !== String(contaExistente.empresaId || "")) {
      return c.json({ success: false, error: "Nao tem permissao para aceder a esta empresa" }, 403);
    }
    const dados = await c.req.json();
    const result = await contabilidade.atualizarContaSegura(id, dados, contaExistente.empresaId);
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Apagar conta contábil escopada por empresa
app.delete("/make-server-7249dcd9/empresas/:empresaId/contas/:id", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const id = c.req.param("id");
    const result = await contabilidade.apagarConta(id, empresaId);
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Apagar conta contábil (rota legada sem empresaId na URL — valida o escopo
// a partir da propria conta, ja que nao ha empresaId no caminho)
app.delete("/make-server-7249dcd9/contas/:id", async (c) => {
  try {
    const chamador = await obterUsuarioAutenticadoRequest(c);
    if (!chamador || chamador.ativo === false) {
      return c.json({ success: false, error: "Utilizador nao autenticado" }, 401);
    }
    const id = c.req.param("id");
    const contaExistente = await kv.get(id) as { empresaId?: string } | null;
    if (!contaExistente) {
      return c.json({ success: false, error: "Conta nao encontrada" }, 404);
    }
    if (!isUsuarioSuperAdminTonline(chamador) && String(chamador.empresaId || "") !== String(contaExistente.empresaId || "")) {
      return c.json({ success: false, error: "Nao tem permissao para aceder a esta empresa" }, 403);
    }
    const result = await contabilidade.apagarConta(id, contaExistente.empresaId);
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Obter diários
// Obter activos fixos cadastrados
app.get("/make-server-7249dcd9/empresas/:empresaId/activos-fixos", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const result = await contabilidade.obterActivosFixos(empresaId);
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Criar activo fixo
app.post("/make-server-7249dcd9/empresas/:empresaId/activos-fixos", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const dados = await c.req.json();
    const result = await contabilidade.criarActivoFixo(empresaId, dados);
    return c.json(result, result.success ? 200 : 400);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Atualizar activo fixo
app.put("/make-server-7249dcd9/empresas/:empresaId/activos-fixos/:id", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const id = c.req.param("id");
    const dados = await c.req.json();
    const result = await contabilidade.atualizarActivoFixo(empresaId, id, dados);
    return c.json(result, result.success ? 200 : 400);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Remover activo fixo
app.delete("/make-server-7249dcd9/empresas/:empresaId/activos-fixos/:id", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const id = c.req.param("id");
    const result = await contabilidade.apagarActivoFixo(empresaId, id);
    return c.json(result, result.success ? 200 : 400);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Reconciliações bancárias
app.get("/make-server-7249dcd9/empresas/:empresaId/reconciliacoes-bancarias", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const result = await contabilidade.obterReconciliacoesBancarias(empresaId, {
      contaId: c.req.query("contaId"),
      dataInicio: c.req.query("dataInicio"),
      dataFim: c.req.query("dataFim"),
    });
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.post("/make-server-7249dcd9/empresas/:empresaId/reconciliacoes-bancarias", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const dados = await c.req.json();
    const result = await contabilidade.salvarReconciliacaoBancaria(empresaId, dados, escopo.usuario?.id);
    return c.json(result, result.success ? 200 : 400);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.put("/make-server-7249dcd9/empresas/:empresaId/reconciliacoes-bancarias/:id", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const id = c.req.param("id");
    const dados = await c.req.json();
    const result = await contabilidade.salvarReconciliacaoBancaria(empresaId, { ...dados, id }, escopo.usuario?.id);
    return c.json(result, result.success ? 200 : 400);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.delete("/make-server-7249dcd9/empresas/:empresaId/reconciliacoes-bancarias/:id", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const id = c.req.param("id");
    const result = await contabilidade.apagarReconciliacaoBancaria(empresaId, id);
    return c.json(result, result.success ? 200 : 400);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.get("/make-server-7249dcd9/empresas/:empresaId/diarios", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const result = await contabilidade.obterDiarios(empresaId);
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Criar diário
app.post("/make-server-7249dcd9/empresas/:empresaId/diarios", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const dados = await c.req.json();
    const result = await contabilidade.criarDiario(empresaId, dados);
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Atualizar diário
app.put("/make-server-7249dcd9/empresas/:empresaId/diarios/:id", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const id = c.req.param("id");
    const dados = await c.req.json();
    const result = await contabilidade.atualizarDiario(id, dados, empresaId);
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Atualizar bloqueio de diário
app.patch("/make-server-7249dcd9/empresas/:empresaId/diarios/:id/bloqueio", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const id = c.req.param("id");
    const dados = await c.req.json();
    const result = await contabilidade.atualizarBloqueioDiario(id, dados.bloqueado);
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Obter lançamentos contábeis
app.get("/make-server-7249dcd9/empresas/:empresaId/lancamentos", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const dataInicio = c.req.query("dataInicio");
    const dataFim = c.req.query("dataFim");
    const diarioId = c.req.query("diarioId");
    const estado = c.req.query("estado");

    const result = await contabilidade.obterLancamentos(empresaId, {
      dataInicio,
      dataFim,
      diarioId,
      estado,
    });
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Prever próxima referência automática do lançamento
app.get("/make-server-7249dcd9/empresas/:empresaId/lancamentos/proxima-referencia", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const result = await contabilidade.preverProximaReferenciaLancamento(empresaId, c.req.query("data"));
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Criar lançamento contábil manual
app.post("/make-server-7249dcd9/empresas/:empresaId/lancamentos", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const dados = await c.req.json();
    const result = await contabilidade.criarLancamento({ ...dados, empresaId });
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Contabilizar uma folha de pagamento do RH (gera lancamento em rascunho no
// diario SAL) — ver contabilidade.gerarLancamentoFolhaPagamento().
app.post("/make-server-7249dcd9/empresas/:empresaId/contabilidade/lancar-folha-pagamento", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const { folhaPagamentoId, criadoPor } = await c.req.json();

    const folha = await folhaPagamentoRH.buscarFolhaPagamentoPorId(folhaPagamentoId);
    if (!folha || folha.empresaId !== empresaId) {
      return c.json({ success: false, error: "Folha de pagamento não encontrada" }, 404);
    }

    const colaborador = await colaboradoresRH.buscarColaboradorPorId(folha.colaboradorId);
    if (!colaborador) {
      return c.json({ success: false, error: "Colaborador não encontrado" }, 404);
    }

    const result = await contabilidade.gerarLancamentoFolhaPagamento(
      empresaId,
      folha,
      colaborador.nome,
      criadoPor || "Utilizador do sistema",
    );
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Atualizar/processar lançamento em rascunho
app.put("/make-server-7249dcd9/lancamentos/:id", async (c) => {
  try {
    const chamador = await obterUsuarioAutenticadoRequest(c);
    if (!chamador || chamador.ativo === false) {
      return c.json({ success: false, error: "Utilizador nao autenticado" }, 401);
    }
    const id = c.req.param("id");
    const lancamentoAtual = await kv.get(id) as { empresaId?: string } | null;
    if (!lancamentoAtual) {
      return c.json({ success: false, error: "Lancamento nao encontrado" }, 404);
    }
    if (!isUsuarioSuperAdminTonline(chamador) && String(chamador.empresaId || "") !== String(lancamentoAtual.empresaId || "")) {
      return c.json({ success: false, error: "Nao tem permissao para aceder a esta empresa" }, 403);
    }
    const dados = await c.req.json();
    const result = await contabilidade.atualizarLancamento(id, dados);
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Lançar (postar) um lançamento
app.post("/make-server-7249dcd9/lancamentos/:id/lancar", async (c) => {
  try {
    const chamador = await obterUsuarioAutenticadoRequest(c);
    if (!chamador || chamador.ativo === false) {
      return c.json({ success: false, error: "Utilizador nao autenticado" }, 401);
    }
    const id = c.req.param("id");
    const lancamentoAtual = await kv.get(id) as { empresaId?: string } | null;
    if (!lancamentoAtual) {
      return c.json({ success: false, error: "Lancamento nao encontrado" }, 404);
    }
    if (!isUsuarioSuperAdminTonline(chamador) && String(chamador.empresaId || "") !== String(lancamentoAtual.empresaId || "")) {
      return c.json({ success: false, error: "Nao tem permissao para aceder a esta empresa" }, 403);
    }
    const result = await contabilidade.lancarLancamento(id);
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Estornar lançamento
app.post("/make-server-7249dcd9/lancamentos/:id/estornar", async (c) => {
  try {
    const chamador = await obterUsuarioAutenticadoRequest(c);
    if (!chamador || chamador.ativo === false) {
      return c.json({ success: false, error: "Utilizador nao autenticado" }, 401);
    }
    const id = c.req.param("id");
    const lancamentoAtual = await kv.get(id) as { empresaId?: string } | null;
    if (!lancamentoAtual) {
      return c.json({ success: false, error: "Lancamento nao encontrado" }, 404);
    }
    if (!isUsuarioSuperAdminTonline(chamador) && String(chamador.empresaId || "") !== String(lancamentoAtual.empresaId || "")) {
      return c.json({ success: false, error: "Nao tem permissao para aceder a esta empresa" }, 403);
    }
    const body = await lerBodyJsonSeguro(c);
    const result = await contabilidade.estornarLancamento(id, {
      usuarioId: body?.usuarioId,
      motivo: body?.motivo,
    });
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Gerar lançamento automático
app.post("/make-server-7249dcd9/contabilidade/gerar-lancamento", async (c) => {
  try {
    const documento = await c.req.json();
    const escopo = await verificarEscopoEmpresaRequest(c, documento?.empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const result = await contabilidade.gerarLancamentoAutomatico(documento);
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Listar documentos fiscais disponiveis para lancamento contabil
app.get("/make-server-7249dcd9/empresas/:empresaId/contabilidade/documentos-fiscais-lancamentos", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const result = await contabilidade.listarDocumentosFiscaisParaLancamento(empresaId, {
      tipo: c.req.query("tipo"),
      dataInicio: c.req.query("dataInicio"),
      dataFim: c.req.query("dataFim"),
      numeroDocumento: c.req.query("numeroDocumento"),
    });
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Verificar inconsistencias entre documentos e lancamentos contabeis
app.get("/make-server-7249dcd9/empresas/:empresaId/contabilidade/inconsistencias", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const result = await contabilidade.verificarInconsistenciasContabeis(empresaId, {
      tipo: c.req.query("tipo"),
      dataInicio: c.req.query("dataInicio"),
      dataFim: c.req.query("dataFim"),
      numeroDocumento: c.req.query("numeroDocumento"),
    });
    return c.json(result, result.success ? 200 : 400);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Previsualizar lancamentos contabeis em lote antes de gravar
app.post("/make-server-7249dcd9/empresas/:empresaId/contabilidade/lancamentos/previsualizar-documentos", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const dados = await c.req.json();
    const result = await contabilidade.previsualizarLancamentosDocumentosFiscais(empresaId, dados);
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Gerar lancamentos contabeis em lote a partir de documentos fiscais
app.post("/make-server-7249dcd9/empresas/:empresaId/contabilidade/lancamentos/gerar-documentos", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const dados = await c.req.json();
    const result = await contabilidade.gerarLancamentosDocumentosFiscais(empresaId, dados);
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Lancar (rascunho -> lancado) todos os lancamentos pendentes de uma vez
app.post("/make-server-7249dcd9/empresas/:empresaId/contabilidade/lancamentos/lancar-pendentes", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const dados = await lerBodyJsonSeguro(c);
    const result = await contabilidade.lancarLancamentosPendentes(empresaId, {
      dataInicio: dados?.dataInicio,
      dataFim: dados?.dataFim,
    });
    return c.json(result, result.success ? 200 : 400);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Preparar fecho contabil do exercicio em rascunho
app.post("/make-server-7249dcd9/empresas/:empresaId/contabilidade/exercicios/:exercicioId/preparar-fecho", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const exercicioId = c.req.param("exercicioId");
    const result = await contabilidade.prepararFechoExercicio(empresaId, exercicioId, escopo.usuario?.id);
    return c.json(result, result.success ? 200 : 400);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Fecho definitivo do exercicio contabil
app.post("/make-server-7249dcd9/empresas/:empresaId/contabilidade/exercicios/:exercicioId/fecho-definitivo", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const exercicioId = c.req.param("exercicioId");
    const result = await contabilidade.fecharDefinitivamenteExercicio(empresaId, exercicioId, escopo.usuario?.id);
    return c.json(result, result.success ? 200 : 400);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Modelos fiscais guardados por exercicio
app.get("/make-server-7249dcd9/empresas/:empresaId/contabilidade/modelos-fiscais", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const ano = c.req.query("ano");
    const result = await contabilidade.listarModelosFiscais(empresaId, ano);
    return c.json(result, result.success ? 200 : 400);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.get("/make-server-7249dcd9/empresas/:empresaId/contabilidade/modelos-fiscais/:ano/:modeloId", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const ano = c.req.param("ano");
    const modeloId = c.req.param("modeloId");
    const result = await contabilidade.obterModeloFiscal(empresaId, ano, modeloId);
    return c.json(result, result.success ? 200 : 400);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.post("/make-server-7249dcd9/empresas/:empresaId/contabilidade/modelos-fiscais/:ano/:modeloId", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const ano = Number(c.req.param("ano"));
    const modeloId = c.req.param("modeloId");
    const dados = await c.req.json();
    const result = await contabilidade.salvarModeloFiscal(empresaId, { ...dados, ano, modeloId }, escopo.usuario?.id);
    return c.json(result, result.success ? 200 : 400);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

app.patch("/make-server-7249dcd9/empresas/:empresaId/contabilidade/modelos-fiscais/:ano/:modeloId/estado", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const ano = c.req.param("ano");
    const modeloId = c.req.param("modeloId");
    const dados = await c.req.json().catch(() => ({}));
    const result = await contabilidade.alterarEstadoModeloFiscal(empresaId, ano, modeloId, dados.estado, escopo.usuario?.id);
    return c.json(result, result.success ? 200 : 400);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Gerar balancete
app.get("/make-server-7249dcd9/empresas/:empresaId/balancete", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const dataInicio = c.req.query("dataInicio");
    const dataFim = c.req.query("dataFim");

    if (!dataInicio || !dataFim) {
      return c.json({ success: false, error: "dataInicio e dataFim são obrigatórios" }, 400);
    }

    const result = await contabilidade.gerarBalancete(empresaId, dataInicio, dataFim);
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Gerar demonstração de resultados
app.get("/make-server-7249dcd9/empresas/:empresaId/demonstracao-resultados", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const dataInicio = c.req.query("dataInicio");
    const dataFim = c.req.query("dataFim");

    if (!dataInicio || !dataFim) {
      return c.json({ success: false, error: "dataInicio e dataFim são obrigatórios" }, 400);
    }

    const result = await contabilidade.gerarDemonstracaoResultados(empresaId, dataInicio, dataFim);
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Obter mapeamentos contábeis
app.get("/make-server-7249dcd9/empresas/:empresaId/mapeamentos", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const result = await contabilidade.obterMapeamentos(empresaId);
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// Criar/atualizar mapeamento contábil
app.post("/make-server-7249dcd9/empresas/:empresaId/mapeamentos", validarAcessoMiddleware("contabilidade"), async (c) => {
  try {
    const empresaId = c.req.param("empresaId");
    const escopo = await verificarEscopoEmpresaRequest(c, empresaId);
    if (!escopo.permitido) {
      return c.json({ success: false, error: escopo.error }, escopo.status as any);
    }
    const dados = await c.req.json();
    const result = await contabilidade.criarMapeamento({ ...dados, empresaId });
    return c.json(result);
  } catch (error: any) {
    return c.json({ success: false, error: error.message }, 500);
  }
});

// ðŸ”„ FORÃ‡A RELOAD: 2026-02-18 20:40 - Fix getVDById to populate cliente
Deno.serve(app.fetch);
