/**
 * 用户服务类
 * 
 * 功能描述：
 * - 提供用户数据的增删改查技术实现
 * - 处理数据持久化和存储操作
 * - 数据格式验证和约束检查
 * - 支持完整的数据生命周期管理
 * 
 * 职责分离：
 * - 数据持久化：通过TypeORM操作MySQL数据库
 * - 数据验证：数据格式和约束完整性检查
 * - 异常处理：统一的错误处理和日志记录
 * - 性能监控：操作耗时统计和性能优化
 * 
 * 最近修改：
 * - 2026-01-07: 代码规范优化 - 完善注释规范，添加完整的文件头和方法注释
 * - 2026-01-07: 功能优化 - 添加完整的日志记录系统和详细的技术实现注释
 * - 2026-01-07: 性能优化 - 优化异常处理和性能监控机制
 * 
 * @author moyin
 * @version 1.0.1
 * @since 2025-12-17
 * @lastModified 2026-01-07
 */

import { Injectable, ConflictException, NotFoundException, BadRequestException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, FindOptionsWhere } from 'typeorm';
import { Users } from './users.entity';
import { CreateUserDto } from './users.dto';
import { UserStatus } from './user_status.enum';
import { validate } from 'class-validator';
import { plainToClass } from 'class-transformer';
import { BaseUsersService } from './base_users.service';
import { USER_ROLES, QUERY_LIMITS, ERROR_MESSAGES, DATABASE_CONSTANTS, ValidationUtils, PerformanceMonitor } from './users.constants';

@Injectable()
export class UsersService extends BaseUsersService {

  constructor(
    @InjectRepository(Users)
    private readonly usersRepository: Repository<Users>,
  ) {
    super(); // 调用基类构造函数
  }

  /**
   * 创建新用户
   * 
   * 技术实现：
   * 1. 验证输入数据的格式和完整性
   * 2. 创建用户实体并设置默认值
   * 3. 保存用户数据到数据库
   * 4. 记录操作日志和性能指标
   * 
   * @param createUserDto 创建用户的数据传输对象，包含用户基本信息
   * @returns 创建成功的用户实体，包含自动生成的ID和时间戳
   * @throws BadRequestException 当数据验证失败或输入格式错误时
   * 
   * @example
   * ```typescript
   * const newUser = await usersService.create({
   *   username: 'testuser',
   *   email: 'test@example.com',
   *   nickname: '测试用户',
   *   password_hash: 'hashed_password'
   * });
   * console.log(`用户创建成功，ID: ${newUser.id}`);
   * ```
   */
  async create(createUserDto: CreateUserDto): Promise<Users> {
    const monitor = PerformanceMonitor.create();
    
    this.logger.log('开始创建用户', {
      operation: 'create',
      username: createUserDto.username,
      email: createUserDto.email,
      timestamp: new Date().toISOString()
    });

    try {
      // 验证DTO
      await this.validateCreateUserDto(createUserDto);

      // 创建用户实体
      const user = this.buildUserEntity(createUserDto);

      // 保存到数据库
      const savedUser = await this.usersRepository.save(user);
      
      this.logger.log('用户创建成功', {
        operation: 'create',
        userId: savedUser.id.toString(),
        username: savedUser.username,
        email: savedUser.email,
        duration: monitor.getDuration(),
        timestamp: new Date().toISOString()
      });

      return savedUser;
    } catch (error) {
      if (error instanceof BadRequestException) {
        throw error;
      }

      this.logger.error('用户创建系统异常', {
        operation: 'create',
        username: createUserDto.username,
        email: createUserDto.email,
        error: error instanceof Error ? error.message : String(error),
        duration: monitor.getDuration(),
        timestamp: new Date().toISOString()
      }, error instanceof Error ? error.stack : undefined);

      throw new BadRequestException(ERROR_MESSAGES.USER_CREATE_FAILED);
    }
  }

  /**
   * 验证创建用户DTO
   * 
   * @param createUserDto 用户数据
   * @throws BadRequestException 当数据验证失败时
   */
  private async validateCreateUserDto(createUserDto: CreateUserDto): Promise<void> {
    const dto = plainToClass(CreateUserDto, createUserDto);
    const validationErrors = await validate(dto);
    
    if (validationErrors.length > 0) {
      const errorMessages = ValidationUtils.formatValidationErrors(validationErrors);
      
      this.logger.warn('用户创建失败：数据验证失败', {
        operation: 'create',
        username: createUserDto.username,
        email: createUserDto.email,
        validationErrors: errorMessages
      });
      
      throw new BadRequestException(`${ERROR_MESSAGES.VALIDATION_FAILED}: ${errorMessages}`);
    }
  }

