const express = require('express');
const router = express.Router();
const db = require('../config/db');
var puppeteer = null;
try {
    puppeteer = require('puppeteer-extra');
    const StealthPlugin = require('puppeteer-extra-plugin-stealth');
    puppeteer.use(StealthPlugin());
} catch (e) {
    console.warn('[TIPO_CAMBIO] Puppeteer no disponible, importación SUNAT deshabilitada:', e.message);
}

const SUNAT_TC_URL = 'https://www.sunat.gob.pe/cl-at-ittipcam/tcS01Alias';

// ============================================================
// GET /tipo-cambio — Listar con filtros
// ============================================================
router.get('/tipo-cambio', async function(req, res) {
    try {
        var idEmpresa = req.query.id_empresa ? parseInt(req.query.id_empresa) : null;
        if (!idEmpresa) return res.status(400).json({ ok: false, mensaje: 'Empresa requerida' });

        var fechaDesde = req.query.fecha_desde || '';
        var fechaHasta = req.query.fecha_hasta || '';
        var mes = req.query.mes ? parseInt(req.query.mes) : null;
        var anio = req.query.anio ? parseInt(req.query.anio) : null;
        var page = parseInt(req.query.page) || 1;
        var limit = parseInt(req.query.limit) || 50;
        var sinPaginacion = limit <= 0;

        var where = 'WHERE id_empresa = @id_empresa';
        var params = { id_empresa: { type: db.sql.Int, value: idEmpresa } };

        if (fechaDesde) {
            where += ' AND fecha >= @fechaDesde';
            params.fechaDesde = { type: db.sql.Date, value: fechaDesde };
        }
        if (fechaHasta) {
            where += ' AND fecha <= @fechaHasta';
            params.fechaHasta = { type: db.sql.Date, value: fechaHasta };
        }
        if (mes && anio) {
            where += ' AND MONTH(fecha) = @mes AND YEAR(fecha) = @anio';
            params.mes = { type: db.sql.Int, value: mes };
            params.anio = { type: db.sql.Int, value: anio };
        } else if (anio) {
            where += ' AND YEAR(fecha) = @anio';
            params.anio = { type: db.sql.Int, value: anio };
        }

        var sqlCount = 'SELECT COUNT(*) as total FROM tipo_cambio ' + where;
        var countResult = await db.query(sqlCount, params);
        var total = countResult[0].total;
        var totalPaginas = total > 0 ? Math.ceil(total / Math.abs(limit)) : 0;

        var sqlData;
        if (sinPaginacion) {
            sqlData = 'SELECT id_empresa, fecha, compra, venta, fuente FROM tipo_cambio ' + where + ' ORDER BY fecha DESC';
        } else {
            var offset = (page - 1) * limit;
            sqlData = 'SELECT id_empresa, fecha, compra, venta, fuente FROM tipo_cambio ' + where + ' ORDER BY fecha DESC OFFSET @offset ROWS FETCH NEXT @limit ROWS ONLY';
            params.offset = { type: db.sql.Int, value: offset };
            params.limit = { type: db.sql.Int, value: limit };
        }

        var data = await db.query(sqlData, params);
        res.json({ ok: true, data: data, total: total, totalPaginas: totalPaginas, page: page });
    } catch (error) {
        console.error('[TIPO_CAMBIO] Error al listar:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al listar tipo de cambio', error: error.message });
    }
});

// ============================================================
// GET /tipo-cambio/actual — Obtener tipo de cambio del día actual
// ============================================================
router.get('/tipo-cambio/actual', async function(req, res) {
    try {
        var idEmpresa = req.query.id_empresa ? parseInt(req.query.id_empresa) : null;
        if (!idEmpresa) return res.status(400).json({ ok: false, mensaje: 'Empresa requerida' });

        var data = await db.query(
            'SELECT id_empresa, fecha, compra, venta, fuente FROM tipo_cambio WHERE id_empresa = @id_empresa ORDER BY fecha DESC',
            { id_empresa: { type: db.sql.Int, value: idEmpresa } }
        );
        if (data.length === 0) return res.json({ ok: true, data: null });
        res.json({ ok: true, data: data[0] });
    } catch (error) {
        console.error('[TIPO_CAMBIO] Error al obtener actual:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al obtener tipo de cambio actual', error: error.message });
    }
});

