const { Payment, ChitGroup, GroupMember, User } = require('../models');
const { Op } = require('sequelize');

// Record a payment
const recordPayment = async (req, res) => {
  try {
    const {
      group_id,
      user_id,
      month,
      year,
      amount,
      payment_method,
      transaction_id,
      notes
    } = req.body;
    
    const managerId = req.user.id;

    // Validate input
    if (!group_id || !user_id || !month || !year || !amount || !payment_method) {
      return res.status(400).json({
        success: false,
        message: 'Group ID, user ID, month, year, amount, and payment method are required'
      });
    }

    // Check if chit group exists and user is the manager
    const chitGroup = await ChitGroup.findOne({
      where: { id: group_id, manager_id: managerId }
    });

    if (!chitGroup) {
      return res.status(404).json({
        success: false,
        message: 'Chit group not found or access denied'
      });
    }

    // Check if user is a member of this group
    const groupMember = await GroupMember.findOne({
      where: { group_id, user_id, status: 'active' }
    });

    if (!groupMember) {
      return res.status(400).json({
        success: false,
        message: 'User is not an active member of this group'
      });
    }

    // Check if payment already exists for this month/year
    const existingPayment = await Payment.findOne({
      where: { group_id, user_id, month, year }
    });

    if (existingPayment) {
      return res.status(400).json({
        success: false,
        message: 'Payment for this month already exists'
      });
    }

    // Validate amount matches monthly installment (with type-safe comparison)
    const receivedAmount = parseFloat(amount);
    const expectedAmount = parseFloat(chitGroup.monthly_installment);
    
    if (receivedAmount !== expectedAmount) {
      return res.status(400).json({
        success: false,
        message: `Payment amount must be ₹${expectedAmount}, received ₹${receivedAmount}`
      });
    }

    // Create payment record
    const payment = await Payment.create({
      group_id,
      user_id,
      month,
      year,
      amount,
      payment_method,
      transaction_id: transaction_id || null,
      status: 'success', // Assuming immediate success for manual recording
      paid_at: new Date(),
      notes: notes || null
    });

    // Update member's total paid amount
    await groupMember.increment('total_paid', { by: amount });

    res.status(201).json({
      success: true,
      message: 'Payment recorded successfully',
      data: payment
    });
  } catch (error) {
    console.error('Record payment error:', error);
    res.status(500).json({
      success: false,
      message: 'Internal server error'
    });
  }
};

// Get payments for a group
const getGroupPayments = async (req, res) => {
  try {
    const { groupId } = req.params;
    const userId = req.user.id;
    const { status, month, year, page = 1, limit = 20 } = req.query;

    // Check if user has access to this group
    const chitGroup = await ChitGroup.findByPk(groupId);
    if (!chitGroup) {
      return res.status(404).json({
        success: false,
        message: 'Chit group not found'
      });
    }

    const isManager = chitGroup.manager_id === userId;
    const isMember = await GroupMember.findOne({
      where: { group_id: groupId, user_id: userId }
    });

    if (!isManager && !isMember) {
      return res.status(403).json({
        success: false,
        message: 'Access denied'
      });
    }

    const whereClause = { group_id: groupId };
    if (status) {
      whereClause.status = status;
    }
    if (month) {
      whereClause.month = month;
    }
    if (year) {
      whereClause.year = year;
    }

    const offset = (page - 1) * limit;

    const payments = await Payment.findAndCountAll({
      where: whereClause,
      include: [
        {
          model: User,
          attributes: ['id', 'full_name', 'mobile_number']
        }
      ],
      limit: parseInt(limit),
      offset: parseInt(offset),
      order: [['created_at', 'DESC']]
    });

    res.json({
      success: true,
      data: {
        payments: payments.rows,
        pagination: {
          currentPage: parseInt(page),
          totalPages: Math.ceil(payments.count / limit),
          totalItems: payments.count,
          itemsPerPage: parseInt(limit)
        }
      }
    });
  } catch (error) {
    console.error('Get group payments error:', error);
    res.status(500).json({
      success: false,
      message: 'Internal server error'
    });
  }
};

