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

// Add member to chit group
const addMemberToGroup = async (req, res) => {
  try {
    const { groupId } = req.params;
    const { mobile_number } = req.body;
    const managerId = req.user.id;

    // Validate input
    if (!mobile_number) {
      return res.status(400).json({
        success: false,
        message: 'Mobile number is required'
      });
    }

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

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

    // Check if group is still forming
    if (chitGroup.status !== 'forming') {
      return res.status(400).json({
        success: false,
        message: 'Cannot add members after chit group has started'
      });
    }

    // Check if group is full
    const currentMemberCount = await GroupMember.count({
      where: { group_id: groupId, status: 'active' }
    });

    if (currentMemberCount >= chitGroup.max_members) {
      return res.status(400).json({
        success: false,
        message: 'Chit group is full'
      });
    }

    // Find user by mobile number
    const user = await User.findOne({
      where: { mobile_number, is_active: true }
    });

    if (!user) {
      return res.status(404).json({
        success: false,
        message: 'User not found'
      });
    }

    // Check if user is already a member
    const existingMembership = await GroupMember.findOne({
      where: { group_id: groupId, user_id: user.id }
    });

    if (existingMembership) {
      return res.status(400).json({
        success: false,
        message: 'User is already a member of this group'
      });
    }

    // Add member to group
    const groupMember = await GroupMember.create({
      group_id: groupId,
      user_id: user.id,
      joined_date: new Date(),
      status: 'active',
      total_paid: 0,
      total_won: 0
    });

    res.status(201).json({
      success: true,
      message: 'Member added successfully',
      data: {
        groupMember,
        user: {
          id: user.id,
          full_name: user.full_name,
          mobile_number: user.mobile_number
        }
      }
    });
  } catch (error) {
    console.error('Add member error:', error);
    res.status(500).json({
      success: false,
      message: 'Internal server error'
    });
  }
};

// Remove member from chit group
const removeMemberFromGroup = async (req, res) => {
  try {
    const { groupId, memberId } = req.params;
    const managerId = req.user.id;

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

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

    // Check if group is still forming
    if (chitGroup.status !== 'forming') {
      return res.status(400).json({
        success: false,
        message: 'Cannot remove members after chit group has started'
      });
    }

    // Find the membership
    const groupMember = await GroupMember.findOne({
      where: { group_id: groupId, user_id: memberId }
    });

    if (!groupMember) {
      return res.status(404).json({
        success: false,
        message: 'Member not found in this group'
      });
    }

    // Remove member
    await groupMember.update({ status: 'removed' });

    res.json({
      success: true,
      message: 'Member removed successfully'
    });
  } catch (error) {
    console.error('Remove member error:', error);
    res.status(500).json({
      success: false,
      message: 'Internal server error'
    });
  }
};

