/**
 * 登录业务数据传输对象
 * 
 * 功能描述：
 * - 定义登录相关API的请求数据结构
 * - 提供数据验证规则和错误提示
 * - 确保API接口的数据格式一致性
 * 
 * 职责分离：
 * - 专注于数据结构定义和验证规则
 * - 提供Swagger文档生成支持
 * - 确保类型安全和数据完整性
 * 
 * 最近修改：
 * - 2026-01-07: 代码规范优化 - 文件夹扁平化，移除单文件文件夹结构
 * - 2026-01-07: 代码规范优化 - 更新注释规范，修正作者信息
 * 
 * @author moyin
 * @version 1.0.2
 * @since 2025-12-17
 * @lastModified 2026-01-07
 */

import { 
  IsString, 
  IsEmail, 
  IsPhoneNumber, 
  IsNotEmpty, 
  Length, 
  IsOptional,
  Matches,
  IsNumberString
} from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';

/**
 * 登录请求DTO
 */
export class LoginDto {
  /**
   * 登录标识符
   * 支持用户名、邮箱或手机号登录
   */
  @ApiProperty({
    description: '登录标识符，支持用户名、邮箱或手机号',
    example: 'testuser',
    minLength: 1,
    maxLength: 100
  })
  @IsString({ message: '登录标识符必须是字符串' })
  @IsNotEmpty({ message: '登录标识符不能为空' })
  @Length(1, 100, { message: '登录标识符长度需在1-100字符之间' })
  identifier: string;

  /**
   * 密码
   */
  @ApiProperty({
    description: '用户密码',
    example: 'password123',
    minLength: 1,
    maxLength: 128
  })
  @IsString({ message: '密码必须是字符串' })
  @IsNotEmpty({ message: '密码不能为空' })
  @Length(1, 128, { message: '密码长度需在1-128字符之间' })
  password: string;
}

/**
 * 注册请求DTO
 */
export class RegisterDto {
  /**
   * 用户名
   */
  @ApiProperty({
    description: '用户名，只能包含字母、数字和下划线',
    example: 'testuser',
    minLength: 1,
    maxLength: 50,
    pattern: '^[a-zA-Z0-9_]+$'
  })
  @IsString({ message: '用户名必须是字符串' })
  @IsNotEmpty({ message: '用户名不能为空' })
  @Length(1, 50, { message: '用户名长度需在1-50字符之间' })
  @Matches(/^[a-zA-Z0-9_]+$/, { message: '用户名只能包含字母、数字和下划线' })
  username: string;

  /**
   * 密码
   */
  @ApiProperty({
    description: '密码，必须包含字母和数字，长度8-128字符',
    example: 'password123',
    minLength: 8,
    maxLength: 128
  })
  @IsString({ message: '密码必须是字符串' })
  @IsNotEmpty({ message: '密码不能为空' })
  @Length(8, 128, { message: '密码长度需在8-128字符之间' })
  @Matches(/^(?=.*[a-zA-Z])(?=.*\d)/, { message: '密码必须包含字母和数字' })
  password: string;

  /**
   * 昵称
   */
  @ApiProperty({
    description: '用户昵称',
    example: '测试用户',
    minLength: 1,
    maxLength: 50
  })
  @IsString({ message: '昵称必须是字符串' })
  @IsNotEmpty({ message: '昵称不能为空' })
  @Length(1, 50, { message: '昵称长度需在1-50字符之间' })
  nickname: string;

  /**
   * 邮箱（可选）
   */
  @ApiProperty({
    description: '邮箱地址（可选）',
    example: 'test@example.com',
    required: false
  })
  @IsOptional()
  @IsEmail({}, { message: '邮箱格式不正确' })
  email?: string;

  /**
   * 手机号（可选）
   */
  @ApiProperty({
    description: '手机号码（可选）',
    example: '+8613800138000',
    required: false
  })
  @IsOptional()
  @IsPhoneNumber(null, { message: '手机号格式不正确' })
  phone?: string;

  /**
   * 邮箱验证码（当提供邮箱时必填）
   */
  @ApiProperty({
    description: '邮箱验证码，当提供邮箱时必填',
    example: '123456',
    pattern: '^\\d{6}$',
    required: false
  })
  @IsOptional()
  @IsString({ message: '验证码必须是字符串' })
  @Matches(/^\d{6}$/, { message: '验证码必须是6位数字' })
  email_verification_code?: string;
}

