const { Task, Wallet, Transaction, UserTask, ActivityLog, sequelize } = require('../models');
const { Op } = require('sequelize');

// Listar tareas disponibles
exports.getTasks = async (req, res) => {
  try {
    const userId = req.user.id;
    const tasks = await Task.findAll({ where: { active: true } });
    
    // Obtener historial de tareas del usuario
    const userTasks = await UserTask.findAll({ where: { userId } });

    // Procesar tareas para añadir estado (completed, available)
    const tasksWithStatus = tasks.map(task => {
      const history = userTasks.filter(ut => ut.taskId === task.id);
      let status = 'available';

      if (task.type === 'one_time') {
        if (history.length > 0) {
          status = 'completed';
        }
      } else if (task.type === 'daily') {
        // Verificar si se completó hoy
        const today = new Date();
        const completedToday = history.some(ut => {
          const completedDate = new Date(ut.completedAt);
          return completedDate.getDate() === today.getDate() &&
                 completedDate.getMonth() === today.getMonth() &&
                 completedDate.getFullYear() === today.getFullYear();
        });
        
        if (completedToday) {
          status = 'completed_today';
        }
      }

      return {
        ...task.toJSON(),
        status
      };
    });

    res.json(tasksWithStatus);
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: 'Error al obtener tareas' });
  }
};

// Completar tarea
exports.completeTask = async (req, res) => {
  const { taskId } = req.body;
  const userId = req.user.id;
  const t = await sequelize.transaction();

  try {
    // 1. Lock the Wallet (Mutex for User)
    const wallet = await Wallet.findOne({ 
        where: { userId }, 
        transaction: t,
        lock: t.LOCK.UPDATE 
    });

    if (!wallet) {
      await t.rollback();
      return res.status(404).json({ message: 'Billetera no encontrada' });
    }

    const task = await Task.findByPk(taskId, { transaction: t });
    if (!task) {
      await t.rollback();
      return res.status(404).json({ message: 'Tarea no encontrada' });
    }

    // Validaciones de Restricciones
    const history = await UserTask.findAll({ 
      where: { userId, taskId },
      transaction: t
    });

    if (task.type === 'one_time' && history.length > 0) {
      await t.rollback();
      return res.status(400).json({ message: 'Esta tarea ya fue completada' });
    }

    if (task.type === 'daily') {
      const today = new Date();
      const completedToday = history.some(ut => {
        const completedDate = new Date(ut.completedAt);
        return completedDate.getDate() === today.getDate() &&
               completedDate.getMonth() === today.getMonth() &&
               completedDate.getFullYear() === today.getFullYear();
      });

      if (completedToday) {
        await t.rollback();
        return res.status(400).json({ message: 'Ya completaste esta tarea hoy' });
      }
    }

    // Registrar actividad del usuario (Punto 5)
    await UserTask.create({
      userId,
      taskId,
      completedAt: new Date()
    }, { transaction: t });

    // Crear transacción (Asignación automática de recompensas - Punto 4)
    await Transaction.create({
      walletId: wallet.id,
      type: 'earning_task',
      amount: task.reward,
      status: 'completed',
      description: `Recompensa por tarea: ${task.title}`
    }, { transaction: t });

    // Actualizar balance
    wallet.balance = parseFloat(wallet.balance) + parseFloat(task.reward);
    await wallet.save({ transaction: t });

    // Log Activity
    await ActivityLog.create({
        userId,
        action: 'TASK_COMPLETED',
        ipAddress: req.ip,
        details: JSON.stringify({ taskId, reward: task.reward })
    }, { transaction: t });

    await t.commit();

    res.json({ 
      message: 'Tarea completada con éxito',
      reward: task.reward,
      newBalance: wallet.balance
    });

  } catch (error) {
    await t.rollback();
    console.error(error);
    res.status(500).json({ message: 'Error al completar tarea' });
  }
};

// Crear tarea (Para Admin o Seed)
exports.createTask = async (req, res) => {
  try {
    const task = await Task.create(req.body);
    await ActivityLog.create({
        userId: req.user.id,
        action: 'TASK_CREATED',
        ipAddress: req.ip,
        details: JSON.stringify({ taskId: task.id, title: task.title })
    });
    res.status(201).json(task);
  } catch (error) {
    res.status(500).json({ message: 'Error al crear tarea' });
  }
};

exports.updateTask = async (req, res) => {
  try {
    const task = await Task.findByPk(req.params.id);
    if (!task) {
      return res.status(404).json({ message: 'Tarea no encontrada' });
    }
    await task.update(req.body);
    await ActivityLog.create({
        userId: req.user.id,
        action: 'TASK_UPDATED',
        ipAddress: req.ip,
        details: JSON.stringify({ taskId: task.id })
    });
    res.json(task);
  } catch (error) {
    res.status(500).json({ message: 'Error al actualizar tarea' });
  }
};

exports.deleteTask = async (req, res) => {
  try {
    const task = await Task.findByPk(req.params.id);
    if (!task) {
      return res.status(404).json({ message: 'Tarea no encontrada' });
    }
    await task.destroy();
    await ActivityLog.create({
        userId: req.user.id,
        action: 'TASK_DELETED',
        ipAddress: req.ip,
        details: JSON.stringify({ taskId: req.params.id })
    });
    res.json({ message: 'Tarea eliminada' });
  } catch (error) {
    res.status(500).json({ message: 'Error al eliminar tarea' });
  }
};

exports.getAdminTasks = async (req, res) => {
  try {
    const tasks = await Task.findAll();
    res.json(tasks);
  } catch (error) {
    res.status(500).json({ message: 'Error al obtener tareas' });
  }
};