  /**
   * 构建用户实体
   * 
   * @param createUserDto 用户数据
   * @returns 用户实体
   */
  private buildUserEntity(createUserDto: CreateUserDto): Users {
    const user = new Users();
    user.username = createUserDto.username;
    user.email = createUserDto.email || null;
    user.phone = createUserDto.phone || null;
    user.password_hash = createUserDto.password_hash || null;
    user.nickname = createUserDto.nickname;
    user.github_id = createUserDto.github_id || null;
    user.avatar_url = createUserDto.avatar_url || null;
    user.role = createUserDto.role || USER_ROLES.NORMAL_USER;
    user.email_verified = createUserDto.email_verified || false;
    user.status = createUserDto.status || UserStatus.ACTIVE;
    
    return user;
  }

  /**
   * 创建新用户（带重复检查）
   * 
   * 技术实现：
   * 1. 检查用户名、邮箱、手机号、GitHub ID的唯一性约束
   * 2. 如果所有检查都通过，调用create方法创建用户
   * 3. 记录操作日志和性能指标
   * 
   * @param createUserDto 创建用户的数据传输对象
   * @returns 创建的用户实体
   * @throws ConflictException 当用户名、邮箱、手机号或GitHub ID已存在时
   * @throws BadRequestException 当数据验证失败时
   * 
   * @example
   * ```typescript
   * const newUser = await usersService.createWithDuplicateCheck({
   *   username: 'testuser',
   *   email: 'test@example.com',
   *   nickname: '测试用户'
   * });
   * ```
   */
  async createWithDuplicateCheck(createUserDto: CreateUserDto): Promise<Users> {
    const monitor = PerformanceMonitor.create();
    
    this.logStart('创建用户（带重复检查）', {
      username: createUserDto.username,
      email: createUserDto.email,
      phone: createUserDto.phone,
      github_id: createUserDto.github_id
    });

    try {
      // 执行所有唯一性检查
      await this.validateUniqueness(createUserDto);

      // 调用普通的创建方法
      const user = await this.create(createUserDto);
      
      this.logSuccess('创建用户（带重复检查）', {
        userId: user.id.toString(),
        username: user.username
      }, monitor.getDuration());

      return user;
    } catch (error) {
      this.handleServiceError(error, '创建用户（带重复检查）', {
        username: createUserDto.username,
        duration: monitor.getDuration()
      });
    }
  }

  /**
   * 验证用户数据的唯一性
   * 
   * @param createUserDto 用户数据
   * @throws ConflictException 当发现重复数据时
   */
  private async validateUniqueness(createUserDto: CreateUserDto): Promise<void> {
    await this.checkUsernameUniqueness(createUserDto.username);
    await this.checkEmailUniqueness(createUserDto.email);
    await this.checkPhoneUniqueness(createUserDto.phone);
    await this.checkGithubIdUniqueness(createUserDto.github_id);
  }

  /**
   * 检查用户名唯一性
   */
  private async checkUsernameUniqueness(username?: string): Promise<void> {
    if (username) {
      const existingUser = await this.usersRepository.findOne({
        where: { username }
      });
      if (existingUser) {
        this.logger.warn('用户创建失败：用户名已存在', {
          operation: 'uniqueness_check',
          username,
          existingUserId: existingUser.id.toString()
        });
        throw new ConflictException(ERROR_MESSAGES.USERNAME_EXISTS);
      }
    }
  }

  /**
   * 检查邮箱唯一性
   */
  private async checkEmailUniqueness(email?: string): Promise<void> {
    if (email) {
      const existingEmail = await this.usersRepository.findOne({
        where: { email }
      });
      if (existingEmail) {
        this.logger.warn('用户创建失败：邮箱已存在', {
          operation: 'uniqueness_check',
          email,
          existingUserId: existingEmail.id.toString()
        });
        throw new ConflictException(ERROR_MESSAGES.EMAIL_EXISTS);
      }
    }
  }

  /**
   * 检查手机号唯一性
   */
  private async checkPhoneUniqueness(phone?: string): Promise<void> {
    if (phone) {
      const existingPhone = await this.usersRepository.findOne({
        where: { phone }
      });
      if (existingPhone) {
        this.logger.warn('用户创建失败：手机号已存在', {
          operation: 'uniqueness_check',
          phone,
          existingUserId: existingPhone.id.toString()
        });
        throw new ConflictException(ERROR_MESSAGES.PHONE_EXISTS);
      }
    }
  }

