// 🚛 CEDAH API Server HÍBRIDO - MySQL Primero, luego CEDAH
// Prioridad: 1. MySQL (nuestra DB) -> 2. CEDAH (solo si no existe)
const express = require('express');
const cors = require('cors');
const rateLimit = require('express-rate-limit');

// Importar módulos de base de datos
const { initDatabase, healthCheck, closeDatabase } = require('./database/connection');
const { buscarPlaca, insertarPlaca, listarPlacas, contarPlacas, buscarPorEstatus } = require('./database/placas');

// Importar cliente CEDAH para fallback
const { consultarPlacaCedah } = require('./cedah-api-client');

const app = express();
const PORT = process.env.PORT || 3000;
const NODE_ENV = process.env.NODE_ENV || 'development';
const PUBLIC_URL = process.env.PUBLIC_URL || '';

// Middlewares
// CORS: en producción, limitar al dominio público configurado
if (NODE_ENV === 'production') {
    const allowedOrigin = PUBLIC_URL || undefined;
    app.use(cors({
        origin: allowedOrigin ? [allowedOrigin] : undefined,
        methods: ['GET','POST','PUT','PATCH','DELETE','OPTIONS'],
        allowedHeaders: ['Content-Type','Authorization'],
        credentials: false
    }));
} else {
    // En desarrollo, permitir todo para facilitar pruebas
    app.use(cors());
}
app.use(express.json());

// 🛡️ Rate limiting - protección contra abuso / inyección masiva
// Confiar en el proxy (cPanel/Nginx/Apache) para obtener la IP real del cliente
app.set('trust proxy', 1);

// Limitador general: aplica a todas las rutas
const limiterGeneral = rateLimit({
    windowMs: 15 * 60 * 1000, // 15 minutos
    max: parseInt(process.env.RATE_LIMIT_GENERAL) || 300, // peticiones por IP en la ventana
    standardHeaders: true,
    legacyHeaders: false,
    message: {
        success: false,
        error: 'Demasiadas peticiones, intenta de nuevo más tarde',
        code: 'RATE_LIMITED'
    }
});

// Limitador estricto: para las consultas de placas (el vector de inyección masiva)
const limiterConsulta = rateLimit({
    windowMs: 1 * 60 * 1000, // 1 minuto
    max: parseInt(process.env.RATE_LIMIT_CONSULTA) || 20, // consultas de placa por IP por minuto
    standardHeaders: true,
    legacyHeaders: false,
    message: {
        success: false,
        error: 'Has excedido el límite de consultas por minuto, espera un momento',
        code: 'RATE_LIMITED_CONSULTA'
    }
});

// Aplicar el limitador general a toda la API
app.use(limiterGeneral);

// Variables globales
let databaseConnected = false;

// Función de validación de placas
function validarPlaca(placa) {
    if (!placa) {
        return { valida: false, error: 'El número de placa es requerido' };
    }
    
    const placaLimpia = placa.toString().trim().toUpperCase();
    
    if (placaLimpia.length === 0) {
        return { valida: false, error: 'El número de placa es requerido' };
    }
    
    if (placaLimpia.length < 5) {
        return { valida: false, error: 'El número de placa debe tener al menos 5 caracteres' };
    }
    
    if (placaLimpia.length > 10) {
        return { valida: false, error: 'El número de placa no puede tener más de 10 caracteres' };
    }
    
    if (!/^[A-Z0-9]+$/.test(placaLimpia)) {
        return { valida: false, error: 'El número de placa solo puede contener letras y números' };
    }
    
    return { valida: true, placa: placaLimpia };
}

