import express, { Application, Request, Response, NextFunction } from 'express';
import cors from 'cors';
import helmet from 'helmet';
import compression from 'compression';
import morgan from 'morgan';
import { config } from './config/index.js';
import { logger } from './shared/utils/logger.js';
import { AppError, ApiResponse } from './shared/types/index.js';
import { setupSwagger } from './config/swagger.config.js';
import authRoutes from './modules/auth/auth.routes.js';
import apiKeysRoutes from './modules/auth/apiKeys.routes.js';
import usersRoutes from './modules/users/users.routes.js';
import { rolesRoutes, permissionsRoutes } from './modules/roles/index.js';
import { tenantsRoutes } from './modules/tenants/index.js';
import companiesRoutes from './modules/companies/companies.routes.js';
import coreRoutes from './modules/core/core.routes.js';
import partnersRoutes from './modules/partners/partners.routes.js';
import inventoryRoutes from './modules/inventory/inventory.routes.js';
import financialRoutes from './modules/financial/financial.routes.js';
import purchasesRoutes from './modules/purchases/purchases.routes.js';
import salesRoutes from './modules/sales/sales.routes.js';
import projectsRoutes from './modules/projects/projects.routes.js';
import systemRoutes from './modules/system/system.routes.js';
import crmRoutes from './modules/crm/crm.routes.js';
import hrRoutes from './modules/hr/hr.routes.js';
import reportsRoutes from './modules/reports/reports.routes.js';

const app: Application = express();

// Security middleware
app.use(helmet());
app.use(cors({
  origin: config.cors.origin,
  credentials: true,
}));

// Request parsing
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true }));
app.use(compression());

// Logging
const morganFormat = config.env === 'production' ? 'combined' : 'dev';
app.use(morgan(morganFormat, {
  stream: { write: (message) => logger.http(message.trim()) }
}));

// Swagger documentation
const apiPrefix = config.apiPrefix;
setupSwagger(app, apiPrefix);

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

// API routes
app.use(`${apiPrefix}/auth`, authRoutes);
app.use(`${apiPrefix}/auth/api-keys`, apiKeysRoutes);
app.use(`${apiPrefix}/users`, usersRoutes);
app.use(`${apiPrefix}/roles`, rolesRoutes);
app.use(`${apiPrefix}/permissions`, permissionsRoutes);
app.use(`${apiPrefix}/tenants`, tenantsRoutes);
app.use(`${apiPrefix}/companies`, companiesRoutes);
app.use(`${apiPrefix}/core`, coreRoutes);
app.use(`${apiPrefix}/partners`, partnersRoutes);
app.use(`${apiPrefix}/inventory`, inventoryRoutes);
app.use(`${apiPrefix}/financial`, financialRoutes);
app.use(`${apiPrefix}/purchases`, purchasesRoutes);
app.use(`${apiPrefix}/sales`, salesRoutes);
app.use(`${apiPrefix}/projects`, projectsRoutes);
app.use(`${apiPrefix}/system`, systemRoutes);
app.use(`${apiPrefix}/crm`, crmRoutes);
app.use(`${apiPrefix}/hr`, hrRoutes);
app.use(`${apiPrefix}/reports`, reportsRoutes);

// 404 handler
app.use((_req: Request, res: Response) => {
  const response: ApiResponse = {
    success: false,
    error: 'Endpoint no encontrado'
  };
  res.status(404).json(response);
});

// Global error handler
app.use((err: Error, _req: Request, res: Response, _next: NextFunction) => {
  logger.error('Unhandled error', {
    error: err.message,
    stack: err.stack,
    name: err.name
  });

  if (err instanceof AppError) {
    const response: ApiResponse = {
      success: false,
      error: err.message,
    };
    return res.status(err.statusCode).json(response);
  }

  // Generic error
  const response: ApiResponse = {
    success: false,
    error: config.env === 'production'
      ? 'Error interno del servidor'
      : err.message,
  };
  res.status(500).json(response);
});

export default app;
