/**
 * Server Entry Point
 * MVP Sistema Administración de Obra e INFONAVIT
 *
 * @author Backend-Agent
 * @date 2025-11-20
 */

import 'reflect-metadata';
import express, { Application } from 'express';
import cors from 'cors';
import helmet from 'helmet';
import morgan from 'morgan';
import dotenv from 'dotenv';
import { AppDataSource } from './shared/database/typeorm.config';

// Cargar variables de entorno
dotenv.config();

const app: Application = express();
const PORT = process.env.APP_PORT || 3000;
const API_VERSION = process.env.API_VERSION || 'v1';

/**
 * Middlewares
 */
app.use(helmet()); // Seguridad HTTP headers
app.use(cors({
  origin: process.env.CORS_ORIGIN?.split(',') || '*',
  credentials: process.env.CORS_CREDENTIALS === 'true',
}));
app.use(morgan(process.env.LOG_FORMAT || 'dev')); // Logging
app.use(express.json()); // Parse JSON bodies
app.use(express.urlencoded({ extended: true })); // Parse URL-encoded bodies

/**
 * Health Check
 */
app.get('/health', (_req, res) => {
  res.status(200).json({
    status: 'ok',
    timestamp: new Date().toISOString(),
    environment: process.env.NODE_ENV || 'development',
    version: API_VERSION,
  });
});

/**
 * API Routes
 */
import { proyectoController, fraccionamientoController, createEtapaController, createManzanaController, createLoteController, createPrototipoController } from './modules/construction/controllers';
import { createAuthController } from './modules/auth/controllers/auth.controller';
import { createUsersController } from './modules/users/controllers/users.controller';
import { createConceptoController, createPresupuestoController } from './modules/budgets/controllers';
import { createAvanceObraController, createBitacoraObraController } from './modules/progress/controllers';
import { createEstimacionController, createAnticipoController, createFondoGarantiaController, createRetencionController } from './modules/estimates/controllers';
import { createPuestoController, createEmployeeController } from './modules/hr/controllers';
import { createCapacitacionController, createIncidenteController } from './modules/hse/controllers';
import { createRequisicionController, createConsumoObraController } from './modules/inventory/controllers';
import { createComparativoController } from './modules/purchase/controllers';
import { createDerechohabienteController, createAsignacionController } from './modules/infonavit/controllers';
import { createInspectionController, createTicketController } from './modules/quality/controllers';
import { createContractController, createSubcontractorController } from './modules/contracts/controllers';
import { createReportController, createDashboardController, createKpiController } from './modules/reports/controllers';
import { createCostCenterController, createAuditLogController, createSystemSettingController, createBackupController } from './modules/admin/controllers';
import { createOpportunityController, createBidController, createBidBudgetController, createBidAnalyticsController } from './modules/bidding/controllers';
import { createAccountingController, createAPController, createARController, createCashFlowController, createBankReconciliationController, createReportsController } from './modules/finance/controllers';

