import { Router } from 'express';
import multer from 'multer';
import path from 'node:path';
import fs from 'node:fs';
import { fileURLToPath } from 'node:url';
import db from '../db/init.js';
import { sqlAll, sqlId, sqlOne } from '../db/helpers.js';
import { verificarToken } from '../middleware/auth.js';
import { calcularCosteLinea, redondearCoste } from '../services/coste.js';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const uploadsDir = path.join(__dirname, '../../uploads');
if (!fs.existsSync(uploadsDir)) {
    fs.mkdirSync(uploadsDir, { recursive: true });
}
const storage = multer.diskStorage({
    destination: (_req, _file, cb) => cb(null, uploadsDir),
    filename: (_req, file, cb) => {
        const unico = `${Date.now()}-${Math.round(Math.random() * 1e9)}`;
        cb(null, `${unico}${path.extname(file.originalname)}`);
    },
});
const upload = multer({
    storage,
    limits: { fileSize: 5 * 1024 * 1024 },
    fileFilter: (_req, file, cb) => {
        if (file.mimetype.startsWith('image/'))
            cb(null, true);
        else
            cb(new Error('Solo se permiten imágenes'));
    },
});
const router = Router();
router.use(verificarToken);
function recalcularCosteTotal(articuloId) {
    const suma = sqlOne(db.prepare('SELECT COALESCE(SUM(coste_linea), 0) as total FROM articulo_gastos WHERE articulo_id = ?')
        .get(articuloId));
    const total = redondearCoste(suma?.total ?? 0, 2);
    db.prepare(`
    UPDATE articulos SET coste_total = ?, fecha_actualizacion = datetime('now') WHERE id = ?
  `).run(total, articuloId);
    return total;
}
function obtenerLineas(articuloId) {
    return sqlAll(db.prepare(`
    SELECT ag.*, g.nombre as gasto_nombre
    FROM articulo_gastos ag
    LEFT JOIN gastos g ON g.id = ag.gasto_id
    WHERE ag.articulo_id = ?
    ORDER BY ag.id ASC
  `).all(articuloId));
}
router.get('/', (_req, res) => {
    const articulos = sqlAll(db.prepare('SELECT * FROM articulos ORDER BY titulo ASC').all());
    res.json(articulos);
});
router.get('/:id', (req, res) => {
    const id = sqlId(req.params.id);
    const articulo = sqlOne(db.prepare('SELECT * FROM articulos WHERE id = ?').get(id));
    if (!articulo) {
        res.status(404).json({ error: 'Artículo no encontrado' });
        return;
    }
    const lineas = obtenerLineas(id);
    res.json({ ...articulo, lineas });
});
router.post('/', (req, res) => {
    const { titulo, descripcion, importe } = req.body;
    if (!titulo) {
        res.status(400).json({ error: 'El título es obligatorio' });
        return;
    }
    const resultado = db.prepare(`
    INSERT INTO articulos (titulo, descripcion, importe, coste_total)
    VALUES (?, ?, ?, 0)
  `).run(titulo, descripcion ?? null, importe ?? null);
    const articulo = sqlOne(db.prepare('SELECT * FROM articulos WHERE id = ?').get(Number(resultado.lastInsertRowid)));
    res.status(201).json({ ...articulo, lineas: [] });
});
router.put('/:id', (req, res) => {
    const id = sqlId(req.params.id);
    const existente = sqlOne(db.prepare('SELECT * FROM articulos WHERE id = ?').get(id));
    if (!existente) {
        res.status(404).json({ error: 'Artículo no encontrado' });
        return;
    }
    const { titulo, descripcion, importe } = req.body;
    db.prepare(`
    UPDATE articulos
    SET titulo = ?, descripcion = ?, importe = ?, fecha_actualizacion = datetime('now')
    WHERE id = ?
  `).run(titulo ?? existente.titulo, descripcion !== undefined ? descripcion : existente.descripcion, importe !== undefined ? importe : existente.importe, id);
    const articulo = sqlOne(db.prepare('SELECT * FROM articulos WHERE id = ?').get(id));
    const lineas = obtenerLineas(id);
    res.json({ ...articulo, lineas });
});
router.delete('/:id', (req, res) => {
    const id = sqlId(req.params.id);
    const resultado = db.prepare('DELETE FROM articulos WHERE id = ?').run(id);
    if (Number(resultado.changes) === 0) {
        res.status(404).json({ error: 'Artículo no encontrado' });
        return;
    }
    res.status(204).send();
});
router.post('/:id/foto', upload.single('foto'), (req, res) => {
    const id = sqlId(req.params.id);
    const articulo = sqlOne(db.prepare('SELECT * FROM articulos WHERE id = ?').get(id));
    if (!articulo) {
        res.status(404).json({ error: 'Artículo no encontrado' });
        return;
    }
    if (!req.file) {
        res.status(400).json({ error: 'No se recibió ninguna imagen' });
        return;
    }
    const fotoUrl = `/uploads/${req.file.filename}`;
    db.prepare(`
    UPDATE articulos SET foto_url = ?, fecha_actualizacion = datetime('now') WHERE id = ?
  `).run(fotoUrl, id);
    res.json({ foto_url: fotoUrl });
});
router.get('/:id/gastos', (req, res) => {
    const id = sqlId(req.params.id);
    const articulo = sqlOne(db.prepare('SELECT id FROM articulos WHERE id = ?').get(id));
    if (!articulo) {
        res.status(404).json({ error: 'Artículo no encontrado' });
        return;
    }
    res.json(obtenerLineas(id));
});
router.post('/:id/gastos', (req, res) => {
    const articuloId = sqlId(req.params.id);
    const articulo = sqlOne(db.prepare('SELECT id FROM articulos WHERE id = ?').get(articuloId));
    if (!articulo) {
        res.status(404).json({ error: 'Artículo no encontrado' });
        return;
    }
    const { gasto_id, cantidad_usada, unidad_usada, coste_linea, es_manual, notas, } = req.body;
    let costeFinal;
    let esManual = es_manual ? 1 : 0;
    if (gasto_id) {
        const gasto = sqlOne(db.prepare('SELECT * FROM gastos WHERE id = ?').get(gasto_id));
        if (!gasto) {
            res.status(404).json({ error: 'Gasto no encontrado' });
            return;
        }
        if (cantidad_usada == null || !unidad_usada) {
            res.status(400).json({ error: 'Cantidad y unidad son obligatorias' });
            return;
        }
        if (es_manual && coste_linea != null) {
            costeFinal = redondearCoste(coste_linea, 2);
            esManual = 1;
        }
        else {
            try {
                costeFinal = redondearCoste(calcularCosteLinea(gasto, cantidad_usada, unidad_usada), 2);
                esManual = 0;
            }
            catch (error) {
                res.status(400).json({ error: error.message });
                return;
            }
        }
    }
    else {
        if (coste_linea == null) {
            res.status(400).json({ error: 'Coste de línea obligatorio para gastos manuales' });
            return;
        }
        costeFinal = redondearCoste(coste_linea, 2);
        esManual = 1;
    }
    const resultado = db.prepare(`
    INSERT INTO articulo_gastos (articulo_id, gasto_id, cantidad_usada, unidad_usada, coste_linea, es_manual, notas)
    VALUES (?, ?, ?, ?, ?, ?, ?)
  `).run(articuloId, gasto_id ?? null, cantidad_usada ?? 0, unidad_usada ?? 'ud', costeFinal, esManual, notas ?? null);
    recalcularCosteTotal(articuloId);
    const linea = sqlOne(db.prepare(`
    SELECT ag.*, g.nombre as gasto_nombre
    FROM articulo_gastos ag
    LEFT JOIN gastos g ON g.id = ag.gasto_id
    WHERE ag.id = ?
  `).get(Number(resultado.lastInsertRowid)));
    res.status(201).json(linea);
});
router.put('/:id/gastos/:lineaId', (req, res) => {
    const articuloId = sqlId(req.params.id);
    const lineaId = sqlId(req.params.lineaId);
    const lineaExistente = sqlOne(db.prepare('SELECT * FROM articulo_gastos WHERE id = ? AND articulo_id = ?')
        .get(lineaId, articuloId));
    if (!lineaExistente) {
        res.status(404).json({ error: 'Línea no encontrada' });
        return;
    }
    const { gasto_id, cantidad_usada, unidad_usada, coste_linea, es_manual, notas, } = req.body;
    const nuevoGastoId = gasto_id !== undefined ? gasto_id : lineaExistente.gasto_id;
    const nuevaCantidad = cantidad_usada ?? lineaExistente.cantidad_usada;
    const nuevaUnidad = unidad_usada ?? lineaExistente.unidad_usada;
    const nuevasNotas = notas !== undefined ? notas : lineaExistente.notas;
    let costeFinal = lineaExistente.coste_linea;
    let esManual = es_manual ? 1 : lineaExistente.es_manual;
    if (nuevoGastoId) {
        const gasto = sqlOne(db.prepare('SELECT * FROM gastos WHERE id = ?').get(nuevoGastoId));
        if (!gasto) {
            res.status(404).json({ error: 'Gasto no encontrado' });
            return;
        }
        if (es_manual && coste_linea != null) {
            costeFinal = redondearCoste(coste_linea, 2);
            esManual = 1;
        }
        else {
            try {
                costeFinal = redondearCoste(calcularCosteLinea(gasto, nuevaCantidad, nuevaUnidad), 2);
                esManual = 0;
            }
            catch (error) {
                res.status(400).json({ error: error.message });
                return;
            }
        }
    }
    else if (coste_linea != null) {
        costeFinal = redondearCoste(coste_linea, 2);
        esManual = 1;
    }
    db.prepare(`
    UPDATE articulo_gastos
    SET gasto_id = ?, cantidad_usada = ?, unidad_usada = ?, coste_linea = ?, es_manual = ?, notas = ?
    WHERE id = ?
  `).run(nuevoGastoId, nuevaCantidad, nuevaUnidad, costeFinal, esManual, nuevasNotas, lineaId);
    recalcularCosteTotal(articuloId);
    const linea = sqlOne(db.prepare(`
    SELECT ag.*, g.nombre as gasto_nombre
    FROM articulo_gastos ag
    LEFT JOIN gastos g ON g.id = ag.gasto_id
    WHERE ag.id = ?
  `).get(lineaId));
    res.json(linea);
});
router.delete('/:id/gastos/:lineaId', (req, res) => {
    const articuloId = sqlId(req.params.id);
    const lineaId = sqlId(req.params.lineaId);
    const resultado = db
        .prepare('DELETE FROM articulo_gastos WHERE id = ? AND articulo_id = ?')
        .run(lineaId, articuloId);
    if (Number(resultado.changes) === 0) {
        res.status(404).json({ error: 'Línea no encontrada' });
        return;
    }
    recalcularCosteTotal(articuloId);
    res.status(204).send();
});
export default router;
