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

// Generate provably fair lottery result
const generateProvablyFairResult = (serverSeed, clientSeed, nonce, eligibleMembers) => {
  // Create combined seed
  const combinedSeed = `${serverSeed}-${clientSeed}-${nonce}`;
  const hash = crypto.createHash('sha256').update(combinedSeed).digest('hex');
  
  // Use first 8 characters of hash as random number
  const randomHex = hash.substring(0, 8);
  const randomNumber = parseInt(randomHex, 16);
  
  // Select winner from eligible members
  const winnerIndex = randomNumber % eligibleMembers.length;
  const winner = eligibleMembers[winnerIndex];
  
  return {
    winner,
    hash,
    randomNumber,
    serverSeed,
    clientSeed,
    nonce
  };
};

// Create a new monthly draw
const createMonthlyDraw = async (req, res) => {
  try {
    const { group_id, month, year, client_seed } = req.body;
    
    // Convert month and year to integers
    const monthInt = parseInt(month, 10);
    const yearInt = parseInt(year, 10);
    const managerId = req.user.id;

    // Validate input
    if (!group_id || !month || !year) {
      return res.status(400).json({
        success: false,
        message: 'Group ID, month, and year are required'
      });
    }
    
    // Validate month and year are valid numbers
    if (isNaN(monthInt) || isNaN(yearInt)) {
      return res.status(400).json({
        success: false,
        message: 'Month and year must be valid numbers'
      });
    }
    
    // Validate month range
    if (monthInt < 1 || monthInt > 12) {
      return res.status(400).json({
        success: false,
        message: 'Month must be between 1 and 12'
      });
    }

    // Check if user is the manager of this group
    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 you are not the manager'
      });
    }

    // Check if group is active
    if (chitGroup.status !== 'active') {
      return res.status(400).json({
        success: false,
        message: 'Can only conduct draws for active chit groups'
      });
    }

    // Check if draw already exists for this month/year
    const existingDraw = await MonthlyDraw.findOne({
      where: { group_id, month: monthInt, year: yearInt }
    });

    if (existingDraw) {
      return res.status(400).json({
        success: false,
        message: 'Draw already exists for this month and year'
      });
    }

    // Get eligible members (active members who haven't won yet)
    const eligibleMembers = await GroupMember.findAll({
      where: {
        group_id,
        status: 'active'
      },
      include: [
        {
          model: User,
          attributes: ['id', 'full_name', 'mobile_number']
        }
      ]
    });

    // Filter out members who have already won
    const wonMembers = await MonthlyDraw.findAll({
      where: { group_id },
      attributes: ['winner_id']
    });

    const wonMemberIds = wonMembers.map(draw => draw.winner_id);
    const availableMembers = eligibleMembers.filter(member => 
      !wonMemberIds.includes(member.user_id)
    );

    if (availableMembers.length === 0) {
      return res.status(400).json({
        success: false,
        message: 'No eligible members available for draw'
      });
    }

    // Generate server seed and nonce
    const serverSeed = crypto.randomBytes(32).toString('hex');
    const nonce = Date.now();

    // Generate provably fair result
    const result = generateProvablyFairResult(
      serverSeed,
      client_seed || 'default',
      nonce,
      availableMembers
    );

    // Calculate prize amount using generic formula
    const totalMembers = eligibleMembers.length;
    const subscriptionPerMonth = chitGroup.total_value / chitGroup.duration_months;
    const installmentPerMonth = subscriptionPerMonth + chitGroup.foreman_commission_amount;
    
    // Calculate dividend for this month (linear schedule)
    const maxDividend = chitGroup.foreman_commission_amount * 2; // Default to 2x commission
    const step = (2 * maxDividend) / (chitGroup.duration_months - 1);
    const currentMonth = monthInt; // Assuming month is 1-based
    const dividend = maxDividend - ((currentMonth - 1) * step);
    
    const winnerPayout = chitGroup.total_value - dividend; // Winner gets bid amount
    const dividendPerMember = dividend / (totalMembers - 1); // Dividend distributed to others

    // Create monthly draw
    const monthlyDraw = await MonthlyDraw.create({
      group_id,
      month: monthInt,
      year: yearInt,
      draw_date: new Date(),
      eligible_members: availableMembers.map(member => ({
        id: member.user_id,
        name: member.User.full_name,
        mobile: member.User.mobile_number
      })),
      winner_id: result.winner.user_id,
      prize_amount: winnerPayout,
      server_seed: serverSeed,
      server_seed_hash: crypto.createHash('sha256').update(serverSeed).digest('hex'),
      client_seed: client_seed || 'default',
      nonce,
      result_hash: result.hash,
      status: 'completed',
      notes: `Winner selected: ${result.winner.User.full_name}`
    });

    res.status(201).json({
      success: true,
      message: 'Monthly draw completed successfully',
      data: {
        ...monthlyDraw.toJSON(),
        winner: result.winner.User,
        eligible_count: availableMembers.length
      }
    });
  } catch (error) {
    console.error('Create monthly draw error:', error);
    res.status(500).json({
      success: false,
      message: 'Internal server error'
    });
  }
};