// Root API info
app.get(`/api/${API_VERSION}`, (_req, res) => {
  res.status(200).json({
    message: 'API MVP Sistema Administración de Obra',
    version: API_VERSION,
    endpoints: {
      health: '/health',
      docs: `/api/${API_VERSION}/docs`,
      auth: `/api/${API_VERSION}/auth`,
      users: `/api/${API_VERSION}/users`,
      proyectos: `/api/${API_VERSION}/proyectos`,
      fraccionamientos: `/api/${API_VERSION}/fraccionamientos`,
      etapas: `/api/${API_VERSION}/etapas`,
      manzanas: `/api/${API_VERSION}/manzanas`,
      lotes: `/api/${API_VERSION}/lotes`,
      prototipos: `/api/${API_VERSION}/prototipos`,
      conceptos: `/api/${API_VERSION}/conceptos`,
      presupuestos: `/api/${API_VERSION}/presupuestos`,
      avances: `/api/${API_VERSION}/avances`,
      bitacora: `/api/${API_VERSION}/bitacora`,
      estimaciones: `/api/${API_VERSION}/estimaciones`,
      anticipos: `/api/${API_VERSION}/anticipos`,
      'fondos-garantia': `/api/${API_VERSION}/fondos-garantia`,
      retenciones: `/api/${API_VERSION}/retenciones`,
      puestos: `/api/${API_VERSION}/puestos`,
      empleados: `/api/${API_VERSION}/empleados`,
      capacitaciones: `/api/${API_VERSION}/capacitaciones`,
      incidentes: `/api/${API_VERSION}/incidentes`,
      requisiciones: `/api/${API_VERSION}/requisiciones`,
      consumos: `/api/${API_VERSION}/consumos`,
      comparativos: `/api/${API_VERSION}/comparativos`,
      derechohabientes: `/api/${API_VERSION}/derechohabientes`,
      asignaciones: `/api/${API_VERSION}/asignaciones`,
      inspections: `/api/${API_VERSION}/inspections`,
      tickets: `/api/${API_VERSION}/tickets`,
      contracts: `/api/${API_VERSION}/contracts`,
      subcontractors: `/api/${API_VERSION}/subcontractors`,
      reports: `/api/${API_VERSION}/reports`,
      dashboards: `/api/${API_VERSION}/dashboards`,
      kpis: `/api/${API_VERSION}/kpis`,
      'cost-centers': `/api/${API_VERSION}/cost-centers`,
      'audit-logs': `/api/${API_VERSION}/audit-logs`,
      settings: `/api/${API_VERSION}/settings`,
      backups: `/api/${API_VERSION}/backups`,
      opportunities: `/api/${API_VERSION}/opportunities`,
      bids: `/api/${API_VERSION}/bids`,
      'bid-budgets': `/api/${API_VERSION}/bid-budgets`,
      'bid-analytics': `/api/${API_VERSION}/bid-analytics`,
      accounting: `/api/${API_VERSION}/accounting`,
      'accounts-payable': `/api/${API_VERSION}/accounts-payable`,
      'accounts-receivable': `/api/${API_VERSION}/accounts-receivable`,
      'cash-flow': `/api/${API_VERSION}/cash-flow`,
      'bank-reconciliation': `/api/${API_VERSION}/bank-reconciliation`,
      'financial-reports': `/api/${API_VERSION}/financial-reports`,
    },
  });
});

// Construction Module Routes
app.use(`/api/${API_VERSION}/proyectos`, proyectoController);
app.use(`/api/${API_VERSION}/fraccionamientos`, fraccionamientoController);

// Auth y Users Module Routes - Se inicializan después de la conexión a BD
let authController: ReturnType<typeof createAuthController>;
let usersController: ReturnType<typeof createUsersController>;

/**
 * 404 Handler
 */
app.use((req, res) => {
  res.status(404).json({
    error: 'Not Found',
    message: `Cannot ${req.method} ${req.path}`,
  });
});

/**
 * Error Handler
 */
app.use((err: Error, _req: express.Request, res: express.Response, _next: express.NextFunction) => {
  console.error('Error:', err);
  res.status(500).json({
    error: 'Internal Server Error',
    message: process.env.NODE_ENV === 'development' ? err.message : 'Something went wrong',
  });
});

/**
 * Inicializar Base de Datos y Servidor
 */
