// src/routes/usuarioInsignias.routes.js
const express = require('express');
const router = express.Router();

const pool = require('../config/db');
const handleValidation = require('../middleware/handleValidation');

const {
  grantValidator,
  revokeValidator,
  listValidator,
  userParamValidator,
  checkAndGrantValidator,
} = require('../validators/usuarioInsignias.validators');

// Utilidad: verifica si un usuario cumple el criterio de una insignia,
// leyendo usuario_metricas y comparando contra (criterio_tipo, criterio_valor).
async function cumpleCriterio(pool, id_usuario, id_insignia) {
  // 1) Leer insignia
  const [[ins]] = await pool.query(
    `SELECT criterio_tipo, criterio_valor
       FROM insignias
      WHERE id_insignia = ?`,
    [id_insignia]
  );
  if (!ins) throw new Error('Insignia no encontrada');

  // 2) Leer métricas del usuario (si no existen, consideramos 0)
  const [[m]] = await pool.query(
    `SELECT actividades_completadas, tiempo_total_minutos, puntos_totales, racha_dias
       FROM usuario_metricas
      WHERE id_usuario = ?`,
    [id_usuario]
  );

  const actividades = m?.actividades_completadas || 0;
  const minutos     = m?.tiempo_total_minutos     || 0;
  const puntos      = m?.puntos_totales           || 0;
  const racha       = m?.racha_dias               || 0;

  switch (ins.criterio_tipo) {
    case 'actividades_completadas': return actividades >= ins.criterio_valor;
    case 'streak_dias':             return racha       >= ins.criterio_valor;
    case 'minutos_acumulados':      return minutos     >= ins.criterio_valor;
    case 'puntos_acumulados':       return puntos      >= ins.criterio_valor;
    default:
      // Si llega un tipo no reconocido, por seguridad no otorgamos
      return false;
  }
}

// ===== Listar (con joins opcionales) =====
router.get('/', listValidator, handleValidation, async (req, res) => {
  const { user_id, insignia_id } = req.query;

  let sql = `
    SELECT ui.id_usuario, ui.id_insignia, ui.fecha_otorgada,
           i.nombre AS insignia_nombre, i.descripcion, i.criterio_tipo, i.criterio_valor, i.icono,
           u.nombre AS usuario_nombre, u.apellido, u.email
      FROM usuarios_insignias ui
      JOIN usuarios u  ON u.id_usuario  = ui.id_usuario
      JOIN insignias i ON i.id_insignia = ui.id_insignia
     WHERE 1=1`;
  const params = [];

  if (user_id)     { sql += ' AND ui.id_usuario = ?';  params.push(Number(user_id)); }
  if (insignia_id) { sql += ' AND ui.id_insignia = ?'; params.push(Number(insignia_id)); }

  sql += ' ORDER BY ui.fecha_otorgada DESC';

  try {
    const [rows] = await pool.query(sql, params);
    res.json(rows);
  } catch (e) {
    console.error(e);
    res.status(500).json({ error: 'Error al listar usuarios_insignias' });
  }
});

// ===== Listar por usuario =====
router.get('/:id_usuario', userParamValidator, handleValidation, async (req, res) => {
  try {
    const [rows] = await pool.query(
      `SELECT ui.id_usuario, ui.id_insignia, ui.fecha_otorgada,
              i.nombre AS insignia_nombre, i.descripcion, i.criterio_tipo, i.criterio_valor, i.icono
         FROM usuarios_insignias ui
         JOIN insignias i ON i.id_insignia = ui.id_insignia
        WHERE ui.id_usuario = ?
        ORDER BY ui.fecha_otorgada DESC`,
      [req.params.id_usuario]
    );
    res.json(rows);
  } catch (e) {
    console.error(e);
    res.status(500).json({ error: 'Error al listar insignias del usuario' });
  }
});

// ===== Otorgar (grant) =====
// Si skip_check != true, valida contra usuario_metricas y criterio de la insignia.
router.post('/grant', grantValidator, handleValidation, async (req, res) => {
  const { id_usuario, id_insignia, fecha_otorgada = null, skip_check = false } = req.body;

  try {
    if (!skip_check) {
      const ok = await cumpleCriterio(pool, id_usuario, id_insignia);
      if (!ok) return res.status(400).json({ error: 'Criterio de insignia no cumplido' });
    }

    // Evitar duplicados (requiere UNIQUE (id_usuario, id_insignia) en la tabla)
    let sql, params;
    if (fecha_otorgada) {
      sql = `INSERT INTO usuarios_insignias (id_usuario, id_insignia, fecha_otorgada)
             VALUES (?, ?, ?)
             ON DUPLICATE KEY UPDATE fecha_otorgada = fecha_otorgada`;
      params = [id_usuario, id_insignia, fecha_otorgada];
    } else {
      sql = `INSERT INTO usuarios_insignias (id_usuario, id_insignia)
             VALUES (?, ?)
             ON DUPLICATE KEY UPDATE fecha_otorgada = fecha_otorgada`;
      params = [id_usuario, id_insignia];
    }

    await pool.query(sql, params);
    res.status(201).json({ message: 'Insignia otorgada (o ya existía)', id_usuario, id_insignia });
  } catch (e) {
    console.error(e);
    res.status(500).json({ error: 'Error al otorgar insignia' });
  }
});

// ===== Verificar y otorgar forzado para 1 insignia =====
router.post('/check-and-grant', checkAndGrantValidator, handleValidation, async (req, res) => {
  const { id_usuario, id_insignia } = req.body;
  try {
    const ok = await cumpleCriterio(pool, id_usuario, id_insignia);
    if (!ok) return res.status(200).json({ granted: false, reason: 'No cumple criterio' });

    await pool.query(
      `INSERT INTO usuarios_insignias (id_usuario, id_insignia)
       VALUES (?, ?)
       ON DUPLICATE KEY UPDATE fecha_otorgada = fecha_otorgada`,
      [id_usuario, id_insignia]
    );

    res.json({ granted: true, message: 'Insignia otorgada' });
  } catch (e) {
    console.error(e);
    res.status(500).json({ error: 'Error en check-and-grant' });
  }
});

// ===== Revocar (revoke) =====
router.delete('/:id_usuario/:id_insignia', revokeValidator, handleValidation, async (req, res) => {
  const { id_usuario, id_insignia } = req.params;
  try {
    const [r] = await pool.query(
      'DELETE FROM usuarios_insignias WHERE id_usuario = ? AND id_insignia = ?',
      [id_usuario, id_insignia]
    );
    if (r.affectedRows === 0) return res.status(404).json({ error: 'Registro no encontrado' });
    res.json({ message: 'Insignia revocada' });
  } catch (e) {
    console.error(e);
    res.status(500).json({ error: 'Error al revocar insignia' });
  }
});

module.exports = router;