// 🎯 FUNCIÓN PRINCIPAL: MySQL PRIMERO, luego CEDAH
async function consultarPlacaHibrida(placa, opciones = {}) {
    console.log(`🚀 Iniciando consulta HÍBRIDA para placa: ${placa}`);
    
    // Validar formato de placa
    const validacion = validarPlaca(placa);
    if (!validacion.valida) {
        console.log(`❌ Placa inválida: ${validacion.error}`);
        return {
            success: false,
            error: validacion.error,
            code: 'INVALID_FORMAT'
        };
    }
    
    const placaValidada = validacion.placa;
    console.log(`✅ Placa validada: ${placaValidada}`);
    
    try {
        // 🥇 PASO 1: Buscar PRIMERO en nuestra base de datos MySQL
        console.log(`🔍 PASO 1: Buscando placa ${placaValidada} en NUESTRA base de datos MySQL...`);
        
        if (databaseConnected) {
            const placaEnMySQL = await buscarPlaca(placaValidada);
            
            if (placaEnMySQL) {
                console.log(`🎉 ¡ENCONTRADA en nuestra MySQL! Placa: ${placaValidada}`);
                console.log(`📊 Datos de nuestra DB:`, placaEnMySQL);
                
                // ✅ RETORNAR INMEDIATAMENTE - No consultar CEDAH
                return {
                    success: true,
                    message: "Placa encontrada en nuestra base de datos",
                    placa: placaValidada,
                    source: "mysql_local",
                    data: {
                        data: [placaEnMySQL]
                    }
                };
            } else {
                console.log(`❌ Placa ${placaValidada} NO encontrada en nuestra MySQL`);
            }
        } else {
            console.log(`⚠️ Base de datos MySQL no conectada, saltando búsqueda local`);
        }
        
        // 🥈 PASO 2: Solo si NO existe en MySQL, consultar CEDAH
        console.log(`🔍 PASO 2: Placa no está en nuestra DB, consultando CEDAH original...`);
        
        const resultadoCedah = await consultarPlacaCedah(placaValidada);
        
        if (resultadoCedah.success === true) {
            console.log(`🎉 ¡ENCONTRADA en CEDAH original! Placa: ${placaValidada}`);
            
            // 💾 PASO 3 (Opcional): Guardar en nuestra DB para futuras consultas
            // ⚠️ Auto-guardado DESACTIVADO por defecto (fue el vector de la inyección masiva).
            //    Para reactivarlo conscientemente, define AUTOSAVE_CEDAH=true en el entorno.
            const autosaveHabilitado = process.env.AUTOSAVE_CEDAH === 'true';
            if (autosaveHabilitado && databaseConnected && opciones.guardarEnDB === true) {
                try {
                    console.log(`💾 Guardando placa ${placaValidada} en nuestra MySQL para futuras consultas...`);
                    
                    // Extraer datos del resultado de CEDAH
                    const datosCedah = resultadoCedah.data?.data?.[0];
                    if (datosCedah) {
                        await insertarPlaca({
                            placa: placaValidada,
                            tipo_transporte: datosCedah.tipo_transporte || 'NO ESPECIFICADO',
                            vigencia: datosCedah.vigencia || '2025-12-31',
                            estatus_actual_de_unidad: datosCedah.estatus_actual_de_unidad || 'CONSULTADO'
                        });
                        console.log(`✅ Placa ${placaValidada} guardada en nuestra MySQL`);
                    }
                } catch (errorGuardar) {
                    console.log(`⚠️ No se pudo guardar en MySQL: ${errorGuardar.message}`);
                    // No fallar la respuesta por esto
                }
            }
            
            // Devolver resultado de CEDAH pero marcado como fuente externa
            return {
                success: true,
                message: "Placa encontrada en CEDAH (guardada localmente)",
                placa: placaValidada,
                source: "cedah_original",
                data: resultadoCedah.data
            };
            
        } else if (resultadoCedah.success === "not_exist") {
            console.log(`❌ Placa ${placaValidada} NO EXISTE ni en nuestra DB ni en CEDAH`);
            
            return {
                success: "not_exist",
                message: "Placa no encontrada en ninguna base de datos",
                placa: placaValidada,
                source: "ambas_consultadas"
            };
            
        } else {
            console.log(`❌ Error en consulta CEDAH: ${resultadoCedah.error}`);
            
            return {
                success: false,
                error: "Error al consultar la información",
                code: 'BOTH_SOURCES_FAILED',
                details: resultadoCedah.error
            };
        }
        
    } catch (error) {
        console.error(`❌ Error en consulta híbrida para placa ${placaValidada}:`, error.message);
        
        return {
            success: false,
            error: "Error interno del servidor en consulta híbrida",
            code: 'HYBRID_ERROR',
            details: error.message
        };
    }
}

// 📍 ENDPOINTS DE LA API

// Health check
app.get('/health', async (req, res) => {
    const dbHealth = await healthCheck();
    
    res.json({
        status: 'ok',
        timestamp: new Date().toISOString(),
        database: dbHealth,
        connected: databaseConnected,
        mode: 'hybrid',
        priority: '1. MySQL Local -> 2. CEDAH Original',
        uptime: process.uptime()
    });
});