async function bootstrap() {
  try {
    // Conectar a base de datos
    console.log('🔌 Conectando a base de datos...');
    await AppDataSource.initialize();
    console.log('✅ Base de datos conectada');

    // Inicializar Auth Controller (requiere DataSource)
    authController = createAuthController(AppDataSource);
    app.use(`/api/${API_VERSION}/auth`, authController);
    console.log('🔐 Auth module inicializado');

    // Inicializar Users Controller (requiere DataSource)
    usersController = createUsersController(AppDataSource);
    app.use(`/api/${API_VERSION}/users`, usersController);
    console.log('👥 Users module inicializado');

    // Inicializar Construction Controllers (requieren DataSource para auth)
    const etapaController = createEtapaController(AppDataSource);
    app.use(`/api/${API_VERSION}/etapas`, etapaController);

    const manzanaController = createManzanaController(AppDataSource);
    app.use(`/api/${API_VERSION}/manzanas`, manzanaController);

    const loteController = createLoteController(AppDataSource);
    app.use(`/api/${API_VERSION}/lotes`, loteController);

    const prototipoController = createPrototipoController(AppDataSource);
    app.use(`/api/${API_VERSION}/prototipos`, prototipoController);

    console.log('🏗️ Construction module inicializado');

    // Inicializar Budgets Controllers (requieren DataSource para auth)
    const conceptoController = createConceptoController(AppDataSource);
    app.use(`/api/${API_VERSION}/conceptos`, conceptoController);

    const presupuestoController = createPresupuestoController(AppDataSource);
    app.use(`/api/${API_VERSION}/presupuestos`, presupuestoController);

    console.log('💰 Budgets module inicializado');

    // Inicializar Progress Controllers (requieren DataSource para auth)
    const avanceObraController = createAvanceObraController(AppDataSource);
    app.use(`/api/${API_VERSION}/avances`, avanceObraController);

    const bitacoraObraController = createBitacoraObraController(AppDataSource);
    app.use(`/api/${API_VERSION}/bitacora`, bitacoraObraController);

    console.log('📊 Progress module inicializado');

    // Inicializar Estimates Controllers (requieren DataSource para auth)
    const estimacionController = createEstimacionController(AppDataSource);
    app.use(`/api/${API_VERSION}/estimaciones`, estimacionController);

    const anticipoController = createAnticipoController(AppDataSource);
    app.use(`/api/${API_VERSION}/anticipos`, anticipoController);

    const fondoGarantiaController = createFondoGarantiaController(AppDataSource);
    app.use(`/api/${API_VERSION}/fondos-garantia`, fondoGarantiaController);

    const retencionController = createRetencionController(AppDataSource);
    app.use(`/api/${API_VERSION}/retenciones`, retencionController);

    console.log('📝 Estimates module inicializado');

    // Inicializar HR Controllers (requieren DataSource para auth)
    const puestoController = createPuestoController(AppDataSource);
    app.use(`/api/${API_VERSION}/puestos`, puestoController);

    const employeeController = createEmployeeController(AppDataSource);
    app.use(`/api/${API_VERSION}/empleados`, employeeController);

    console.log('👷 HR module inicializado');

    // Inicializar HSE Controllers (requieren DataSource para auth)
    const capacitacionController = createCapacitacionController(AppDataSource);
    app.use(`/api/${API_VERSION}/capacitaciones`, capacitacionController);

    const incidenteController = createIncidenteController(AppDataSource);
    app.use(`/api/${API_VERSION}/incidentes`, incidenteController);

    console.log('🦺 HSE module inicializado');

    // Inicializar Inventory Controllers (requieren DataSource para auth)
    const requisicionController = createRequisicionController(AppDataSource);
    app.use(`/api/${API_VERSION}/requisiciones`, requisicionController);

    const consumoObraController = createConsumoObraController(AppDataSource);
    app.use(`/api/${API_VERSION}/consumos`, consumoObraController);

    console.log('📦 Inventory module inicializado');

    // Inicializar Purchase Controllers (requieren DataSource para auth)
    const comparativoController = createComparativoController(AppDataSource);
    app.use(`/api/${API_VERSION}/comparativos`, comparativoController);

    console.log('🛒 Purchase module inicializado');

    // Inicializar Infonavit Controllers (requieren DataSource para auth)
    const derechohabienteController = createDerechohabienteController(AppDataSource);
    app.use(`/api/${API_VERSION}/derechohabientes`, derechohabienteController);

    const asignacionController = createAsignacionController(AppDataSource);
    app.use(`/api/${API_VERSION}/asignaciones`, asignacionController);

    console.log('🏠 Infonavit module inicializado');

    // Inicializar Quality Controllers (requieren DataSource para auth)
    const inspectionController = createInspectionController(AppDataSource);
    app.use(`/api/${API_VERSION}/inspections`, inspectionController);

    const ticketController = createTicketController(AppDataSource);
    app.use(`/api/${API_VERSION}/tickets`, ticketController);

    console.log('✅ Quality module inicializado');

    // Inicializar Contracts Controllers (requieren DataSource para auth)
    const contractController = createContractController(AppDataSource);
    app.use(`/api/${API_VERSION}/contracts`, contractController);

    const subcontractorController = createSubcontractorController(AppDataSource);
    app.use(`/api/${API_VERSION}/subcontractors`, subcontractorController);

    console.log('📄 Contracts module inicializado');

    // Inicializar Reports Controllers (requieren DataSource para auth)
    const reportController = createReportController(AppDataSource);
    app.use(`/api/${API_VERSION}/reports`, reportController);

    const dashboardController = createDashboardController(AppDataSource);
    app.use(`/api/${API_VERSION}/dashboards`, dashboardController);

    const kpiController = createKpiController(AppDataSource);
    app.use(`/api/${API_VERSION}/kpis`, kpiController);

    console.log('📈 Reports module inicializado');

    // Inicializar Admin Controllers (requieren DataSource para auth)
    const costCenterController = createCostCenterController(AppDataSource);
    app.use(`/api/${API_VERSION}/cost-centers`, costCenterController);

    const auditLogController = createAuditLogController(AppDataSource);
    app.use(`/api/${API_VERSION}/audit-logs`, auditLogController);

    const systemSettingController = createSystemSettingController(AppDataSource);
    app.use(`/api/${API_VERSION}/settings`, systemSettingController);

    const backupController = createBackupController(AppDataSource);
    app.use(`/api/${API_VERSION}/backups`, backupController);

    console.log('⚙️ Admin module inicializado');

    // Inicializar Bidding Controllers (requieren DataSource para auth)
    const opportunityController = createOpportunityController(AppDataSource);
    app.use(`/api/${API_VERSION}/opportunities`, opportunityController);

    const bidController = createBidController(AppDataSource);
    app.use(`/api/${API_VERSION}/bids`, bidController);

    const bidBudgetController = createBidBudgetController(AppDataSource);
    app.use(`/api/${API_VERSION}/bid-budgets`, bidBudgetController);

    const bidAnalyticsController = createBidAnalyticsController(AppDataSource);
    app.use(`/api/${API_VERSION}/bid-analytics`, bidAnalyticsController);

    console.log('📋 Bidding module inicializado');

    // Inicializar Finance Controllers (requieren DataSource para auth)
    const accountingController = createAccountingController(AppDataSource);
    app.use(`/api/${API_VERSION}/accounting`, accountingController);

    const apController = createAPController(AppDataSource);
    app.use(`/api/${API_VERSION}/accounts-payable`, apController);

    const arController = createARController(AppDataSource);
    app.use(`/api/${API_VERSION}/accounts-receivable`, arController);

    const cashFlowController = createCashFlowController(AppDataSource);
    app.use(`/api/${API_VERSION}/cash-flow`, cashFlowController);

    const bankReconciliationController = createBankReconciliationController(AppDataSource);
    app.use(`/api/${API_VERSION}/bank-reconciliation`, bankReconciliationController);

    const financialReportsController = createReportsController(AppDataSource);
    app.use(`/api/${API_VERSION}/financial-reports`, financialReportsController);

    console.log('💵 Finance module inicializado');

    // Iniciar servidor
    app.listen(PORT, () => {
      console.log('🚀 Servidor iniciado');
      console.log(`📍 URL: http://localhost:${PORT}`);
      console.log(`📍 API: http://localhost:${PORT}/api/${API_VERSION}`);
      console.log(`📍 Health: http://localhost:${PORT}/health`);
      console.log(`🌍 Entorno: ${process.env.NODE_ENV || 'development'}`);
    });
  } catch (error) {
    console.error('❌ Error al iniciar servidor:', error);
    process.exit(1);
  }
}

// Iniciar aplicación
bootstrap();

export default app;