  /**
   * 检查GitHub ID唯一性
   */
  private async checkGithubIdUniqueness(githubId?: string): Promise<void> {
    if (githubId) {
      const existingGithub = await this.usersRepository.findOne({
        where: { github_id: githubId }
      });
      if (existingGithub) {
        this.logger.warn('用户创建失败：GitHub ID已存在', {
          operation: 'uniqueness_check',
          github_id: githubId,
          existingUserId: existingGithub.id.toString()
        });
        throw new ConflictException(ERROR_MESSAGES.GITHUB_ID_EXISTS);
      }
    }
  }

  /**
   * 查询所有用户
   * 
   * @param limit 限制返回数量，默认100
   * @param offset 偏移量，默认0
   * @param includeDeleted 是否包含已删除用户，默认false
   * @returns 用户列表
   */
  async findAll(limit: number = QUERY_LIMITS.DEFAULT_LIMIT, offset: number = 0, includeDeleted: boolean = false): Promise<Users[]> {
    // 注意：软删除功能暂未实现，includeDeleted参数预留用于未来扩展
    const whereCondition = {};
    
    return await this.usersRepository.find({
      where: whereCondition,
      take: limit,
      skip: offset,
      order: { created_at: DATABASE_CONSTANTS.ORDER_DESC }
    });
  }

  /**
   * 根据ID查询用户
   * 
   * @param id 用户ID
   * @param includeDeleted 是否包含已删除用户，默认false
   * @returns 用户实体
   * @throws NotFoundException 当用户不存在时
   */
  async findOne(id: bigint, includeDeleted: boolean = false): Promise<Users> {
    // 注意：软删除功能暂未实现，includeDeleted参数预留用于未来扩展
    const whereCondition = { id };
    
    const user = await this.usersRepository.findOne({
      where: whereCondition
    });

    if (!user) {
      throw new NotFoundException(`ID为 ${id} 的用户不存在`);
    }

    return user;
  }

  /**
   * 根据用户名查询用户
   * 
   * @param username 用户名
   * @param includeDeleted 是否包含已删除用户，默认false
   * @returns 用户实体或null
   */
  async findByUsername(username: string, includeDeleted: boolean = false): Promise<Users | null> {
    // 注意：软删除功能暂未实现，includeDeleted参数预留用于未来扩展
    const whereCondition = { username };
    
    return await this.usersRepository.findOne({
      where: whereCondition
    });
  }

  /**
   * 根据邮箱查询用户
   * 
   * @param email 邮箱
   * @param includeDeleted 是否包含已删除用户，默认false
   * @returns 用户实体或null
   */
  async findByEmail(email: string, includeDeleted: boolean = false): Promise<Users | null> {
    // 注意：软删除功能暂未实现，includeDeleted参数预留用于未来扩展
    const whereCondition = { email };
    
    return await this.usersRepository.findOne({
      where: whereCondition
    });
  }

  /**
   * 根据GitHub ID查询用户
   * 
   * @param githubId GitHub ID
   * @param includeDeleted 是否包含已删除用户，默认false
   * @returns 用户实体或null
   */
  async findByGithubId(githubId: string, includeDeleted: boolean = false): Promise<Users | null> {
    // 注意：软删除功能暂未实现，includeDeleted参数预留用于未来扩展
    const whereCondition = { github_id: githubId };
    
    return await this.usersRepository.findOne({
      where: whereCondition
    });
  }