// ============================================================
// GET /tipo-cambio/:fecha — Obtener uno por fecha
// ============================================================
router.get('/tipo-cambio/:fecha', async function(req, res) {
    try {
        var idEmpresa = req.query.id_empresa ? parseInt(req.query.id_empresa) : null;
        if (!idEmpresa) return res.status(400).json({ ok: false, mensaje: 'Empresa requerida' });

        var data = await db.query(
            'SELECT id_empresa, fecha, compra, venta, fuente FROM tipo_cambio WHERE id_empresa = @id_empresa AND fecha = @fecha',
            { id_empresa: { type: db.sql.Int, value: idEmpresa }, fecha: { type: db.sql.Date, value: req.params.fecha } }
        );
        if (data.length === 0) return res.status(404).json({ ok: false, mensaje: 'Tipo de cambio no encontrado' });
        res.json({ ok: true, data: data[0] });
    } catch (error) {
        console.error('[TIPO_CAMBIO] Error al obtener:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al obtener tipo de cambio', error: error.message });
    }
});

// ============================================================
// POST /tipo-cambio — Crear (ingreso manual)
// ============================================================
router.post('/tipo-cambio', async function(req, res) {
    try {
        var idEmpresa = req.body.id_empresa ? parseInt(req.body.id_empresa) : null;
        if (!idEmpresa) return res.status(400).json({ ok: false, mensaje: 'Empresa requerida' });

        var fecha = req.body.fecha;
        var compra = parseFloat(req.body.compra) || 0;
        var venta = parseFloat(req.body.venta) || 0;

        if (!fecha) return res.status(400).json({ ok: false, mensaje: 'La fecha es requerida' });
        if (compra <= 0 || venta <= 0) return res.status(400).json({ ok: false, mensaje: 'Compra y venta deben ser mayores a 0' });

        var existing = await db.query(
            'SELECT COUNT(*) as cnt FROM tipo_cambio WHERE id_empresa = @id_empresa AND fecha = @fecha',
            { id_empresa: { type: db.sql.Int, value: idEmpresa }, fecha: { type: db.sql.Date, value: fecha } }
        );
        if (existing[0].cnt > 0) {
            return res.status(400).json({ ok: false, mensaje: 'Ya existe un tipo de cambio para esta fecha' });
        }

        await db.execute(
            'INSERT INTO tipo_cambio (id_empresa, fecha, compra, venta, fuente) VALUES (@id_empresa, @fecha, @compra, @venta, @fuente)',
            {
                id_empresa: { type: db.sql.Int, value: idEmpresa },
                fecha: { type: db.sql.Date, value: fecha },
                compra: { type: db.sql.Decimal(8, 4), value: compra },
                venta: { type: db.sql.Decimal(8, 4), value: venta },
                fuente: { type: db.sql.VarChar(20), value: 'MANUAL' }
            }
        );
        res.json({ ok: true, mensaje: 'Tipo de cambio registrado' });
    } catch (error) {
        console.error('[TIPO_CAMBIO] Error al crear:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al registrar tipo de cambio', error: error.message });
    }
});