// Get group members
const getGroupMembers = async (req, res) => {
  try {
    const { groupId } = 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 };
    if (status) {
      whereClause.status = status;
    }

    const offset = (page - 1) * limit;

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

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

// Get member details with payment history
const getMemberDetails = async (req, res) => {
  try {
    const { groupId, memberId } = 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 member details
    const groupMember = await GroupMember.findOne({
      where: { group_id: groupId, user_id: memberId },
      include: [
        {
          model: User,
          attributes: ['id', 'full_name', 'mobile_number', 'created_at']
        },
        {
          model: Payment,
          where: { group_id: groupId, user_id: memberId },
          order: [['created_at', 'DESC']],
          limit: 10
        }
      ]
    });

    if (!groupMember) {
      return res.status(404).json({
        success: false,
        message: 'Member not found in this group'
      });
    }

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

// Update member status
const updateMemberStatus = async (req, res) => {
  try {
    const { groupId, memberId } = req.params;
    const { status } = req.body;
    const managerId = req.user.id;

    // Validate status
    const validStatuses = ['active', 'inactive', 'removed'];
    if (!validStatuses.includes(status)) {
      return res.status(400).json({
        success: false,
        message: 'Invalid status. Must be active, inactive, or removed'
      });
    }

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

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

    // Find the membership
    const groupMember = await GroupMember.findOne({
      where: { group_id: groupId, user_id: memberId }
    });

    if (!groupMember) {
      return res.status(404).json({
        success: false,
        message: 'Member not found in this group'
      });
    }

    // Update status
    await groupMember.update({ status });

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

// Get member payment summary
const getMemberPaymentSummary = async (req, res) => {
  try {
    const { groupId, memberId } = 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 member and payment data
    const groupMember = await GroupMember.findOne({
      where: { group_id: groupId, user_id: memberId },
      include: [
        {
          model: User,
          attributes: ['id', 'full_name', 'mobile_number']
        }
      ]
    });

    if (!groupMember) {
      return res.status(404).json({
        success: false,
        message: 'Member not found in this group'
      });
    }

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

    const totalPaid = payments
      .filter(p => p.status === 'success')
      .reduce((sum, p) => sum + parseFloat(p.amount), 0);

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

    const summary = {
      member: {
        id: groupMember.User.id,
        full_name: groupMember.User.full_name,
        mobile_number: groupMember.User.mobile_number,
        joined_date: groupMember.joined_date,
        status: groupMember.status
      },
      payments: {
        total_paid: totalPaid,
        total_expected: chitGroup.monthly_installment * chitGroup.duration_months,
        pending_count: pendingPayments,
        successful_count: successfulPayments,
        failed_count: failedPayments,
        payment_history: payments.slice(0, 5) // Last 5 payments
      },
      group_info: {
        monthly_installment: chitGroup.monthly_installment,
        duration_months: chitGroup.duration_months,
        total_won: groupMember.total_won
      }
    };

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

// Get all users (for adding to groups)
const getAllUsers = async (req, res) => {
  try {
    const { search, page = 1, limit = 50 } = req.query;
    const managerId = req.user.id;

    // Only managers can get all users
    const whereClause = { 
      is_active: true,
      role: 'member' // Only get members, not other managers
    };

    if (search) {
      whereClause[Op.or] = [
        { full_name: { [Op.iLike]: `%${search}%` } },
        { mobile_number: { [Op.iLike]: `%${search}%` } }
      ];
    }

    const offset = (page - 1) * limit;

    const users = await User.findAndCountAll({
      where: whereClause,
      attributes: ['id', 'full_name', 'mobile_number', 'created_at'],
      limit: parseInt(limit),
      offset: parseInt(offset),
      order: [['full_name', 'ASC']]
    });

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

const getAvailableUsersForGroup = async (req, res) => {
  try {
    const { groupId } = req.params;
    const { search, page = 1, limit = 50 } = req.query;
    const managerId = req.user.id;

    // First, get all active member users
    const whereClause = {
      is_active: true,
      role: 'member'
    };

    if (search) {
      whereClause[Op.or] = [
        { full_name: { [Op.iLike]: `%${search}%` } },
        { mobile_number: { [Op.iLike]: `%${search}%` } }
      ];
    }

    const offset = (page - 1) * limit;

    // Get users who are NOT already members of this group
    const users = await User.findAndCountAll({
      where: {
        ...whereClause,
        id: {
          [Op.notIn]: require('sequelize').literal(`
            SELECT user_id FROM group_members 
            WHERE group_id = '${groupId}' AND status = 'active'
          `)
        }
      },
      attributes: ['id', 'full_name', 'mobile_number', 'email', 'address', 'emergency_contact', 'created_at'],
      limit: parseInt(limit),
      offset: parseInt(offset),
      order: [['full_name', 'ASC']]
    });

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

module.exports = {
  addMemberToGroup,
  removeMemberFromGroup,
  getGroupMembers,
  getMemberDetails,
  updateMemberStatus,
  getMemberPaymentSummary,
  getAllUsers,
  getAvailableUsersForGroup
};