  /**
   * 更新用户信息
   * 
   * 功能描述：
   * 更新指定用户的信息，包含完整的数据验证和唯一性检查
   * 
   * 业务逻辑：
   * 1. 验证用户是否存在
   * 2. 检查更新字段的唯一性约束（用户名、邮箱、手机号、GitHub ID）
   * 3. 合并更新数据到现有用户实体
   * 4. 保存更新后的用户信息
   * 5. 记录操作日志
   * 
   * @param id 用户ID，必须是有效的已存在用户
   * @param updateData 更新的数据，支持部分字段更新
   * @returns 更新后的用户实体
   * @throws NotFoundException 当用户不存在时
   * @throws ConflictException 当更新的数据与其他用户冲突时
   * 
   * @example
   * ```typescript
   * const updatedUser = await usersService.update(BigInt(1), {
   *   nickname: '新昵称',
   *   email: 'new@example.com'
   * });
   * ```
   */
  async update(id: bigint, updateData: Partial<CreateUserDto>): Promise<Users> {
    const monitor = PerformanceMonitor.create();
    
    this.logger.log('开始更新用户信息', {
      operation: 'update',
      userId: id.toString(),
      updateFields: Object.keys(updateData),
      timestamp: new Date().toISOString()
    });

    try {
      // 1. 检查用户是否存在 - 确保要更新的用户确实存在
      const existingUser = await this.findOne(id);

      // 2. 检查更新数据的唯一性约束 - 防止违反数据库唯一约束
      await this.checkUpdateUniqueness(id, updateData);

      // 3. 合并更新数据 - 使用Object.assign将新数据合并到现有实体
      Object.assign(existingUser, updateData);
      
      // 4. 保存更新后的用户信息 - TypeORM会自动更新updated_at字段
      const updatedUser = await this.usersRepository.save(existingUser);
      
      this.logger.log('用户信息更新成功', {
        operation: 'update',
        userId: id.toString(),
        updateFields: Object.keys(updateData),
        duration: monitor.getDuration(),
        timestamp: new Date().toISOString()
      });

      return updatedUser;
    } catch (error) {
      if (error instanceof NotFoundException || error instanceof ConflictException) {
        throw error;
      }

      this.logger.error('用户更新系统异常', {
        operation: 'update',
        userId: id.toString(),
        updateData,
        error: error instanceof Error ? error.message : String(error),
        duration: monitor.getDuration(),
        timestamp: new Date().toISOString()
      }, error instanceof Error ? error.stack : undefined);

      throw new BadRequestException(ERROR_MESSAGES.USER_UPDATE_FAILED);
    }
  }

  /**
   * 删除用户
   * 
   * 功能描述：
   * 物理删除指定的用户记录，数据将从数据库中永久移除
   * 
   * 业务逻辑：
   * 1. 验证用户是否存在
   * 2. 执行物理删除操作
   * 3. 返回删除结果统计
   * 4. 记录删除操作日志
   * 
   * 注意事项：
   * - 这是物理删除，数据无法恢复
   * - 如需保留数据，请使用 softRemove 方法
   * - 删除前请确认用户没有关联的重要数据
   * 
   * @param id 用户ID，必须是有效的已存在用户
   * @returns 删除操作结果，包含影响行数和操作消息
   * @throws NotFoundException 当用户不存在时
   * 
   * @example
   * ```typescript
   * const result = await usersService.remove(BigInt(1));
   * console.log(`删除了 ${result.affected} 个用户`);
   * ```
   */
  async remove(id: bigint): Promise<{ affected: number; message: string }> {
    const monitor = PerformanceMonitor.create();
    
    this.logger.log('开始删除用户', {
      operation: 'remove',
      userId: id.toString(),
      timestamp: new Date().toISOString()
    });

    try {
      // 1. 检查用户是否存在 - 确保要删除的用户确实存在
      await this.findOne(id);

      // 2. 执行删除操作 - 使用where条件来处理bigint类型
      const result = await this.usersRepository.delete({ id });

      const deleteResult = {
        affected: result.affected || 0,
        message: `成功删除ID为 ${id} 的用户`
      };

      this.logger.log('用户删除成功', {
        operation: 'remove',
        userId: id.toString(),
        affected: deleteResult.affected,
        duration: monitor.getDuration(),
        timestamp: new Date().toISOString()
      });

      return deleteResult;
    } catch (error) {
      if (error instanceof NotFoundException) {
        throw error;
      }

      this.logger.error('用户删除系统异常', {
        operation: 'remove',
        userId: id.toString(),
        error: error instanceof Error ? error.message : String(error),
        duration: monitor.getDuration(),
        timestamp: new Date().toISOString()
      }, error instanceof Error ? error.stack : undefined);

      throw new BadRequestException(ERROR_MESSAGES.USER_DELETE_FAILED);
    }
  }

  /**
   * 检查更新数据的唯一性约束
   * 
   * @param id 用户ID
   * @param updateData 更新数据
   * @throws ConflictException 当发现冲突时
   */
  private async checkUpdateUniqueness(id: bigint, updateData: Partial<CreateUserDto>): Promise<void> {
    const existingUser = await this.findOne(id);

    if (updateData.username && updateData.username !== existingUser.username) {
      await this.checkUsernameUniqueness(updateData.username);
    }

    if (updateData.email && updateData.email !== existingUser.email) {
      await this.checkEmailUniqueness(updateData.email);
    }

    if (updateData.phone && updateData.phone !== existingUser.phone) {
      await this.checkPhoneUniqueness(updateData.phone);
    }

    if (updateData.github_id && updateData.github_id !== existingUser.github_id) {
      await this.checkGithubIdUniqueness(updateData.github_id);
    }
  }