// ============================================================
// PUT /tipo-cambio/:fecha — Actualizar
// ============================================================
router.put('/tipo-cambio/:fecha', async function(req, res) {
    try {
        var idEmpresa = req.body.id_empresa ? parseInt(req.body.id_empresa) : null;
        if (!idEmpresa) return res.status(400).json({ ok: false, mensaje: 'Empresa requerida' });

        var compra = parseFloat(req.body.compra) || 0;
        var venta = parseFloat(req.body.venta) || 0;

        if (compra <= 0 || venta <= 0) return res.status(400).json({ ok: false, mensaje: 'Compra y venta deben ser mayores a 0' });

        var existing = await db.query(
            'SELECT COUNT(*) as cnt FROM tipo_cambio WHERE id_empresa = @id_empresa AND fecha = @fecha',
            { id_empresa: { type: db.sql.Int, value: idEmpresa }, fecha: { type: db.sql.Date, value: req.params.fecha } }
        );
        if (existing[0].cnt === 0) {
            return res.status(404).json({ ok: false, mensaje: 'Tipo de cambio no encontrado' });
        }

        await db.execute(
            'UPDATE tipo_cambio SET compra = @compra, venta = @venta, fuente = @fuente WHERE id_empresa = @id_empresa AND fecha = @fecha',
            {
                id_empresa: { type: db.sql.Int, value: idEmpresa },
                fecha: { type: db.sql.Date, value: req.params.fecha },
                compra: { type: db.sql.Decimal(8, 4), value: compra },
                venta: { type: db.sql.Decimal(8, 4), value: venta },
                fuente: { type: db.sql.VarChar(20), value: req.body.fuente || 'MANUAL' }
            }
        );
        res.json({ ok: true, mensaje: 'Tipo de cambio actualizado' });
    } catch (error) {
        console.error('[TIPO_CAMBIO] Error al actualizar:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al actualizar tipo de cambio', error: error.message });
    }
});

// ============================================================
// DELETE /tipo-cambio/:fecha — Eliminar
// ============================================================
router.delete('/tipo-cambio/:fecha', async function(req, res) {
    try {
        var idEmpresa = req.query.id_empresa ? parseInt(req.query.id_empresa) : null;
        if (!idEmpresa) return res.status(400).json({ ok: false, mensaje: 'Empresa requerida' });

        var existing = await db.query(
            'SELECT COUNT(*) as cnt FROM tipo_cambio WHERE id_empresa = @id_empresa AND fecha = @fecha',
            { id_empresa: { type: db.sql.Int, value: idEmpresa }, fecha: { type: db.sql.Date, value: req.params.fecha } }
        );
        if (existing[0].cnt === 0) {
            return res.status(404).json({ ok: false, mensaje: 'Tipo de cambio no encontrado' });
        }

        await db.execute(
            'DELETE FROM tipo_cambio WHERE id_empresa = @id_empresa AND fecha = @fecha',
            { id_empresa: { type: db.sql.Int, value: idEmpresa }, fecha: { type: db.sql.Date, value: req.params.fecha } }
        );
        res.json({ ok: true, mensaje: 'Tipo de cambio eliminado' });
    } catch (error) {
        console.error('[TIPO_CAMBIO] Error al eliminar:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al eliminar tipo de cambio', error: error.message });
    }
});

