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

// Obtener balance y resumen
exports.getWalletSummary = async (req, res) => {
  try {
    const userId = req.user.id;
    const wallet = await Wallet.findOne({ where: { userId } });

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

    res.json({
      balance: wallet.balance,
      currency: 'USD' // O lo que se use
    });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: 'Error al obtener billetera' });
  }
};

// Obtener historial de transacciones
exports.getTransactions = async (req, res) => {
  try {
    const userId = req.user.id;
    const wallet = await Wallet.findOne({ where: { userId } });

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

    const transactions = await Transaction.findAll({
      where: { walletId: wallet.id },
      order: [['createdAt', 'DESC']]
    });

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

// Solicitud de depósito
exports.requestDeposit = async (req, res) => {
  const { amount, description } = req.body;
  try {
    if (!amount || isNaN(amount) || parseFloat(amount) <= 0) {
        return res.status(400).json({ message: 'Monto inválido' });
    }

    const userId = req.user.id;
    const wallet = await Wallet.findOne({ where: { userId } });

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

    const transaction = await Transaction.create({
      walletId: wallet.id,
      type: 'deposit',
      amount,
      status: 'pending',
      description: description || 'Depósito solicitado'
    });

    await ActivityLog.create({
        userId,
        action: 'DEPOSIT_REQUEST',
        ipAddress: req.ip,
        details: JSON.stringify({ amount, transactionId: transaction.id })
    });

    res.status(201).json(transaction);
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: 'Error al solicitar depósito' });
  }
};

// Solicitud de retiro
exports.requestWithdrawal = async (req, res) => {
  const { amount, description } = req.body;
  const t = await sequelize.transaction();

  try {
    if (!amount || isNaN(amount) || parseFloat(amount) <= 0) {
        await t.rollback();
        return res.status(400).json({ message: 'Monto inválido' });
    }

    const userId = req.user.id;
    const wallet = await Wallet.findOne({ where: { userId }, transaction: t });

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

    if (parseFloat(wallet.balance) < parseFloat(amount)) {
      await t.rollback();
      return res.status(400).json({ message: 'Fondos insuficientes' });
    }

    // Deduct immediately
    wallet.balance = parseFloat(wallet.balance) - parseFloat(amount);
    await wallet.save({ transaction: t });

    const transaction = await Transaction.create({
      walletId: wallet.id,
      type: 'withdrawal',
      amount,
      status: 'pending',
      description: description || 'Retiro solicitado'
    }, { transaction: t });

    await ActivityLog.create({
        userId,
        action: 'WITHDRAWAL_REQUEST',
        ipAddress: req.ip,
        details: JSON.stringify({ amount, transactionId: transaction.id })
    }, { transaction: t });

    await t.commit();
    res.status(201).json({ transaction, newBalance: wallet.balance });
  } catch (error) {
    await t.rollback();
    console.error(error);
    res.status(500).json({ message: 'Error al solicitar retiro' });
  }
};

// Admin: Obtener todas las transacciones
exports.getAllTransactions = async (req, res) => {
    try {
        const { status, type } = req.query;
        const whereClause = {};
        if (status) whereClause.status = status;
        if (type) whereClause.type = type;

        const transactions = await Transaction.findAll({
            where: whereClause,
            include: [{
                model: Wallet,
                include: [{ model: User, attributes: ['id', 'username', 'email'] }]
            }],
            order: [['createdAt', 'DESC']]
        });
        res.json(transactions);
    } catch (error) {
        console.error(error);
        res.status(500).json({ message: 'Error al obtener transacciones' });
    }
};

// Admin: Actualizar estado de transacción
exports.updateTransactionStatus = async (req, res) => {
    const { id } = req.params;
    const { status } = req.body; // 'completed' or 'rejected'
    const t = await sequelize.transaction();

    try {
        const transaction = await Transaction.findByPk(id, { transaction: t });
        if (!transaction) {
            await t.rollback();
            return res.status(404).json({ message: 'Transacción no encontrada' });
        }

        if (transaction.status !== 'pending') {
            await t.rollback();
            return res.status(400).json({ message: 'La transacción ya ha sido procesada' });
        }

        const wallet = await Wallet.findByPk(transaction.walletId, { transaction: t });

        if (status === 'completed') {
            if (transaction.type === 'deposit') {
                wallet.balance = parseFloat(wallet.balance) + parseFloat(transaction.amount);
                await wallet.save({ transaction: t });
            }
            // If withdrawal, balance was already deducted
        } else if (status === 'rejected') {
            if (transaction.type === 'withdrawal') {
                // Refund
                wallet.balance = parseFloat(wallet.balance) + parseFloat(transaction.amount);
                await wallet.save({ transaction: t });
            }
            // If deposit, just reject
        } else {
            await t.rollback();
            return res.status(400).json({ message: 'Estado inválido' });
        }

        transaction.status = status;
        await transaction.save({ transaction: t });

        // Log Admin Action
        await ActivityLog.create({
            userId: req.user.id, // Admin ID
            action: 'TRANSACTION_UPDATE',
            ipAddress: req.ip,
            details: JSON.stringify({ transactionId: id, status, type: transaction.type, amount: transaction.amount })
        }, { transaction: t });

        await t.commit();
        res.json({ message: `Transacción ${status}`, transaction });

    } catch (error) {
        await t.rollback();
        console.error(error);
        res.status(500).json({ message: 'Error al actualizar transacción' });
    }
};
