/**
 * ========================================
 * RUTAS DE AGENDA
 * ========================================
 *
 * Maneja la agenda/calendario de actividades de los usuarios.
 * TODAS las rutas requieren autenticación.
 * Los usuarios solo pueden ver/modificar su propia agenda.
 */

const express = require('express');
const router = express.Router();

const pool = require('../config/db');
const { requireAuth } = require('../utils/jwt');
const handleValidation = require('../middleware/handleValidation');
const { checkPermission } = require('../middleware/checkPermission');
const { RESOURCES, ACTIONS } = require('../config/permissions');

const {
  createAgendaValidator,
  updateAgendaValidator,
  agendaIdValidator,
  listAgendaValidator,
  startAgendaValidator,
  finishAgendaValidator,
  ESTADOS, // ['pendiente','realizada','omitida','reprogramada']
} = require('../validators/agenda.validators');

// 👇 nombre exacto de tu tabla de registros
const REG_TABLE = 'registro_actividad';

/**
 * ========================================
 * GET /api/agenda
 * ========================================
 * Lista las agendas del usuario autenticado con filtros opcionales
 *
 * CAMBIOS DE SEGURIDAD:
 * - ✅ Requiere autenticación
 * - ✅ Requiere permiso de LIST en recurso AGENDA
 * - ✅ Solo muestra agendas del usuario autenticado
 * - ✅ Validación de estados permitidos
 */
router.get('/', requireAuth, checkPermission(RESOURCES.AGENDA, ACTIONS.LIST), listAgendaValidator, handleValidation, async (req, res) => {
  try {
    const { id_usuario } = req.user; // ✅ Del token
    const { estado, desde, hasta } = req.query;

    // ✅ Validar estado si se proporciona
    const validEstados = ['pendiente', 'realizada', 'omitida', 'reprogramada'];
    if (estado && !validEstados.includes(estado)) {
      return res.status(400).json({ error: 'Estado inválido' });
    }

    let sql = `
      SELECT id_agenda, id_usuario, id_actividad, fecha_programada, estado
        FROM agenda_actividades
       WHERE id_usuario = ?`; // ✅ Siempre filtrar por usuario autenticado
    const params = [id_usuario];

    if (estado) { sql += ' AND estado = ?'; params.push(estado); }
    if (desde) { sql += ' AND fecha_programada >= ?'; params.push(desde); }
    if (hasta) { sql += ' AND fecha_programada <= ?'; params.push(hasta); }

    sql += ' ORDER BY fecha_programada ASC';

    const [rows] = await pool.query(sql, params);
    res.json({ ok: true, data: rows });
  } catch (e) {
    console.error('GET /agenda error:', e);
    res.status(500).json({ error: 'Error al listar agenda' });
  }
});

/**
 * ========================================
 * GET /api/agenda/:id
 * ========================================
 * Obtiene una agenda específica del usuario autenticado
 *
 * SEGURIDAD:
 * - ✅ Requiere autenticación
 * - ✅ Requiere permiso de READ en recurso AGENDA
 */
router.get('/:id', requireAuth, checkPermission(RESOURCES.AGENDA, ACTIONS.READ), agendaIdValidator, handleValidation, async (req, res) => {
  try {
    const { id_usuario } = req.user;
    const id = Number(req.params.id);

    if (isNaN(id) || id <= 0) {
      return res.status(400).json({ error: 'ID de agenda inválido' });
    }

    // ✅ Solo permite ver agendas propias
    const [rows] = await pool.query(
      'SELECT * FROM agenda_actividades WHERE id_agenda = ? AND id_usuario = ?',
      [id, id_usuario]
    );

    if (!rows.length) {
      return res.status(404).json({ error: 'Agenda no encontrada' });
    }

    res.json({ ok: true, data: rows[0] });
  } catch (e) {
    console.error('GET /agenda/:id error:', e);
    res.status(500).json({ error: 'Error al obtener agenda' });
  }
});

