import {
  Controller,
  Post,
  Body,
  HttpCode,
  HttpStatus,
  UseGuards,
  Req,
  Headers,
} from '@nestjs/common';
import { ThrottlerGuard } from '@nestjs/throttler';
import { ApiTags, ApiOperation, ApiProperty } from '@nestjs/swagger';
import { IsString, IsNotEmpty, MinLength, Matches } from 'class-validator';
import { AuthService, LoginResult } from '@/application/services';

class RegisterDto {
  @ApiProperty({ description: '手机号', example: '13800138000' })
  @IsString()
  @IsNotEmpty({ message: '手机号不能为空' })
  @Matches(/^1[3-9]\d{9}$/, { message: '手机号格式不正确' })
  phone: string;

  @ApiProperty({ description: '密码', example: '123456' })
  @IsString()
  @IsNotEmpty({ message: '密码不能为空' })
  @MinLength(6, { message: '密码至少6位' })
  password: string;

  @ApiProperty({ description: '短信验证码', example: '123456' })
  @IsString()
  @IsNotEmpty({ message: '验证码不能为空' })
  @Matches(/^\d{6}$/, { message: '验证码格式不正确' })
  smsCode: string;
}

class LoginDto {
  @ApiProperty({ description: '手机号', example: '13800138000' })
  @IsString()
  @IsNotEmpty({ message: '手机号不能为空' })
  @Matches(/^1[3-9]\d{9}$/, { message: '手机号格式不正确' })
  phone: string;

  @ApiProperty({ description: '密码', example: '123456' })
  @IsString()
  @IsNotEmpty({ message: '密码不能为空' })
  password: string;
}

class LoginBySmsDto {
  @ApiProperty({ description: '手机号', example: '13800138000' })
  @IsString()
  @IsNotEmpty({ message: '手机号不能为空' })
  @Matches(/^1[3-9]\d{9}$/, { message: '手机号格式不正确' })
  phone: string;

  @ApiProperty({ description: '短信验证码', example: '123456' })
  @IsString()
  @IsNotEmpty({ message: '验证码不能为空' })
  @Matches(/^\d{6}$/, { message: '验证码格式不正确' })
  smsCode: string;
}

class RefreshTokenDto {
  @ApiProperty({ description: '刷新令牌' })
  @IsString()
  @IsNotEmpty({ message: '刷新令牌不能为空' })
  refreshToken: string;
}

@ApiTags('Auth')
@Controller('auth')
@UseGuards(ThrottlerGuard)
export class AuthController {
  constructor(private readonly authService: AuthService) {}

  /**
   * 用户注册
   * POST /auth/register
   */
  @Post('register')
  @ApiOperation({ summary: '用户注册' })
  async register(
    @Body() dto: RegisterDto,
    @Headers('X-Device-Info') deviceInfo?: string,
    @Req() req?: any,
  ): Promise<{ success: boolean; data: LoginResult }> {
    const result = await this.authService.register({
      phone: dto.phone,
      password: dto.password,
      smsCode: dto.smsCode,
    });

    return { success: true, data: result };
  }

  /**
   * 密码登录
   * POST /auth/login
   */
  @Post('login')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '密码登录' })
  async login(
    @Body() dto: LoginDto,
    @Headers('X-Device-Info') deviceInfo?: string,
    @Req() req?: any,
  ): Promise<{ success: boolean; data: LoginResult }> {
    const ipAddress = req?.ip || req?.connection?.remoteAddress;
    const result = await this.authService.loginByPassword({
      phone: dto.phone,
      password: dto.password,
      deviceInfo,
      ipAddress,
    });

    return { success: true, data: result };
  }

  /**
   * 验证码登录
   * POST /auth/login-sms
   */
  @Post('login-sms')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '验证码登录' })
  async loginBySms(
    @Body() dto: LoginBySmsDto,
    @Headers('X-Device-Info') deviceInfo?: string,
    @Req() req?: any,
  ): Promise<{ success: boolean; data: LoginResult }> {
    const ipAddress = req?.ip || req?.connection?.remoteAddress;
    const result = await this.authService.loginBySms({
      phone: dto.phone,
      smsCode: dto.smsCode,
      deviceInfo,
      ipAddress,
    });

    return { success: true, data: result };
  }

  /**
   * 刷新令牌
   * POST /auth/refresh
   */
  @Post('refresh')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '刷新访问令牌' })
  async refresh(
    @Body() dto: RefreshTokenDto,
  ): Promise<{ success: boolean; data: { accessToken: string; expiresIn: number } }> {
    const result = await this.authService.refreshToken(dto.refreshToken);
    return { success: true, data: result };
  }

  /**
   * 登出
   * POST /auth/logout
   */
  @Post('logout')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '退出登录' })
  async logout(
    @Body() dto: RefreshTokenDto,
  ): Promise<{ success: boolean }> {
    await this.authService.logout(dto.refreshToken);
    return { success: true };
  }
}
