// services/manso/src/api/v1/routes/routes.js

import { Router } from 'express';
import pool from '#db'; // Pool Singleton
const router = Router();

// ==========================================================
// Rutas de API v1
// ==========================================================



// ----------------------------------------------------------
// API Comandas
// ----------------------------------------------------------

router.route('/comandas').get( async (req, res, next) => {
  try {
    var client = await pool.getClient()
    const estado = (req.query.estado || '').trim() || null;
    const limit  = Math.min(parseInt(req.query.limit || '200', 10), 1000);

    const { rows } = await client.query(
      `SELECT * FROM public.f_comandas_resumen($1, $2)`,
      [estado, limit]
    );
    res.json(rows);
  } catch (e) {
    next(e); 
  } finally {
    client.release();
  }
});

router.route('/comandas/:id/detalle').get( async (req, res, next) => {
  try {
    const client = await pool.getClient()
    client.query(
      `SELECT id_det_comanda, id_producto, producto_nombre,
              cantidad, pre_unitario, subtotal, observaciones
        FROM public.v_comandas_detalle_items
        WHERE id_comanda = $1::int
        ORDER BY id_det_comanda`,
      [req.params.id]
    )
    .then(r => res.json(r.rows))
    .catch(next)
    client.release();
  } catch (error) {
    next(e);
  }
});

router.route('/comandas/:id/cerrar').post( async (req, res, next) => {
  try {
    const client = await pool.getClient()
    const id = Number(req.params.id);
    if (!Number.isInteger(id) || id <= 0) {
      return res.status(400).json({ error: 'id inválido' });
    }
    const { rows } = await client.query(
      `SELECT public.f_cerrar_comanda($1) AS data`,
      [id]
    );
    if (!rows.length || rows[0].data === null) {
      return res.status(404).json({ error: 'Comanda no encontrada' });
    }
    res.json(rows[0].data);
    client.release();
  } catch (err) { next(err); }
});

router.route('/comandas/:id/abrir').post( async (req, res, next) => {
  try {
    const client = await pool.getClient()
    const id = Number(req.params.id);
    if (!Number.isInteger(id) || id <= 0) {
      return res.status(400).json({ error: 'id inválido' });
    }
    const { rows } = await client.query(
      `SELECT public.f_abrir_comanda($1) AS data`,
      [id]
    );
    if (!rows.length || rows[0].data === null) {
      return res.status(404).json({ error: 'Comanda no encontrada' });
    }
    res.json(rows[0].data);
    client.release();
  } catch (err) { next(err); }
});



// ----------------------------------------------------------
// API Productos
// ----------------------------------------------------------

// GET producto + receta
router.route('/rpc/get_producto/:id').get( async (req, res) => {
  const client = await pool.getClient()
  const id = Number(req.params.id);
  const { rows } = await client.query('SELECT public.get_producto($1) AS data', [id]);
  res.json(rows[0]?.data || {});
  client.release();
});

// POST guardar producto + receta
router.route('/rpc/save_producto').post(async (req, res) => {
  try {
    // console.debug('receta payload:', req.body?.receta); // habilitalo si lo necesitás
    const client = await pool.getClient()
    const q = 'SELECT public.save_producto($1,$2,$3,$4,$5,$6,$7::jsonb) AS id_producto';
    const { id_producto=null, nombre, img_producto=null, precio=0, activo=true, id_categoria=null, receta=[] } = req.body || {};
    const params = [id_producto, nombre, img_producto, precio, activo, id_categoria, JSON.stringify(receta||[])];
    const { rows } = await client.query(q, params);
    res.json(rows[0] || {});
    client.release();
  } catch(e) {
    console.error(e);
    res.status(500).json({ error: 'save_producto failed' });
  }
});



// ----------------------------------------------------------
// API Materias Primas
// ----------------------------------------------------------