// Página raíz: en blanco (sin información)
app.get('/', (req, res) => {
    res.setHeader('Content-Type', 'text/html; charset=utf-8');
    res.status(200).send('<!doctype html><html lang="es"><head><meta charset="utf-8"><title></title><meta name="robots" content="noindex"></head><body></body></html>');
});

// Información de la API (documentación en JSON)
app.get('/info', (req, res) => {
    res.json({
        name: 'CEDAH API HÍBRIDA',
        version: '2.1.0',
        description: 'Sistema híbrido: Busca primero en MySQL local, luego en CEDAH original',
        publicUrl: PUBLIC_URL || null,
        environment: NODE_ENV,
        database: databaseConnected ? 'Conectada' : 'Desconectada',
        flujo: [
            '1. Buscar en nuestra base de datos MySQL',
            '2. Si existe: retornar inmediatamente (success: true)',
            '3. Si NO existe: consultar CEDAH original',
            '4. Si encuentra en CEDAH: guardar en nuestra DB y retornar',
            '5. Si no encuentra: retornar not_exist'
        ],
        endpoints: {
            'GET /health': 'Estado del sistema híbrido',
            'POST /api/consultar-placa': 'Consulta híbrida (JSON: {"placa": "914WZ8"})',
            'GET /api/consultar-placa/:placa': 'Consulta híbrida directa',
            'GET /api/listar-placas': 'Listar placas de nuestra MySQL',
            'GET /api/estatus/:estatus': 'Buscar por estatus en nuestra MySQL'
        },
        ejemplo: {
            consulta: 'GET /api/consultar-placa/914WZ8',
            respuesta_mysql: {
                success: true,
                source: 'mysql_local',
                message: 'Encontrada en nuestra base de datos'
            },
            respuesta_cedah: {
                success: true,
                source: 'cedah_original', 
                message: 'Encontrada en CEDAH (guardada localmente)'
            }
        }
    });
});

// POST - Consultar placa (HÍBRIDA)
app.post('/api/consultar-placa', limiterConsulta, async (req, res) => {
    const timestamp = new Date().toISOString();
    const { placa } = req.body;
    
    console.log(`${timestamp} - POST /api/consultar-placa (HÍBRIDA)`);
    console.log(`🔍 Consultando placa HÍBRIDA (POST): ${placa}`);
    
    const resultado = await consultarPlacaHibrida(placa);
    
    const statusCode = resultado.success === true ? 200 : 
                      resultado.success === "not_exist" ? 404 : 400;
    
    res.status(statusCode).json(resultado);
});

// GET - Consultar placa (HÍBRIDA)
app.get('/api/consultar-placa/:placa', limiterConsulta, async (req, res) => {
    const timestamp = new Date().toISOString();
    const { placa } = req.params;
    
    console.log(`${timestamp} - GET /api/consultar-placa/${placa} (HÍBRIDA)`);
    console.log(`🔍 Consultando placa HÍBRIDA (GET): ${placa}`);
    
    const resultado = await consultarPlacaHibrida(placa);
    
    const statusCode = resultado.success === true ? 200 : 
                      resultado.success === "not_exist" ? 404 : 400;
    
    res.status(statusCode).json(resultado);
});

// GET - Listar placas (solo de nuestra MySQL)
app.get('/api/listar-placas', async (req, res) => {
    try {
        if (!databaseConnected) {
            return res.status(503).json({
                success: false,
                error: 'Base de datos local no disponible',
                code: 'DATABASE_UNAVAILABLE'
            });
        }
        
        const limit = parseInt(req.query.limit) || 50;
        const offset = parseInt(req.query.offset) || 0;
        
        console.log(`📋 Listando placas de nuestra MySQL (limit: ${limit}, offset: ${offset})`);
        
        const placas = await listarPlacas(limit, offset);
        const total = await contarPlacas();
        
        res.json({
            success: true,
            total,
            limit,
            offset,
            count: placas.length,
            source: 'mysql_local',
            data: placas
        });
        
    } catch (error) {
        console.error('❌ Error al listar placas:', error.message);
        res.status(500).json({
            success: false,
            error: 'Error al obtener lista de placas',
            code: 'DATABASE_ERROR'
        });
    }
});