// Get all monthly draws for a group
const getGroupMonthlyDraws = async (req, res) => {
  try {
    const { group_id } = req.params;
    const { status, page = 1, limit = 20 } = req.query;

    // Check if user has access to this group
    const chitGroup = await ChitGroup.findOne({
      where: {
        id: group_id,
        [Op.or]: [
          { manager_id: req.user.id },
          { '$members.user_id$': req.user.id }
        ]
      },
      include: [
        {
          model: GroupMember,
          as: 'members',
          include: [
            {
              model: User,
              attributes: ['id', 'full_name', 'mobile_number']
            }
          ]
        }
      ]
    });

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

    const whereClause = { group_id };
    if (status) {
      whereClause.status = status;
    }

    const offset = (page - 1) * limit;

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

    res.json({
      success: true,
      message: 'Monthly draws retrieved successfully',
      data: {
        monthlyDraws: monthlyDraws.rows,
        total: monthlyDraws.count,
        page: parseInt(page),
        limit: parseInt(limit),
        totalPages: Math.ceil(monthlyDraws.count / limit)
      }
    });
  } catch (error) {
    console.error('Get group monthly draws error:', error);
    res.status(500).json({
      success: false,
      message: 'Internal server error'
    });
  }
};

// Get monthly draw details
const getMonthlyDrawDetails = async (req, res) => {
  try {
    const { draw_id } = req.params;

    const monthlyDraw = await MonthlyDraw.findOne({
      where: { id: draw_id },
      include: [
        {
          model: User,
          as: 'winner',
          attributes: ['id', 'full_name', 'mobile_number']
        },
        {
          model: ChitGroup,
          attributes: ['id', 'name', 'monthly_installment', 'foreman_commission_amount']
        }
      ]
    });

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

    // Check if user has access to this draw
    const chitGroup = await ChitGroup.findOne({
      where: {
        id: monthlyDraw.group_id,
        [Op.or]: [
          { manager_id: req.user.id },
          { '$members.user_id$': req.user.id }
        ]
      }
    });

    if (!chitGroup) {
      return res.status(403).json({
        success: false,
        message: 'Access denied to this monthly draw'
      });
    }

    res.json({
      success: true,
      message: 'Monthly draw details retrieved successfully',
      data: monthlyDraw
    });
  } catch (error) {
    console.error('Get monthly draw details error:', error);
    res.status(500).json({
      success: false,
      message: 'Internal server error'
    });
  }
};

// Verify provably fair result
const verifyDrawResult = async (req, res) => {
  try {
    const { draw_id } = req.params;
    const { client_seed } = req.body;

    const monthlyDraw = await MonthlyDraw.findOne({
      where: { id: draw_id },
      include: [
        {
          model: User,
          as: 'winner',
          attributes: ['id', 'full_name', 'mobile_number']
        }
      ]
    });

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

    // Check if user has access to this draw
    const chitGroup = await ChitGroup.findOne({
      where: {
        id: monthlyDraw.group_id,
        [Op.or]: [
          { manager_id: req.user.id },
          { '$members.user_id$': req.user.id }
        ]
      }
    });

    if (!chitGroup) {
      return res.status(403).json({
        success: false,
        message: 'Access denied to this monthly draw'
      });
    }

    // Verify the result
    const verificationResult = generateProvablyFairResult(
      monthlyDraw.server_seed,
      client_seed || monthlyDraw.client_seed,
      monthlyDraw.nonce,
      monthlyDraw.eligible_members
    );

    const isVerified = verificationResult.hash === monthlyDraw.result_hash;

    res.json({
      success: true,
      message: 'Draw verification completed',
      data: {
        isVerified,
        originalHash: monthlyDraw.result_hash,
        verificationHash: verificationResult.hash,
        serverSeed: monthlyDraw.server_seed,
        clientSeed: client_seed || monthlyDraw.client_seed,
        nonce: monthlyDraw.nonce,
        winner: monthlyDraw.winner
      }
    });
  } catch (error) {
    console.error('Verify draw result error:', error);
    res.status(500).json({
      success: false,
      message: 'Internal server error'
    });
  }
};

// Get draw statistics for a group
const getDrawStatistics = async (req, res) => {
  try {
    const { group_id } = req.params;

    // Check if user has access to this group
    const chitGroup = await ChitGroup.findOne({
      where: {
        id: group_id,
        [Op.or]: [
          { manager_id: req.user.id },
          { '$members.user_id$': req.user.id }
        ]
      }
    });

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

    // Get all draws for this group
    const draws = await MonthlyDraw.findAll({
      where: { group_id },
      include: [
        {
          model: User,
          as: 'winner',
          attributes: ['id', 'full_name', 'mobile_number']
        }
      ],
      order: [['created_at', 'ASC']]
    });

    // Get total members
    const totalMembers = await GroupMember.count({
      where: { group_id, status: 'active' }
    });

    // Calculate statistics
    const completedDraws = draws.filter(draw => draw.status === 'completed');
    const totalPrizeAmount = completedDraws.reduce((sum, draw) => sum + parseFloat(draw.prize_amount), 0);
    const averagePrizeAmount = completedDraws.length > 0 ? totalPrizeAmount / completedDraws.length : 0;

    // Get winners by month
    const winnersByMonth = completedDraws.map(draw => ({
      month: draw.month,
      year: draw.year,
      winner: draw.winner,
      prize_amount: draw.prize_amount,
      draw_date: draw.draw_date
    }));

    res.json({
      success: true,
      message: 'Draw statistics retrieved successfully',
      data: {
        totalDraws: draws.length,
        completedDraws: completedDraws.length,
        pendingDraws: draws.filter(draw => draw.status === 'pending').length,
        totalMembers,
        totalPrizeAmount,
        averagePrizeAmount,
        winnersByMonth,
        remainingDraws: chitGroup.duration_months - completedDraws.length
      }
    });
  } catch (error) {
    console.error('Get draw statistics error:', error);
    res.status(500).json({
      success: false,
      message: 'Internal server error'
    });
  }
};

module.exports = {
  createMonthlyDraw,
  getGroupMonthlyDraws,
  getMonthlyDrawDetails,
  verifyDrawResult,
  getDrawStatistics
};