// GET MP + proveedores
router.route('/rpc/get_materia/:id').get(async (req, res) => {
  const id = Number(req.params.id);
  try {
    const client = await pool.getClient()
    const { rows } = await client.query('SELECT public.get_materia_prima($1) AS data', [id]);
    res.json(rows[0]?.data || {});
    client.release();
  } catch (e) {
    console.error(e);
    res.status(500).json({ error: 'get_materia failed' });
  }
});

// SAVE MP + proveedores (array)
router.route('/rpc/save_materia').post( async (req, res) => {
  const { id_mat_prima=null, nombre, unidad, activo=true, proveedores=[] } = req.body || {};
  try {
    const q = 'SELECT public.save_materia_prima($1,$2,$3,$4,$5::jsonb) AS id_mat_prima';
    const params = [id_mat_prima, nombre, unidad, activo, JSON.stringify(proveedores||[])];
    const { rows } = await pool.query(q, params);
    res.json(rows[0] || {});
  } catch (e) {
    console.error(e);
    res.status(500).json({ error: 'save_materia failed' });
  }
});



// ----------------------------------------------------------
// API Usuarios y Asistencias
// ----------------------------------------------------------

// POST /api/rpc/find_usuarios_por_documentos  { docs: ["12345678","09123456", ...] }
router.route('/rpc/find_usuarios_por_documentos').post( async (req, res) => {
  try {
    const docs = Array.isArray(req.body?.docs) ? req.body.docs : [];
    const sql  = 'SELECT public.find_usuarios_por_documentos($1::jsonb) AS data';
    const { rows } = await pool.query(sql, [JSON.stringify(docs)]);
    res.json(rows[0]?.data || {});
  } catch (e) {
    console.error(e);
    res.status(500).json({ error: 'find_usuarios_por_documentos failed' });
  }
});

// POST /api/rpc/import_asistencia  { registros: [...], origen?: "AGL_001.txt" }
router.route('/rpc/import_asistencia').post( async (req, res) => {
  try {
    const registros = Array.isArray(req.body?.registros) ? req.body.registros : [];
    const origen    = req.body?.origen || null;
    const sql = 'SELECT public.import_asistencia($1::jsonb,$2) AS data';
    const { rows } = await pool.query(sql, [JSON.stringify(registros), origen]);
    res.json(rows[0]?.data || {});
  } catch (e) {
    console.error(e);
    res.status(500).json({ error: 'import_asistencia failed' });
  }
});

// Consultar datos de asistencia (raw + pares) para un usuario y rango
router.route('/rpc/asistencia_get').post( async (req, res) => {
  try {
    const { doc, desde, hasta } = req.body || {};
    const sql = 'SELECT public.asistencia_get($1::text,$2::date,$3::date) AS data';
    const { rows } = await pool.query(sql, [doc, desde, hasta]);
    res.json(rows[0]?.data || {});
  } catch (e) {
    console.error(e); res.status(500).json({ error: 'asistencia_get failed' });
  }
});

// Editar un registro crudo y recalcular pares
router.route('/rpc/asistencia_update_raw').post( async (req, res) => {
  try {
    const { id_raw, fecha, hora, modo } = req.body || {};
    const sql = 'SELECT public.asistencia_update_raw($1::bigint,$2::date,$3::text,$4::text) AS data';
    const { rows } = await pool.query(sql, [id_raw, fecha, hora, modo ?? null]);
    res.json(rows[0]?.data || {});
  } catch (e) {
    console.error(e); res.status(500).json({ error: 'asistencia_update_raw failed' });
  }
});

// Eliminar un registro crudo y recalcular pares
router.route('/rpc/asistencia_delete_raw').post( async (req, res) => {
  try {
    const { id_raw } = req.body || {};
    const sql = 'SELECT public.asistencia_delete_raw($1::bigint) AS data';
    const { rows } = await pool.query(sql, [id_raw]);
    res.json(rows[0]?.data || {});
  } catch (e) {
    console.error(e); res.status(500).json({ error: 'asistencia_delete_raw failed' });
  }
});