/**
 * GitHub OAuth登录请求DTO
 */
export class GitHubOAuthDto {
  /**
   * GitHub用户ID
   */
  @ApiProperty({
    description: 'GitHub用户ID',
    example: '12345678',
    minLength: 1,
    maxLength: 100
  })
  @IsString({ message: 'GitHub ID必须是字符串' })
  @IsNotEmpty({ message: 'GitHub ID不能为空' })
  @Length(1, 100, { message: 'GitHub ID长度需在1-100字符之间' })
  github_id: string;

  /**
   * 用户名
   */
  @ApiProperty({
    description: 'GitHub用户名',
    example: 'octocat',
    minLength: 1,
    maxLength: 50
  })
  @IsString({ message: '用户名必须是字符串' })
  @IsNotEmpty({ message: '用户名不能为空' })
  @Length(1, 50, { message: '用户名长度需在1-50字符之间' })
  username: string;

  /**
   * 昵称
   */
  @ApiProperty({
    description: 'GitHub显示名称',
    example: 'The Octocat',
    minLength: 1,
    maxLength: 50
  })
  @IsString({ message: '昵称必须是字符串' })
  @IsNotEmpty({ message: '昵称不能为空' })
  @Length(1, 50, { message: '昵称长度需在1-50字符之间' })
  nickname: string;

  /**
   * 邮箱（可选）
   */
  @ApiProperty({
    description: 'GitHub邮箱地址（可选）',
    example: 'octocat@github.com',
    required: false
  })
  @IsOptional()
  @IsEmail({}, { message: '邮箱格式不正确' })
  email?: string;

  /**
   * 头像URL（可选）
   */
  @ApiProperty({
    description: 'GitHub头像URL（可选）',
    example: 'https://github.com/images/error/octocat_happy.gif',
    required: false
  })
  @IsOptional()
  @IsString({ message: '头像URL必须是字符串' })
  avatar_url?: string;
}

/**
 * 忘记密码请求DTO
 */
export class ForgotPasswordDto {
  /**
   * 邮箱或手机号
   */
  @ApiProperty({
    description: '邮箱或手机号',
    example: 'test@example.com',
    minLength: 1,
    maxLength: 100
  })
  @IsString({ message: '标识符必须是字符串' })
  @IsNotEmpty({ message: '邮箱或手机号不能为空' })
  @Length(1, 100, { message: '标识符长度需在1-100字符之间' })
  identifier: string;
}

/**
 * 重置密码请求DTO
 */
export class ResetPasswordDto {
  /**
   * 邮箱或手机号
   */
  @ApiProperty({
    description: '邮箱或手机号',
    example: 'test@example.com',
    minLength: 1,
    maxLength: 100
  })
  @IsString({ message: '标识符必须是字符串' })
  @IsNotEmpty({ message: '邮箱或手机号不能为空' })
  @Length(1, 100, { message: '标识符长度需在1-100字符之间' })
  identifier: string;

  /**
   * 验证码
   */
  @ApiProperty({
    description: '6位数字验证码',
    example: '123456',
    pattern: '^\\d{6}$'
  })
  @IsString({ message: '验证码必须是字符串' })
  @IsNotEmpty({ message: '验证码不能为空' })
  @Matches(/^\d{6}$/, { message: '验证码必须是6位数字' })
  verification_code: string;

  /**
   * 新密码
   */
  @ApiProperty({
    description: '新密码，必须包含字母和数字，长度8-128字符',
    example: 'newpassword123',
    minLength: 8,
    maxLength: 128
  })
  @IsString({ message: '新密码必须是字符串' })
  @IsNotEmpty({ message: '新密码不能为空' })
  @Length(8, 128, { message: '新密码长度需在8-128字符之间' })
  @Matches(/^(?=.*[a-zA-Z])(?=.*\d)/, { message: '新密码必须包含字母和数字' })
  new_password: string;
}

/**
 * 修改密码请求DTO
 */