/**
 * ========================================
 * POST /api/agenda
 * ========================================
 * Crea una nueva agenda para el usuario autenticado
 *
 * CAMBIOS DE SEGURIDAD:
 * - ✅ Requiere autenticación
 * - ✅ Requiere permiso de CREATE en recurso AGENDA
 * - ✅ Usa id_usuario del token (NO del body)
 */
router.post('/', requireAuth, checkPermission(RESOURCES.AGENDA, ACTIONS.CREATE), createAgendaValidator, handleValidation, async (req, res) => {
  try {
    const { id_usuario } = req.user; // ✅ Del token, no del body
    const { id_actividad, fecha_programada, estado = 'pendiente' } = req.body;

    // ✅ Validar estado
    const validEstados = ['pendiente', 'realizada', 'omitida', 'reprogramada'];
    if (!validEstados.includes(estado)) {
      return res.status(400).json({ error: 'Estado inválido' });
    }

    // ✅ Validar que la actividad exista
    const [actExists] = await pool.query(
      'SELECT 1 FROM actividades WHERE id_actividad = ?',
      [id_actividad]
    );
    if (!actExists.length) {
      return res.status(400).json({ error: 'Actividad no existe' });
    }

    const [insert] = await pool.query(
      `INSERT INTO agenda_actividades (id_usuario, id_actividad, fecha_programada, estado)
       VALUES (?, ?, ?, ?)`,
      [id_usuario, id_actividad, fecha_programada, estado]
    );

    res.status(201).json({ ok: true, message: 'Agenda creada', id: insert.insertId });
  } catch (e) {
    console.error('POST /agenda error:', e);
    res.status(500).json({ error: 'Error al crear agenda' });
  }
});

/**
 * ========================================
 * PUT /api/agenda/:id
 * ========================================
 * Actualiza una agenda del usuario autenticado
 *
 * CAMBIOS DE SEGURIDAD:
 * - ✅ Requiere autenticación
 * - ✅ Requiere permiso de UPDATE en recurso AGENDA
 * - ✅ Solo permite actualizar agendas propias
 * - ✅ NO permite cambiar id_usuario
 */
router.put('/:id', requireAuth, checkPermission(RESOURCES.AGENDA, ACTIONS.UPDATE), updateAgendaValidator, handleValidation, async (req, res) => {
  try {
    const { id_usuario } = req.user;
    const id = Number(req.params.id);

    if (isNaN(id) || id <= 0) {
      return res.status(400).json({ error: 'ID de agenda inválido' });
    }

    const { id_actividad, fecha_programada, estado } = req.body;

    // ✅ Construir update dinámico (SIN id_usuario)
    const updates = {};
    if (id_actividad !== undefined) updates.id_actividad = id_actividad;
    if (fecha_programada !== undefined) updates.fecha_programada = fecha_programada;
    if (estado !== undefined) {
      const validEstados = ['pendiente', 'realizada', 'omitida', 'reprogramada'];
      if (!validEstados.includes(estado)) {
        return res.status(400).json({ error: 'Estado inválido' });
      }
      updates.estado = estado;
    }

    if (Object.keys(updates).length === 0) {
      return res.status(400).json({ error: 'Nada para actualizar' });
    }

    const sets = Object.keys(updates).map(k => `${k} = ?`).join(', ');
    const values = [...Object.values(updates), id, id_usuario];

    // ✅ Solo actualiza si pertenece al usuario
    const [result] = await pool.query(
      `UPDATE agenda_actividades SET ${sets} WHERE id_agenda = ? AND id_usuario = ?`,
      values
    );

    if (result.affectedRows === 0) {
      return res.status(404).json({ error: 'Agenda no encontrada o no autorizado' });
    }

    res.json({ ok: true, message: 'Agenda actualizada' });
  } catch (e) {
    console.error('PUT /agenda/:id error:', e);
    res.status(500).json({ error: 'Error al actualizar agenda' });
  }
});

