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 { 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
  const invitationStats = await Invitation.findAll({
    where: { inviterId: userId },
    attributes: [
      [require('sequelize').fn('COUNT', require('sequelize').col('id')), 'totalInvites'],
      [require('sequelize').fn('SUM', require('sequelize').col('reward_amount')), 'totalRewards'],
    ],
    raw: true,
  });

  const invitationCounts = {
    totalInvites: parseInt(invitationStats[0]?.totalInvites || 0),
    totalRewards: parseFloat(invitationStats[0]?.totalRewards || 0),
  };

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

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

  withdrawalStats.forEach((stat) => {
    withdrawalCounts[stat.status] = parseInt(stat.count);
    withdrawalCounts.total += parseInt(stat.count);
    withdrawalCounts.totalAmount += parseFloat(stat.total || 0);
  });

  // 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,
    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,
};