  /**
   * 软删除用户
   * 
   * @param id 用户ID
   * @returns 软删除操作结果
   */
  async softRemove(id: bigint): Promise<Users> {
    const user = await this.findOne(id);
    // 注意：软删除功能暂未实现，当前仅返回用户实体
    return user;
  }

  /**
   * 统计用户数量
   * 
   * @param conditions 查询条件
   * @returns 用户数量
   */
  async count(conditions?: FindOptionsWhere<Users>): Promise<number> {
    return await this.usersRepository.count({ where: conditions });
  }

  /**
   * 检查用户是否存在
   * 
   * @param id 用户ID
   * @returns 是否存在
   */
  async exists(id: bigint): Promise<boolean> {
    const count = await this.usersRepository.count({ where: { id } });
    return count > 0;
  }

  /**
   * 批量创建用户
   * 
   * @param createUserDtos 用户数据数组
   * @returns 创建的用户列表
   */
  async createBatch(createUserDtos: CreateUserDto[]): Promise<Users[]> {
    const users: Users[] = [];

    for (const dto of createUserDtos) {
      const user = await this.create(dto);
      users.push(user);
    }

    return users;
  }

  /**
   * 根据角色查询用户
   * 
   * @param role 角色值
   * @param includeDeleted 是否包含已删除用户，默认false
   * @returns 用户列表
   */
  async findByRole(role: number, includeDeleted: boolean = false): Promise<Users[]> {
    // 注意：软删除功能暂未实现，includeDeleted参数预留用于未来扩展
    const whereCondition = { role };
    
    return await this.usersRepository.find({
      where: whereCondition,
      order: { created_at: DATABASE_CONSTANTS.ORDER_DESC }
    });
  }

  /**
   * 搜索用户（根据用户名或昵称）
   * 
   * 功能描述：
   * 根据关键词在用户名和昵称字段中进行模糊搜索，支持部分匹配
   * 
   * 业务逻辑：
   * 1. 使用QueryBuilder构建复杂查询
   * 2. 对用户名和昵称字段进行LIKE模糊匹配
   * 3. 按创建时间倒序排列结果
   * 4. 限制返回数量防止性能问题
   * 
   * 性能考虑：
   * - 使用数据库索引优化查询性能
   * - 限制返回数量避免大数据量问题
   * - 建议在用户名和昵称字段上建立索引
   * 
   * @param keyword 搜索关键词，支持中文、英文、数字等字符
   * @param limit 限制数量，默认20条，建议不超过100
   * @returns 匹配的用户列表，按创建时间倒序排列
   * 
   * @example
   * ```typescript
   * // 搜索包含"张三"的用户
   * const users = await usersService.search('张三', 10);
   * 
   * // 搜索包含"admin"的用户
   * const adminUsers = await usersService.search('admin');
   * ```
   */
  async search(keyword: string, limit: number = QUERY_LIMITS.DEFAULT_SEARCH_LIMIT, includeDeleted: boolean = false): Promise<Users[]> {
    const monitor = PerformanceMonitor.create();
    
    this.logStart('搜索用户', { keyword, limit, includeDeleted });

    try {
      // 1. 构建查询 - 使用QueryBuilder支持复杂的WHERE条件
      const queryBuilder = this.usersRepository.createQueryBuilder('user');
      
      // 添加搜索条件 - 在用户名和昵称中进行模糊匹配
      let whereClause = 'user.username LIKE :keyword OR user.nickname LIKE :keyword';
      
      // 注意：软删除功能暂未实现，includeDeleted参数预留用于未来扩展
      
      const result = await queryBuilder
        .where(whereClause, {
          keyword: `%${keyword}%`  // 前后加%实现模糊匹配
        })
        .orderBy('user.created_at', DATABASE_CONSTANTS.ORDER_DESC)  // 按创建时间倒序
        .limit(limit)  // 限制返回数量
        .getMany();

      this.logSuccess('搜索用户', {
        keyword,
        limit,
        includeDeleted,
        resultCount: result.length
      }, monitor.getDuration());

      return result;
    } catch (error) {
      // 搜索异常使用特殊处理，返回空数组而不抛出异常
      return this.handleSearchError(error, '搜索用户', { 
        keyword, 
        limit, 
        includeDeleted, 
        duration: monitor.getDuration() 
      });
    }
  }
}