/**
 * ========================================
 * DELETE /api/agenda/:id
 * ========================================
 * Elimina una agenda del usuario autenticado
 *
 * SEGURIDAD:
 * - ✅ Requiere autenticación
 * - ✅ Requiere permiso de DELETE en recurso AGENDA
 */
router.delete('/:id', requireAuth, checkPermission(RESOURCES.AGENDA, ACTIONS.DELETE), agendaIdValidator, handleValidation, async (req, res) => {
  try {
    const { id_usuario } = req.user;
    const id = Number(req.params.id);

    if (isNaN(id) || id <= 0) {
      return res.status(400).json({ error: 'ID de agenda inválido' });
    }

    // ✅ Solo elimina si pertenece al usuario
    const [result] = await pool.query(
      'DELETE FROM agenda_actividades WHERE id_agenda = ? AND id_usuario = ?',
      [id, id_usuario]
    );

    if (result.affectedRows === 0) {
      return res.status(404).json({ error: 'Agenda no encontrada o no autorizado' });
    }

    res.json({ ok: true, message: 'Agenda eliminada' });
  } catch (e) {
    console.error('DELETE /agenda/:id error:', e);
    res.status(500).json({ error: 'Error al eliminar agenda' });
  }
});

/**
 * ========================================
 * PATCH /api/agenda/:id/start
 * ========================================
 * Inicia una actividad desde la agenda
 *
 * CAMBIOS DE SEGURIDAD:
 * - ✅ Requiere autenticación
 * - ✅ Solo permite iniciar agendas propias
 */
router.patch('/:id/start', requireAuth, startAgendaValidator, handleValidation, async (req, res) => {
  try {
    const { id_usuario } = req.user;
    const idAgenda = Number(req.params.id);

    if (isNaN(idAgenda) || idAgenda <= 0) {
      return res.status(400).json({ error: 'ID de agenda inválido' });
    }

    // ✅ Solo permite iniciar agendas propias
    const [agRows] = await pool.query(
      'SELECT id_agenda, id_usuario, id_actividad, estado FROM agenda_actividades WHERE id_agenda = ? AND id_usuario = ?',
      [idAgenda, id_usuario]
    );

    if (!agRows.length) {
      return res.status(404).json({ error: 'Agenda no encontrada o no autorizado' });
    }

    const agenda = agRows[0];

    // Bloquea si ya se marcó como realizada u omitida
    if (agenda.estado === 'omitida' || agenda.estado === 'realizada') {
      return res.status(400).json({ error: `La agenda está en estado ${agenda.estado}` });
    }

    // Crear registro
    const [insReg] = await pool.query(
      `INSERT INTO ${REG_TABLE} (id_usuario, id_actividad, fecha_inicio, completada)
       VALUES (?, ?, NOW(), 0)`,
      [id_usuario, agenda.id_actividad]
    );

    res.json({
      ok: true,
      message: 'Actividad iniciada desde agenda',
      registro_id: insReg.insertId,
    });
  } catch (e) {
    console.error('PATCH /agenda/:id/start error:', e);
    res.status(500).json({ error: 'Error al iniciar desde agenda' });
  }
});

/**
 * ========================================
 * PATCH /api/agenda/:id/finish
 * ========================================
 * Finaliza una actividad desde la agenda
 *
 * CAMBIOS DE SEGURIDAD:
 * - ✅ Requiere autenticación
 * - ✅ Valida ownership de la agenda
 */