export class ChangePasswordDto {
  /**
   * 用户ID
   * 实际应用中应从JWT令牌中获取，这里为了演示放在请求体中
   */
  @ApiProperty({
    description: '用户ID（实际应用中应从JWT令牌中获取）',
    example: '1'
  })
  @IsNumberString({}, { message: '用户ID必须是数字字符串' })
  @IsNotEmpty({ message: '用户ID不能为空' })
  user_id: string;

  /**
   * 旧密码
   */
  @ApiProperty({
    description: '当前密码',
    example: 'oldpassword123',
    minLength: 1,
    maxLength: 128
  })
  @IsString({ message: '旧密码必须是字符串' })
  @IsNotEmpty({ message: '旧密码不能为空' })
  @Length(1, 128, { message: '旧密码长度需在1-128字符之间' })
  old_password: string;

  /**
   * 新密码
   */
  @ApiProperty({
    description: '新密码，必须包含字母和数字，长度8-128字符',
    example: 'newpassword123',
    minLength: 8,
    maxLength: 128
  })
  @IsString({ message: '新密码必须是字符串' })
  @IsNotEmpty({ message: '新密码不能为空' })
  @Length(8, 128, { message: '新密码长度需在8-128字符之间' })
  @Matches(/^(?=.*[a-zA-Z])(?=.*\d)/, { message: '新密码必须包含字母和数字' })
  new_password: string;
}

/**
 * 邮箱验证请求DTO
 */
export class EmailVerificationDto {
  /**
   * 邮箱地址
   */
  @ApiProperty({
    description: '邮箱地址',
    example: 'test@example.com'
  })
  @IsEmail({}, { message: '邮箱格式不正确' })
  @IsNotEmpty({ message: '邮箱不能为空' })
  email: string;

  /**
   * 验证码
   */
  @ApiProperty({
    description: '6位数字验证码',
    example: '123456',
    pattern: '^\\d{6}$'
  })
  @IsString({ message: '验证码必须是字符串' })
  @IsNotEmpty({ message: '验证码不能为空' })
  @Matches(/^\d{6}$/, { message: '验证码必须是6位数字' })
  verification_code: string;
}

/**
 * 发送邮箱验证码请求DTO
 */
export class SendEmailVerificationDto {
  /**
   * 邮箱地址
   */
  @ApiProperty({
    description: '邮箱地址',
    example: 'test@example.com'
  })
  @IsEmail({}, { message: '邮箱格式不正确' })
  @IsNotEmpty({ message: '邮箱不能为空' })
  email: string;
}

/**
 * 验证码登录请求DTO
 */
export class VerificationCodeLoginDto {
  /**
   * 登录标识符
   * 支持邮箱或手机号登录
   */
  @ApiProperty({
    description: '登录标识符，支持邮箱或手机号',
    example: 'test@example.com',
    minLength: 1,
    maxLength: 100
  })
  @IsString({ message: '登录标识符必须是字符串' })
  @IsNotEmpty({ message: '登录标识符不能为空' })
  @Length(1, 100, { message: '登录标识符长度需在1-100字符之间' })
  identifier: string;

  /**
   * 验证码
   */
  @ApiProperty({
    description: '6位数字验证码',
    example: '123456',
    pattern: '^\\d{6}$'
  })
  @IsString({ message: '验证码必须是字符串' })
  @IsNotEmpty({ message: '验证码不能为空' })
  @Matches(/^\d{6}$/, { message: '验证码必须是6位数字' })
  verification_code: string;
}

/**
 * 发送登录验证码请求DTO
 */
export class SendLoginVerificationCodeDto {
  /**
   * 登录标识符
   * 支持邮箱或手机号
   */
  @ApiProperty({
    description: '登录标识符，支持邮箱或手机号',
    example: 'test@example.com',
    minLength: 1,
    maxLength: 100
  })
  @IsString({ message: '登录标识符必须是字符串' })
  @IsNotEmpty({ message: '登录标识符不能为空' })
  @Length(1, 100, { message: '登录标识符长度需在1-100字符之间' })
  identifier: string;
}

/**
 * 刷新令牌请求DTO
 */
export class RefreshTokenDto {
  /**
   * 刷新令牌
   */
  @ApiProperty({
    description: 'JWT刷新令牌',
    example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
    minLength: 1
  })
  @IsString({ message: '刷新令牌必须是字符串' })
  @IsNotEmpty({ message: '刷新令牌不能为空' })
  refresh_token: string;
}