// ----------------------------------------------------------
// API Reportes
// ----------------------------------------------------------

// POST /api/rpc/report_tickets { year }
router.route('/rpc/report_tickets').post( async (req, res) => {
  try {
    const y = parseInt(req.body?.year ?? req.query?.year, 10);
    const year = (Number.isFinite(y) && y >= 2000 && y <= 2100)
      ? y
      : (new Date()).getFullYear();

    const { rows } = await pool.query(
      'SELECT public.report_tickets_year($1::int) AS j', [year]
    );
    res.json(rows[0].j);
  } catch (e) {
    console.error('report_tickets error:', e);
    res.status(500).json({
      error: 'report_tickets failed',
      message: e.message, detail: e.detail, where: e.where, code: e.code
    });
  }
});

// POST /api/rpc/report_asistencia { desde: 'YYYY-MM-DD', hasta: 'YYYY-MM-DD' }
router.route('/rpc/report_asistencia').post( async (req, res) => {
  try {
    let { desde, hasta } = req.body || {};
    // defaults si vienen vacíos/invalidos
    const re = /^\d{4}-\d{2}-\d{2}$/;
    if (!re.test(desde) || !re.test(hasta)) {
      const end   = new Date();
      const start = new Date(end); start.setDate(end.getDate()-30);
      desde = start.toISOString().slice(0,10);
      hasta = end.toISOString().slice(0,10);
    }

    const { rows } = await pool.query(
      'SELECT public.report_asistencia($1::date,$2::date) AS j', [desde, hasta]
    );
    res.json(rows[0].j);
  } catch (e) {
    console.error('report_asistencia error:', e);
    res.status(500).json({
      error: 'report_asistencia failed',
      message: e.message, detail: e.detail, where: e.where, code: e.code
    });
  }
});

// ----------------------------------------------------------
// API Compras y Gastos
// ----------------------------------------------------------

// Guardar (insert/update)
router.route('/rpc/save_compra').post( async (req, res) => {
  try {
    const { id_compra, id_proveedor, fec_compra, detalles } = req.body || {};
    const sql  = 'SELECT * FROM public.save_compra($1::int,$2::int,$3::timestamptz,$4::jsonb)';
    const args = [id_compra ?? null, id_proveedor, fec_compra ? new Date(fec_compra) : null, JSON.stringify(detalles)];
    const { rows } = await pool.query(sql, args);
    res.json(rows[0]); // { id_compra, total }
  } catch (e) {
    console.error('save_compra error:', e);
    res.status(500).json({ error: 'save_compra failed', message: e.message, detail: e.detail, where: e.where, code: e.code });
  }
});


// Obtener para editar
router.route('/rpc/get_compra').post( async (req, res) => {
  try {
    const { id_compra } = req.body || {};
    const sql = `SELECT public.get_compra($1::int) AS data`;
    const { rows } = await pool.query(sql, [id_compra]);
    res.json(rows[0]?.data || {});
  } catch (e) {
    console.error(e); res.status(500).json({ error: 'get_compra failed' });
  }
});

// Eliminar
router.route('/rpc/delete_compra').post( async (req, res) => {
  try {
    const { id_compra } = req.body || {};
    await pool.query(`SELECT public.delete_compra($1::int)`, [id_compra]);
    res.json({ ok: true });
  } catch (e) {
    console.error(e); res.status(500).json({ error: 'delete_compra failed' });
  }
});


// POST /api/rpc/report_gastos  { year: 2025 }
router.route('/rpc/report_gastos').post( async (req, res) => {
  try {
    const year = parseInt(req.body?.year ?? new Date().getFullYear(), 10);
    const { rows } = await pool.query(
      'SELECT public.report_gastos($1::int) AS j', [year]
    );
    res.json(rows[0].j);
  } catch (e) {
    console.error('report_gastos error:', e);
    res.status(500).json({
      error: 'report_gastos failed',
      message: e.message, detail: e.detail, code: e.code
    });
  }
});


export default router;