router.patch('/:id/finish', requireAuth, finishAgendaValidator, handleValidation, async (req, res) => {
  try {
    const { id_usuario } = req.user;
    const idAgenda = Number(req.params.id);
    const { registro_id, emocion = null, puntos_obtenidos = null, comentario = null } = req.body;

    if (isNaN(idAgenda) || idAgenda <= 0) {
      return res.status(400).json({ error: 'ID de agenda inválido' });
    }

    // ✅ Verificar que la agenda pertenece al usuario
    const [agRows] = await pool.query(
      'SELECT 1 FROM agenda_actividades WHERE id_agenda = ? AND id_usuario = ?',
      [idAgenda, id_usuario]
    );

    if (!agRows.length) {
      return res.status(404).json({ error: 'Agenda no encontrada o no autorizado' });
    }

    // Actualizar registro
    await pool.query(
      `UPDATE ${REG_TABLE}
          SET fecha_fin = COALESCE(fecha_fin, NOW()),
              emocion = COALESCE(?, emocion),
              puntos_obtenidos = COALESCE(?, puntos_obtenidos),
              comentario = COALESCE(?, comentario),
              completada = 1
        WHERE id_registro = ? AND id_usuario = ?`,
      [emocion, puntos_obtenidos, comentario, registro_id, id_usuario]
    );

    // Marcar agenda como realizada
    await pool.query(
      'UPDATE agenda_actividades SET estado = ? WHERE id_agenda = ?',
      ['realizada', idAgenda]
    );

    res.json({ ok: true, message: 'Actividad finalizada; agenda marcada como realizada' });
  } catch (e) {
    console.error('PATCH /agenda/:id/finish error:', e);
    res.status(500).json({ error: 'Error al finalizar desde agenda' });
  }
});

/**
 * ========================================
 * PATCH /api/agenda/:id/reprogramar
 * ========================================
 * Reprograma una agenda (cambia fecha y marca como 'reprogramada')
 */
router.patch('/:id/reprogramar', requireAuth, agendaIdValidator, handleValidation, async (req, res) => {
  try {
    const { id_usuario } = req.user;
    const id = Number(req.params.id);
    const { fecha_programada } = req.body;

    if (!fecha_programada) {
      return res.status(400).json({ error: 'fecha_programada requerida' });
    }

    if (isNaN(id) || id <= 0) {
      return res.status(400).json({ error: 'ID de agenda inválido' });
    }

    // ✅ Solo reprograma si pertenece al usuario
    const [r] = await pool.query(
      `UPDATE agenda_actividades
         SET fecha_programada = ?, estado = 'reprogramada'
       WHERE id_agenda = ? AND id_usuario = ?`,
      [fecha_programada, id, id_usuario]
    );

    if (r.affectedRows === 0) {
      return res.status(404).json({ error: 'Agenda no encontrada o no autorizado' });
    }

    res.json({ ok: true, message: 'Agenda reprogramada' });
  } catch (e) {
    console.error('PATCH /agenda/:id/reprogramar error:', e);
    res.status(500).json({ error: 'Error al reprogramar agenda' });
  }
});

/**
 * ========================================
 * PATCH /api/agenda/:id/omitir
 * ========================================
 * Marca una agenda como 'omitida'
 */
router.patch('/:id/omitir', requireAuth, agendaIdValidator, handleValidation, async (req, res) => {
  try {
    const { id_usuario } = req.user;
    const id = Number(req.params.id);

    if (isNaN(id) || id <= 0) {
      return res.status(400).json({ error: 'ID de agenda inválido' });
    }

    // ✅ Solo omite si pertenece al usuario
    const [r] = await pool.query(
      'UPDATE agenda_actividades SET estado = ? WHERE id_agenda = ? AND id_usuario = ?',
      ['omitida', id, id_usuario]
    );

    if (r.affectedRows === 0) {
      return res.status(404).json({ error: 'Agenda no encontrada o no autorizado' });
    }

    res.json({ ok: true, message: 'Agenda marcada como omitida' });
  } catch (e) {
    console.error('PATCH /agenda/:id/omitir error:', e);
    res.status(500).json({ error: 'Error al omitir agenda' });
  }
});

module.exports = router;