const User = require('../models/User');
const Appointment = require('../models/Appointment');
const Invitation = require('../models/Invitation');
const Withdrawal = require('../models/Withdrawal');
const LoginHistory = require('../models/LoginHistory');
const Commission = require('../models/Commission');
const PaymentOrder = require('../models/PaymentOrder');
const { Op } = require('sequelize');
const { Parser } = require('json2csv');

/**
 * Admin User Service
 * Handles user management operations for admin panel
 */

/**
 * Get paginated user list with search and filters
 * @param {Object} options - Query options
 * @returns {Promise<Object>} User list with pagination
 */
const getUserList = async (options = {}) => {
  const {
    page = 1,
    limit = 20,
    search = '',
    status = '',
    language = '',
    sortBy = 'createdAt',
    sortOrder = 'DESC',
  } = options;

  const offset = (page - 1) * limit;

  // Build where clause
  const where = {};

  // Search by nickname, real name, phone, or wechat ID
  if (search) {
    where[Op.or] = [
      { nickname: { [Op.like]: `%${search}%` } },
      { realName: { [Op.like]: `%${search}%` } },
      { phone: { [Op.like]: `%${search}%` } },
      { wechatId: { [Op.like]: `%${search}%` } },
    ];
  }

  // Filter by status
  if (status) {
    where.status = status;
  }

  // Filter by language
  if (language) {
    where.language = language;
  }

  // Query users
  const { count, rows: users } = await User.findAndCountAll({
    where,
    limit: parseInt(limit),
    offset,
    order: [[sortBy, sortOrder]],
    attributes: [
      'id',
      'uid',
      'nickname',
      'avatar',
      'realName',
      'phone',
      'whatsapp',
      'wechatId',
      'language',
      'balance',
      'invitationCode',
      'status',
      'createdAt',
      'updatedAt',
    ],
  });

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

/**
 * Get detailed user information
 * @param {String} userId - User ID
 * @returns {Promise<Object>} User details with related data
 */
const getUserDetails = async (userId) => {
  // Get user
  const user = await User.findByPk(userId, {
    attributes: [
      'id',
      'uid',
      'wechatOpenId',
      'nickname',
      'avatar',
      'realName',
      'phone',
      'whatsapp',
      'wechatId',
      'language',
      'balance',
      'invitationCode',
      'invitedBy',
      'status',
      'createdAt',
      'updatedAt',
    ],
  });

  if (!user) {
    throw new Error('User not found');
  }

  // Get inviter information if exists
  let inviter = null;
  if (user.invitedBy) {
    inviter = await User.findByPk(user.invitedBy, {
      attributes: ['id', 'nickname', 'realName'],
    });
  }

  // Get appointment statistics
  const appointmentStats = await Appointment.findAll({
    where: { userId },
    attributes: [
      'status',
      [require('sequelize').fn('COUNT', require('sequelize').col('id')), 'count'],
    ],
    group: ['status'],
    raw: true,
  });

  const appointmentCounts = {
    total: 0,
    pending: 0,
    confirmed: 0,
    'in-progress': 0,
    completed: 0,
    cancelled: 0,
  };

  appointmentStats.forEach((stat) => {
    appointmentCounts[stat.status] = parseInt(stat.count);
    appointmentCounts.total += parseInt(stat.count);
  });

  // Get invitation statistics from Commission table (more accurate)
  const commissions = await Commission.findAll({
    where: { inviterId: userId, status: 'credited' },
    attributes: ['commissionAmount', 'currency'],
    raw: true,
  });

  let totalRewardsRmb = 0;
  let totalRewardsPeso = 0;
  commissions.forEach(c => {
    const amount = parseFloat(c.commissionAmount || 0);
    if (c.currency === 'PHP') {
      totalRewardsPeso += amount;
    } else {
      totalRewardsRmb += amount;
    }
  });

  // Get invited users count
  const invitedUsersCount = await User.count({
    where: { invitedBy: userId },
  });

  // Get paid invites count
  const paidInvitesCount = await Commission.count({
    where: { inviterId: userId, status: 'credited' },
    distinct: true,
    col: 'invitee_id',
  });

  const invitationCounts = {
    totalInvites: invitedUsersCount,
    paidInvites: paidInvitesCount,
    totalRewards: totalRewardsRmb,
    totalRewardsRmb: totalRewardsRmb,
    totalRewardsPeso: totalRewardsPeso,
  };

  // Get invited users with their commission details
  const invitedUsers = await User.findAll({
    where: { invitedBy: userId },
    attributes: ['id', 'uid', 'nickname', 'avatar', 'createdAt'],
    order: [['createdAt', 'DESC']],
    limit: 50,
  });

  // Get commission details for each invited user
  const invitedUsersWithCommissions = await Promise.all(
    invitedUsers.map(async (invitee) => {
      const userCommissions = await Commission.findAll({
        where: { 
          inviterId: userId, 
          inviteeId: invitee.id,
          status: 'credited' 
        },
        include: [
          {
            model: PaymentOrder,
            as: 'paymentOrder',
            attributes: ['id', 'orderNo', 'serviceContent', 'paymentTime', 'amountRmb', 'amountPeso'],
          },
        ],
        order: [['createdAt', 'DESC']],
      });

      let userTotalRmb = 0;
      let userTotalPeso = 0;
      let userPaymentRmb = 0;
      let userPaymentPeso = 0;

      const orders = userCommissions.map(c => {
        const commissionAmount = parseFloat(c.commissionAmount);
        const paymentAmount = parseFloat(c.paymentAmount);
        
        if (c.currency === 'PHP') {
          userTotalPeso += commissionAmount;
          userPaymentPeso += paymentAmount;
        } else {
          userTotalRmb += commissionAmount;
          userPaymentRmb += paymentAmount;
        }

        return {
          id: c.id,
          orderNo: c.paymentOrder?.orderNo || '-',
          serviceContent: c.paymentOrder?.serviceContent || '-',
          paymentTime: c.paymentOrder?.paymentTime || c.createdAt,
          paymentAmount: paymentAmount.toFixed(2),
          commissionAmount: commissionAmount.toFixed(2),
          currency: c.currency || 'RMB',
          createdAt: c.createdAt,
        };
      });

      return {
        user: {
          id: invitee.id,
          uid: invitee.uid,
          nickname: invitee.nickname,
          avatar: invitee.avatar,
          registeredAt: invitee.createdAt,
        },
        orderCount: orders.length,
        orders,
        totalPaymentRmb: userPaymentRmb.toFixed(2),
        totalPaymentPeso: userPaymentPeso.toFixed(2),
        totalCommissionRmb: userTotalRmb.toFixed(2),
        totalCommissionPeso: userTotalPeso.toFixed(2),
      };
    })
  );

  // Get withdrawal statistics
  const withdrawalStats = await Withdrawal.findAll({
    where: { userId },
    attributes: [
      'status',
      'currency',
      [require('sequelize').fn('COUNT', require('sequelize').col('id')), 'count'],
      [require('sequelize').fn('SUM', require('sequelize').col('amount')), 'total'],
    ],
    group: ['status', 'currency'],
    raw: true,
  });

  const withdrawalCounts = {
    total: 0,
    totalAmount: 0,
    totalAmountRmb: 0,
    totalAmountPeso: 0,
    waiting: 0,
    processing: 0,
    completed: 0,
    rejected: 0,
  };

  withdrawalStats.forEach((stat) => {
    const count = parseInt(stat.count);
    const amount = parseFloat(stat.total || 0);
    
    withdrawalCounts[stat.status] = (withdrawalCounts[stat.status] || 0) + count;
    withdrawalCounts.total += count;
    withdrawalCounts.totalAmount += amount;
    
    // 按货币类型统计提现金额
    if (stat.currency === 'PHP') {
      withdrawalCounts.totalAmountPeso += amount;
    } else {
      withdrawalCounts.totalAmountRmb += amount;
    }
  });

  // Add pending balance by currency from user model
  withdrawalCounts.pendingBalanceRmb = parseFloat(user.balance || 0).toFixed(2);
  withdrawalCounts.pendingBalancePeso = parseFloat(user.balancePeso || 0).toFixed(2);
  withdrawalCounts.totalAmountRmb = withdrawalCounts.totalAmountRmb.toFixed(2);
  withdrawalCounts.totalAmountPeso = withdrawalCounts.totalAmountPeso.toFixed(2);

  // Get recent login history
  const loginHistory = await LoginHistory.findAll({
    where: { userId, userType: 'user' },
    limit: 10,
    order: [['loginAt', 'DESC']],
    attributes: ['id', 'ipAddress', 'userAgent', 'deviceInfo', 'loginAt'],
  });

  return {
    user: user.toJSON(),
    inviter,
    appointments: appointmentCounts,
    invitations: invitationCounts,
    invitedUsers: invitedUsersWithCommissions,
    withdrawals: withdrawalCounts,
    loginHistory,
  };
};

/**
 * Update user status
 * @param {String} userId - User ID
 * @param {String} status - New status (active/suspended)
 * @returns {Promise<Object>} Updated user
 */
const updateUserStatus = async (userId, status) => {
  const user = await User.findByPk(userId);

  if (!user) {
    throw new Error('User not found');
  }

  if (!['active', 'suspended'].includes(status)) {
    throw new Error('Invalid status value');
  }

  user.status = status;
  await user.save();

  return user;
};

/**
 * Export user data to CSV
 * @param {Object} options - Query options (same as getUserList)
 * @returns {Promise<String>} CSV string
 */
const exportUsersToCSV = async (options = {}) => {
  // Get all users matching criteria (no pagination)
  const { search = '', status = '', language = '' } = options;

  const where = {};

  if (search) {
    where[Op.or] = [
      { nickname: { [Op.like]: `%${search}%` } },
      { realName: { [Op.like]: `%${search}%` } },
      { phone: { [Op.like]: `%${search}%` } },
      { wechatId: { [Op.like]: `%${search}%` } },
    ];
  }

  if (status) {
    where.status = status;
  }

  if (language) {
    where.language = language;
  }

  const users = await User.findAll({
    where,
    order: [['createdAt', 'DESC']],
    attributes: [
      'id',
      'nickname',
      'realName',
      'phone',
      'whatsapp',
      'wechatId',
      'language',
      'balance',
      'invitationCode',
      'status',
      'createdAt',
    ],
  });

  // Convert to plain objects
  const userData = users.map((user) => ({
    ID: user.id,
    Nickname: user.nickname || '',
    'Real Name': user.realName || '',
    Phone: user.phone || '',
    WhatsApp: user.whatsapp || '',
    'WeChat ID': user.wechatId || '',
    Language: user.language,
    Balance: user.balance,
    'Invitation Code': user.invitationCode || '',
    Status: user.status,
    'Created At': user.createdAt.toISOString(),
  }));

  // Convert to CSV
  const json2csvParser = new Parser();
  const csv = json2csvParser.parse(userData);

  return csv;
};

module.exports = {
  getUserList,
  getUserDetails,
  updateUserStatus,
  exportUsersToCSV,
};
