import express, { type Express } from 'express';
import cors from 'cors';
import helmet from 'helmet';
import { env, getCorsOrigins } from './config/env.js';
import { errorMiddleware } from './middlewares/error.middleware.js';
import { authRoutes } from './routes/auth.routes.js';
import { dashboardRoutes } from './routes/dashboard.routes.js';
import { cfdiRoutes } from './routes/cfdi.routes.js';
import { impuestosRoutes } from './routes/impuestos.routes.js';
import { exportRoutes } from './routes/export.routes.js';
import { alertasRoutes } from './routes/alertas.routes.js';
import { notificationPreferencesRoutes } from './routes/notification-preferences.routes.js';
import { tareasRoutes } from './routes/tareas.routes.js';
import { papeleriaRoutes } from './routes/papeleria.routes.js';
import { despachoStatsRoutes } from './routes/despacho-stats.routes.js';
import { calendarioRoutes } from './routes/calendario.routes.js';
import { reportesRoutes } from './routes/reportes.routes.js';
import { usuariosRoutes } from './routes/usuarios.routes.js';
import { tenantsRoutes } from './routes/tenants.routes.js';
import fielRoutes from './routes/fiel.routes.js';
import satRoutes from './routes/sat.routes.js';
import { webhookRoutes } from './routes/webhook.routes.js';
import { subscriptionRoutes } from './routes/subscription.routes.js';
import { regimenRoutes } from './routes/regimen.routes.js';
import { bancosRoutes } from './routes/bancos.routes.js';
import { conciliacionRoutes } from './routes/conciliacion.routes.js';
import { facturacionRoutes } from './routes/facturacion.routes.js';
import { catalogosRoutes } from './routes/catalogos.routes.js';
import { documentosRoutes } from './routes/documentos.routes.js';
import { auditLogRoutes } from './routes/audit-log.routes.js';
import { platformStaffRoutes } from './routes/platform-staff.routes.js';
import despachoRoutes from './routes/despacho.routes.js';
import contribuyenteRoutes from './routes/contribuyente.routes.js';
import carteraRoutes from './routes/cartera.routes.js';
import planCatalogoRoutes from './routes/plan-catalogo.routes.js';
import connectorRoutes from './routes/connector.routes.js';
import adminDashboardRoutes from './routes/admin-dashboard.routes.js';
import adminImpersonateRoutes from './routes/admin-impersonate.routes.js';
import adminClientesRoutes from './routes/admin-clientes.routes.js';
import adminAddonsRoutes from './routes/admin-addons.routes.js';
import { trialInvitationRoutes } from './routes/trial-invitations.routes.js';
import clientInvitationRoutes from './routes/client-invitations.routes.js';
import despachoAuditRoutes from './routes/despacho-audit.routes.js';
import metricasRoutes from './routes/metricas.routes.js';

const app: Express = express();

// Trust proxy — la app corre detrás de Cloudflare/nginx. Necesario para que
// express-rate-limit lea correctamente X-Forwarded-For sin lanzar warnings.
app.set('trust proxy', 1);

// Security. Helmet default incluye un CSP restrictivo que puede chocar con el
// frontend cuando éste embebe recursos propios (ej: /terminos embebe el PDF de
// /legal/). Dejamos CSP off en el API y centralizamos los headers de seguridad
// en next.config del web (X-Frame-Options, CSP frame-ancestors, HSTS, nosniff,
// Referrer-Policy) que es quien sirve la UI. El API solo responde JSON y
// archivos binarios (PDFs, XMLs) — no tiene contenido HTML que requiera CSP.
app.use(helmet({
  contentSecurityPolicy: false,
  crossOriginResourcePolicy: { policy: 'cross-origin' }, // permite /legal/*.pdf embebido
}));
app.use(cors({
  origin: getCorsOrigins(),
  credentials: true,
}));

// Body parsing - 10MB default, bulk CFDI route has its own higher limit
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true, limit: '10mb' }));

// Health check
app.get('/health', (req, res) => {
  res.json({ status: 'ok', timestamp: new Date().toISOString() });
});

// API Routes
app.use('/api/auth', authRoutes);
app.use('/api/dashboard', dashboardRoutes);
app.use('/api/cfdi', cfdiRoutes);
app.use('/api/impuestos', impuestosRoutes);
app.use('/api/export', exportRoutes);
app.use('/api/alertas', alertasRoutes);
app.use('/api/notificaciones', notificationPreferencesRoutes);
app.use('/api/tareas', tareasRoutes);
app.use('/api/papeleria', papeleriaRoutes);
app.use('/api/despachos', despachoStatsRoutes);
app.use('/api/calendario', calendarioRoutes);
app.use('/api/reportes', reportesRoutes);
app.use('/api/usuarios', usuariosRoutes);
app.use('/api/tenants', tenantsRoutes);
app.use('/api/fiel', fielRoutes);
app.use('/api/sat', satRoutes);
app.use('/api/webhooks', webhookRoutes);
app.use('/api/subscriptions', subscriptionRoutes);
app.use('/api/regimenes', regimenRoutes);
app.use('/api/bancos', bancosRoutes);
app.use('/api/conciliacion', conciliacionRoutes);
app.use('/api/facturacion', facturacionRoutes);
app.use('/api/catalogos', catalogosRoutes);
app.use('/api/documentos', documentosRoutes);
app.use('/api/audit-log', auditLogRoutes);
app.use('/api/platform-staff', platformStaffRoutes);
app.use('/api/despachos', despachoRoutes);
app.use('/api/contribuyentes', contribuyenteRoutes);
app.use('/api/carteras', carteraRoutes);
app.use('/api/planes', planCatalogoRoutes);
app.use('/api/connector', connectorRoutes);
app.use('/api/admin/dashboard', adminDashboardRoutes);
app.use('/api/admin/impersonate', adminImpersonateRoutes);
app.use('/api/admin/clientes', adminClientesRoutes);
app.use('/api/admin/addons', adminAddonsRoutes);
app.use('/api/despacho/audit-log', despachoAuditRoutes);
app.use('/api/metricas', metricasRoutes);
app.use('/api/invitations/trial', trialInvitationRoutes);
app.use('/api/invitations/client', clientInvitationRoutes);

// Error handling
app.use(errorMiddleware);

export { app };