// Get member's payments
const getMemberPayments = async (req, res) => {
  try {
    const { groupId, memberId } = req.params;
    const userId = req.user.id;
    const { status, page = 1, limit = 20 } = req.query;

    // Check if user has access to this group
    const chitGroup = await ChitGroup.findByPk(groupId);
    if (!chitGroup) {
      return res.status(404).json({
        success: false,
        message: 'Chit group not found'
      });
    }

    const isManager = chitGroup.manager_id === userId;
    const isMember = await GroupMember.findOne({
      where: { group_id: groupId, user_id: userId }
    });

    if (!isManager && !isMember) {
      return res.status(403).json({
        success: false,
        message: 'Access denied'
      });
    }

    const whereClause = { group_id: groupId, user_id: memberId };
    if (status) {
      whereClause.status = status;
    }

    const offset = (page - 1) * limit;

    const payments = await Payment.findAndCountAll({
      where: whereClause,
      limit: parseInt(limit),
      offset: parseInt(offset),
      order: [['created_at', 'DESC']]
    });

    res.json({
      success: true,
      data: {
        payments: payments.rows,
        pagination: {
          currentPage: parseInt(page),
          totalPages: Math.ceil(payments.count / limit),
          totalItems: payments.count,
          itemsPerPage: parseInt(limit)
        }
      }
    });
  } catch (error) {
    console.error('Get member payments error:', error);
    res.status(500).json({
      success: false,
      message: 'Internal server error'
    });
  }
};

// Update payment status
const updatePaymentStatus = async (req, res) => {
  try {
    const { paymentId } = req.params;
    const { status, notes } = req.body;
    const managerId = req.user.id;

    // Validate status
    const validStatuses = ['pending', 'success', 'failed', 'cancelled'];
    if (!validStatuses.includes(status)) {
      return res.status(400).json({
        success: false,
        message: 'Invalid status'
      });
    }

    // Find payment and check access
    const payment = await Payment.findByPk(paymentId, {
      include: [
        {
          model: ChitGroup,
          where: { manager_id: managerId }
        }
      ]
    });

    if (!payment) {
      return res.status(404).json({
        success: false,
        message: 'Payment not found or access denied'
      });
    }

    // Update payment
    const updateData = { status };
    if (status === 'success' && !payment.paid_at) {
      updateData.paid_at = new Date();
    }
    if (notes) {
      updateData.notes = notes;
    }

    await payment.update(updateData);

    // Update member's total paid amount if status changed to success
    if (status === 'success' && payment.status !== 'success') {
      const groupMember = await GroupMember.findOne({
        where: { group_id: payment.group_id, user_id: payment.user_id }
      });
      if (groupMember) {
        await groupMember.increment('total_paid', { by: payment.amount });
      }
    }

    res.json({
      success: true,
      message: 'Payment status updated successfully',
      data: payment
    });
  } catch (error) {
    console.error('Update payment status error:', error);
    res.status(500).json({
      success: false,
      message: 'Internal server error'
    });
  }
};