// GET - Buscar por estatus (solo en nuestra MySQL)
app.get('/api/estatus/:estatus', async (req, res) => {
    try {
        if (!databaseConnected) {
            return res.status(503).json({
                success: false,
                error: 'Base de datos local no disponible',
                code: 'DATABASE_UNAVAILABLE'
            });
        }
        
        const { estatus } = req.params;
        console.log(`🔍 Buscando placas con estatus: ${estatus} en nuestra MySQL`);
        
        const placas = await buscarPorEstatus(estatus);
        
        res.json({
            success: true,
            estatus: estatus.toUpperCase(),
            count: placas.length,
            source: 'mysql_local',
            data: placas
        });
        
    } catch (error) {
        console.error(`❌ Error al buscar por estatus ${req.params.estatus}:`, error.message);
        res.status(500).json({
            success: false,
            error: 'Error al buscar placas por estatus',
            code: 'DATABASE_ERROR'
        });
    }
});

// (El endpoint POST /api/agregar-placa fue eliminado por seguridad)

// Manejo de rutas no encontradas
app.use((req, res) => {
    res.status(404).json({
        success: false,
        error: 'Endpoint no encontrado',
        code: 'NOT_FOUND',
        available_endpoints: [
            'GET /health',
            'GET /',
            'POST /api/consultar-placa (HÍBRIDA)',
            'GET /api/consultar-placa/:placa (HÍBRIDA)',
            'GET /api/listar-placas (MySQL)',
            'GET /api/estatus/:estatus (MySQL)'
        ]
    });
});

// Inicializar servidor
async function startServer() {
    try {
        console.log('🚀 Iniciando CEDAH API Server HÍBRIDO...');
        console.log('🎯 FLUJO: 1. MySQL Local -> 2. CEDAH Original (si no existe)');
        
        // Inicializar conexión a la base de datos
        try {
            await initDatabase();
            databaseConnected = true;
            console.log('✅ Base de datos MySQL conectada - Modo HÍBRIDO activado');
        } catch (error) {
            console.log('⚠️ Base de datos MySQL no disponible - Solo funcionará CEDAH original');
            databaseConnected = false;
        }
        
        // Iniciar servidor HTTP
        app.listen(PORT, () => {
            console.log('\n🚀 CEDAH API Server HÍBRIDO iniciado');
            if (PUBLIC_URL) {
                console.log(`📍 URL pública: ${PUBLIC_URL}`);
            }
            console.log(`📍 URL local: http://localhost:${PORT}`);
            console.log(`🔗 Health Check: http://localhost:${PORT}/health`);
            console.log(`📖 Documentación: http://localhost:${PORT}/info`);
            console.log('\n🎯 FLUJO DE CONSULTA:');
            console.log('   1️⃣ Buscar en MySQL Local (nuestra DB)');
            console.log('   2️⃣ Si existe: retornar success: true');
            console.log('   3️⃣ Si NO existe: consultar CEDAH original');
            console.log('   4️⃣ Si encuentra en CEDAH: guardar + retornar');
            console.log('\n📊 Endpoints disponibles:');
            console.log('   POST /api/consultar-placa (HÍBRIDA)');
            console.log('   GET  /api/consultar-placa/:placa (HÍBRIDA)');
            console.log('   GET  /api/listar-placas (MySQL)');
            console.log('   GET  /api/estatus/:estatus (MySQL)');
            console.log('   GET  /health');
            console.log('\n✨ Servidor HÍBRIDO listo - MySQL PRIMERO, CEDAH después');
        });
        
    } catch (error) {
        console.error('❌ Error al inicializar el servidor:', error.message);
        process.exit(1);
    }
}

// Manejo de cierre graceful
process.on('SIGINT', async () => {
    console.log('\n👋 Cerrando servidor híbrido...');
    if (databaseConnected) {
        await closeDatabase();
    }
    process.exit(0);
});

process.on('SIGTERM', async () => {
    console.log('\n👋 Cerrando servidor híbrido...');
    if (databaseConnected) {
        await closeDatabase();
    }
    process.exit(0);
});

// Iniciar el servidor
if (require.main === module) {
    startServer();
}

// Exportar la app para pruebas y el startServer para arranque desde app.js (cPanel)
module.exports = app;
module.exports.startServer = startServer;