const User = require('../models/User');
const Invitation = require('../models/Invitation');
const Appointment = require('../models/Appointment');
const { sequelize } = require('../config/database');
const { generateInvitationCode } = require('./authService');

/**
 * Invitation Service
 * Handles invitation code generation, tracking, and rewards
 */

/**
 * Generate invitation code for user
 * @param {string} userId - User ID
 * @returns {Object} User with invitation code
 */
const generateInvitationCodeForUser = async (userId) => {
  const user = await User.findByPk(userId);
  
  if (!user) {
    throw new Error('User not found');
  }

  // Check if user already has an invitation code
  if (user.invitationCode) {
    return user;
  }

  // Generate unique invitation code
  let code;
  let exists = true;
  
  while (exists) {
    code = generateInvitationCode();
    const existingUser = await User.findOne({ where: { invitationCode: code } });
    exists = !!existingUser;
  }

  // Update user with invitation code
  user.invitationCode = code;
  await user.save();

  return user;
};

/**
 * Get invitation statistics for user
 * @param {string} userId - User ID
 * @returns {Object} Invitation statistics
 */
const getInvitationStats = async (userId) => {
  const user = await User.findByPk(userId);
  
  if (!user) {
    throw new Error('User not found');
  }

  // Get all invitations where user is the inviter
  const invitations = await Invitation.findAll({
    where: { inviterId: userId },
  });

  // Calculate statistics
  const totalInvites = invitations.length;
  const paidInvites = invitations.filter(inv => inv.firstPaymentAt != null).length;
  const totalRewards = invitations
    .filter(inv => inv.rewardStatus === 'credited')
    .reduce((sum, inv) => sum + parseFloat(inv.rewardAmount || 0), 0);

  return {
    invitationCode: user.invitationCode,
    totalInvites,
    paidInvites,
    totalRewards: totalRewards.toFixed(2),
    availableBalance: parseFloat(user.balance).toFixed(2),
  };
};

/**
 * Get invitation records for user
 * @param {string} userId - User ID
 * @param {Object} options - Query options (page, limit)
 * @returns {Object} Invitation records with pagination
 */
const getInvitationRecords = async (userId, options = {}) => {
  const { page = 1, limit = 20 } = options;
  const offset = (page - 1) * limit;

  const user = await User.findByPk(userId);
  
  if (!user) {
    throw new Error('User not found');
  }

  // Get invitations with invitee information
  const { count, rows } = await Invitation.findAndCountAll({
    where: { inviterId: userId },
    include: [
      {
        model: User,
        as: 'invitee',
        attributes: ['id', 'nickname', 'avatar', 'createdAt'],
      },
    ],
    order: [['createdAt', 'DESC']],
    limit: parseInt(limit),
    offset: parseInt(offset),
  });

  // Format records
  const records = rows.map(invitation => ({
    id: invitation.id,
    invitee: {
      id: invitation.invitee.id,
      nickname: invitation.invitee.nickname,
      avatar: invitation.invitee.avatar,
      registeredAt: invitation.registeredAt,
    },
    firstPaymentAt: invitation.firstPaymentAt,
    firstPaymentAmount: invitation.firstPaymentAmount ? parseFloat(invitation.firstPaymentAmount).toFixed(2) : null,
    rewardAmount: invitation.rewardAmount ? parseFloat(invitation.rewardAmount).toFixed(2) : null,
    rewardStatus: invitation.rewardStatus,
    createdAt: invitation.createdAt,
  }));

  return {
    records,
    pagination: {
      page: parseInt(page),
      limit: parseInt(limit),
      total: count,
      totalPages: Math.ceil(count / limit),
    },
  };
};

/**
 * Record invitation relationship when user registers
 * @param {string} inviteeId - New user ID
 * @param {string} invitationCode - Invitation code used
 * @returns {Object} Invitation record
 */
const recordInvitationRelationship = async (inviteeId, invitationCode) => {
  // Find inviter by invitation code
  const inviter = await User.findOne({ where: { invitationCode } });
  
  if (!inviter) {
    throw new Error('Invalid invitation code');
  }

  // Check if invitation relationship already exists
  const existingInvitation = await Invitation.findOne({
    where: { inviteeId },
  });

  if (existingInvitation) {
    return existingInvitation;
  }

  // Create invitation record
  const invitation = await Invitation.create({
    inviterId: inviter.id,
    inviteeId,
    invitationCode,
    registeredAt: new Date(),
    rewardStatus: 'pending',
  });

  return invitation;
};

/**
 * Process first payment and calculate reward
 * @deprecated This function is deprecated. Commission calculation is now handled by
 * commissionService.calculateCommission() when payment orders are created in admin panel.
 * The new system calculates commission for EVERY payment (not just first), and uses
 * configurable commission rate (default 2%) instead of fixed 10%.
 * 
 * @param {string} userId - User ID who made payment
 * @param {string} appointmentId - Appointment ID
 * @returns {Object} Updated invitation record or null
 */
const processFirstPayment = async (userId, appointmentId) => {
  // DEPRECATED: Commission calculation is now handled by commissionService
  // when admin creates payment orders. This function is kept for backward
  // compatibility but no longer calculates or credits commissions.
  
  // Check if user was invited
  const invitation = await Invitation.findOne({
    where: { inviteeId: userId },
  });

  if (!invitation) {
    return null; // User was not invited
  }

  // Just return the invitation record without processing commission
  // Commission is now calculated via PaymentOrder creation in admin panel
  return invitation;
};

module.exports = {
  generateInvitationCodeForUser,
  getInvitationStats,
  getInvitationRecords,
  recordInvitationRelationship,
  processFirstPayment,
};