// Get payment summary for a group
const getGroupPaymentSummary = async (req, res) => {
  try {
    const { groupId } = req.params;
    const userId = req.user.id;

    // Check if user has access to this group
    const chitGroup = await ChitGroup.findByPk(groupId);
    if (!chitGroup) {
      return res.status(404).json({
        success: false,
        message: 'Chit group not found'
      });
    }

    const isManager = chitGroup.manager_id === userId;
    const isMember = await GroupMember.findOne({
      where: { group_id: groupId, user_id: userId }
    });

    if (!isManager && !isMember) {
      return res.status(403).json({
        success: false,
        message: 'Access denied'
      });
    }

    // Get payment statistics
    const payments = await Payment.findAll({
      where: { group_id: groupId },
      attributes: ['status', 'amount', 'month', 'year']
    });

    const totalPayments = payments.length;
    const successfulPayments = payments.filter(p => p.status === 'success');
    const pendingPayments = payments.filter(p => p.status === 'pending');
    const failedPayments = payments.filter(p => p.status === 'failed');

    const totalCollection = successfulPayments.reduce((sum, p) => sum + parseFloat(p.amount), 0);
    const expectedCollection = chitGroup.monthly_installment * chitGroup.duration_months * chitGroup.max_members;

    // Get monthly payment trends
    const monthlyStats = {};
    payments.forEach(payment => {
      const key = `${payment.year}-${payment.month.toString().padStart(2, '0')}`;
      if (!monthlyStats[key]) {
        monthlyStats[key] = {
          total: 0,
          successful: 0,
          pending: 0,
          failed: 0
        };
      }
      monthlyStats[key].total += 1;
      monthlyStats[key][payment.status] += 1;
    });

    const summary = {
      group_info: {
        name: chitGroup.name,
        monthly_installment: chitGroup.monthly_installment,
        duration_months: chitGroup.duration_months,
        max_members: chitGroup.max_members
      },
      payment_stats: {
        total_payments: totalPayments,
        successful_payments: successfulPayments.length,
        pending_payments: pendingPayments.length,
        failed_payments: failedPayments.length,
        total_collection: totalCollection,
        expected_collection: expectedCollection,
        collection_percentage: (totalCollection / expectedCollection) * 100
      },
      monthly_trends: monthlyStats
    };

    res.json({
      success: true,
      data: summary
    });
  } catch (error) {
    console.error('Get group payment summary error:', error);
    res.status(500).json({
      success: false,
      message: 'Internal server error'
    });
  }
};

// Get pending payments for a group
const getPendingPayments = async (req, res) => {
  try {
    const { groupId } = req.params;
    const userId = req.user.id;

    // Check if user has access to this group
    const chitGroup = await ChitGroup.findByPk(groupId);
    if (!chitGroup) {
      return res.status(404).json({
        success: false,
        message: 'Chit group not found'
      });
    }

    const isManager = chitGroup.manager_id === userId;
    const isMember = await GroupMember.findOne({
      where: { group_id: groupId, user_id: userId }
    });

    if (!isManager && !isMember) {
      return res.status(403).json({
        success: false,
        message: 'Access denied'
      });
    }

    // Get all active members
    const activeMembers = await GroupMember.findAll({
      where: { group_id: groupId, status: 'active' },
      include: [
        {
          model: User,
          attributes: ['id', 'full_name', 'mobile_number']
        }
      ]
    });

    // Get current month and year
    const now = new Date();
    const currentMonth = now.getMonth() + 1;
    const currentYear = now.getFullYear();

    // Find members who haven't paid for current month
    const pendingPayments = [];
    
    for (const member of activeMembers) {
      const existingPayment = await Payment.findOne({
        where: {
          group_id: groupId,
          user_id: member.user_id,
          month: currentMonth,
          year: currentYear
        }
      });

      if (!existingPayment || existingPayment.status !== 'success') {
        pendingPayments.push({
          member: {
            id: member.User.id,
            full_name: member.User.full_name,
            mobile_number: member.User.mobile_number
          },
          payment_status: existingPayment ? existingPayment.status : 'not_paid',
          amount_due: chitGroup.monthly_installment,
          due_date: new Date(currentYear, currentMonth - 1, chitGroup.draw_date)
        });
      }
    }

    res.json({
      success: true,
      data: {
        current_month: currentMonth,
        current_year: currentYear,
        pending_payments: pendingPayments,
        total_pending: pendingPayments.length
      }
    });
  } catch (error) {
    console.error('Get pending payments error:', error);
    res.status(500).json({
      success: false,
      message: 'Internal server error'
    });
  }
};

module.exports = {
  recordPayment,
  getGroupPayments,
  getMemberPayments,
  updatePaymentStatus,
  getGroupPaymentSummary,
  getPendingPayments
};