// ============================================================
// POST /tipo-cambio/importar-sunat — Scraping desde SUNAT
// ============================================================
router.post('/tipo-cambio/importar-sunat', async function(req, res) {
    var idEmpresa = req.body.id_empresa ? parseInt(req.body.id_empresa) : null;
    if (!idEmpresa) return res.status(400).json({ ok: false, mensaje: 'Empresa requerida' });

    var mes = parseInt(req.body.mes);
    var anio = parseInt(req.body.anio);

    if (!mes || !anio || mes < 1 || mes > 12) {
        return res.status(400).json({ ok: false, mensaje: 'Mes y año son requeridos (mes: 1-12)' });
    }

    var browser = null;
    try {
        // Intentar Browserless.io (entorno cloud/web), fallback a Chrome local
        var sunatCfg = { BROWSERLESS_TOKEN: '' };
        try { sunatCfg = require('./sunat-config'); } catch (_) {}
        var wsToken = sunatCfg.BROWSERLESS_TOKEN || process.env.BROWSERLESS_TOKEN;
        if (wsToken) {
            try {
                browser = await puppeteer.connect({ browserWSEndpoint: 'wss://chrome.browserless.io?token=' + wsToken, defaultViewport: { width: 1280, height: 900 } });
            } catch (e) {
                console.log('[TC] Browserless falló, intentando Chrome local:', e.message);
            }
        }
        if (!browser) {
            var localPaths = [
                process.env.CHROME_PATH,
                'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
                'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe'
            ].filter(Boolean);
            for (var p = 0; p < localPaths.length; p++) {
                try { browser = await puppeteer.launch({ executablePath: localPaths[p], headless: true }); break; }
                catch (_) {}
            }
        }
        if (!browser) {
            return res.status(500).json({ ok: false, mensaje: 'No se pudo iniciar Chrome (ni Browserless ni local)' });
        }

        var page = await browser.newPage();
        await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36');
        await page.setViewport({ width: 1280, height: 900 });

        await page.goto(SUNAT_TC_URL, { waitUntil: 'domcontentloaded', timeout: 20000 });
        await page.waitForFunction(function() {
            return document.querySelector('.calendar-table') || document.body.textContent.indexOf('Compra') >= 0;
        }, { timeout: 15000 });

        console.log('[TC] Navegando a mes ' + mes + '/' + anio + ' via recargarCalendario...');
        await page.evaluate(function(anho, mes0) {
            var data = {};
            data.anhoConsulta = anho;
            data.mesConsulta = mes0;
            data.diaConsulta = 1;
            data.indMes = '1';
            data.mode = 'month';
            if (typeof recargarCalendario === 'function') {
                recargarCalendario(data);
            }
        }, anio, mes - 1);

        await new Promise(function(r) { setTimeout(r, 3000); });

        var debugInfo = await page.evaluate(function() {
            var header = document.querySelector('.cal-header, .month-header, .calendar-header');
            var headerText = header ? header.textContent.trim().substring(0, 80) : 'NO HEADER';
            var cells = document.querySelectorAll('.calendar-table td');
            var texts = [];
            for (var i = 0; i < Math.min(cells.length, 10); i++) {
                texts.push(cells[i].textContent.trim().substring(0, 80));
            }
            return { header: headerText, tdCount: cells.length, samples: texts, url: window.location.href };
        });
        console.log('[TC] Debug:', JSON.stringify(debugInfo));

        var datos = await page.evaluate(function(anio, mes) {
            var rows = [];
            var cells = document.querySelectorAll('.calendar-table td');
            for (var i = 0; i < cells.length; i++) {
                var text = cells[i].textContent || '';
                var trimmed = text.trim();
                var dayMatch = trimmed.match(/^(\d{1,2})\s*Compra\s+([\d.]+)\s*Venta\s+([\d.]+)/);
                if (dayMatch) {
                    var day = parseInt(dayMatch[1]);
                    var compra = parseFloat(dayMatch[2]);
                    var venta = parseFloat(dayMatch[3]);
                    if (!isNaN(compra) && !isNaN(venta) && compra > 0 && venta > 0) {
                        var mm = String(mes).padStart(2, '0');
                        var dd = String(day).padStart(2, '0');
                        rows.push({ fecha: anio + '-' + mm + '-' + dd, compra: compra, venta: venta });
                    }
                }
            }
            return rows;
        }, anio, mes);

        console.log('[TC] Filas extraídas:', datos.length);

        if (datos.length === 0) {
            return res.json({ ok: false, mensaje: 'No se encontraron datos de tipo de cambio para ' + mes + '/' + anio });
        }

        var insertados = 0, actualizados = 0, ignorados = 0;

        for (var i = 0; i < datos.length; i++) {
            var d = datos[i];
            var existing = await db.query(
                'SELECT COUNT(*) as cnt FROM tipo_cambio WHERE id_empresa = @id_empresa AND fecha = @fecha',
                { id_empresa: { type: db.sql.Int, value: idEmpresa }, fecha: { type: db.sql.Date, value: d.fecha } }
            );

            if (existing[0].cnt > 0) {
                await db.execute(
                    'UPDATE tipo_cambio SET compra = @compra, venta = @venta, fuente = \'SUNAT\' WHERE id_empresa = @id_empresa AND fecha = @fecha',
                    {
                        id_empresa: { type: db.sql.Int, value: idEmpresa },
                        fecha: { type: db.sql.Date, value: d.fecha },
                        compra: { type: db.sql.Decimal(8, 4), value: d.compra },
                        venta: { type: db.sql.Decimal(8, 4), value: d.venta }
                    }
                );
                actualizados++;
            } else {
                await db.execute(
                    'INSERT INTO tipo_cambio (id_empresa, fecha, compra, venta, fuente) VALUES (@id_empresa, @fecha, @compra, @venta, \'SUNAT\')',
                    {
                        id_empresa: { type: db.sql.Int, value: idEmpresa },
                        fecha: { type: db.sql.Date, value: d.fecha },
                        compra: { type: db.sql.Decimal(8, 4), value: d.compra },
                        venta: { type: db.sql.Decimal(8, 4), value: d.venta }
                    }
                );
                insertados++;
            }
        }

        // Completar días faltantes solo hasta la última fecha con datos de SUNAT
        var primerDia = new Date(anio, mes - 1, 1);
        var ultimaFechaSUNAT = datos[datos.length - 1].fecha;
        var primerDiaStr = anio + '-' + String(mes).padStart(2, '0') + '-01';
        var completados = 0;
        var ultimoConocido = null;

        // Eliminar registros futuros del mes que ya no tienen datos en SUNAT
        await db.execute(
            'DELETE FROM tipo_cambio WHERE id_empresa = @id_empresa AND fecha >= @primerDia AND fecha > @ultimaFecha',
            { id_empresa: { type: db.sql.Int, value: idEmpresa }, primerDia: { type: db.sql.Date, value: primerDiaStr }, ultimaFecha: { type: db.sql.Date, value: ultimaFechaSUNAT } }
        );

        // Buscar el último tipo de cambio antes del primer día del mes
        var antesMes = await db.query(
            'SELECT fecha, compra, venta FROM tipo_cambio WHERE id_empresa = @id_empresa AND fecha < @primerDia ORDER BY fecha DESC',
            { id_empresa: { type: db.sql.Int, value: idEmpresa }, primerDia: { type: db.sql.Date, value: primerDia.toISOString().split('T')[0] } }
        );
        if (antesMes.length > 0) {
            ultimoConocido = { compra: antesMes[0].compra, venta: antesMes[0].venta };
        }

        for (var d = new Date(anio, mes - 1, 1); ; d.setDate(d.getDate() + 1)) {
            var diaSemana = d.getDay();
            if (diaSemana === 0 || diaSemana === 6) continue;

            var mm = String(d.getMonth() + 1).padStart(2, '0');
            var dd = String(d.getDate()).padStart(2, '0');
            var fechaStr = anio + '-' + mm + '-' + dd;

            if (fechaStr > ultimaFechaSUNAT) break;
            var check = await db.query(
                'SELECT COUNT(*) as cnt FROM tipo_cambio WHERE id_empresa = @id_empresa AND fecha = @fecha',
                { id_empresa: { type: db.sql.Int, value: idEmpresa }, fecha: { type: db.sql.Date, value: fechaStr } }
            );

            if (check[0].cnt === 0 && ultimoConocido) {
                await db.execute(
                    'INSERT INTO tipo_cambio (id_empresa, fecha, compra, venta, fuente) VALUES (@id_empresa, @fecha, @compra, @venta, \'SUNAT\')',
                    {
                        id_empresa: { type: db.sql.Int, value: idEmpresa },
                        fecha: { type: db.sql.Date, value: fechaStr },
                        compra: { type: db.sql.Decimal(8, 4), value: ultimoConocido.compra },
                        venta: { type: db.sql.Decimal(8, 4), value: ultimoConocido.venta }
                    }
                );
                completados++;
            } else if (check[0].cnt > 0) {
                var known = await db.query(
                    'SELECT compra, venta FROM tipo_cambio WHERE id_empresa = @id_empresa AND fecha = @fecha',
                    { id_empresa: { type: db.sql.Int, value: idEmpresa }, fecha: { type: db.sql.Date, value: fechaStr } }
                );
                if (known.length > 0) {
                    ultimoConocido = { compra: known[0].compra, venta: known[0].venta };
                }
            }
        }

        res.json({
            ok: true,
            mensaje: 'Importación completada',
            insertados: insertados,
            actualizados: actualizados,
            completados_faltantes: completados,
            total_dias: datos.length
        });

    } catch (error) {
        console.error('[TIPO_CAMBIO] Error en scraping SUNAT:', error.message);
        res.status(500).json({ ok: false, mensaje: 'Error al importar desde SUNAT: ' + (error.message || 'sin respuesta') });
    } finally {
        if (browser) {
            try { await browser.close(); } catch (_) {}
        }
    }
});



module.exports = router;
