import {
  Controller,
  Post,
  Body,
  HttpCode,
  HttpStatus,
  UseGuards,
  Req,
  Ip,
} from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth } from '@nestjs/swagger';
import { AuthGuard } from '@nestjs/passport';
import { ThrottlerGuard } from '@nestjs/throttler';
import { AuthService } from '../../../application/services/auth.service';
import { RegisterDto } from '../dto/register.dto';
import { LoginDto } from '../dto/login.dto';
import { RefreshTokenDto } from '../dto/refresh-token.dto';
import { ChangePasswordDto } from '../dto/change-password.dto';
import { SendSmsCodeDto } from '../dto/send-sms-code.dto';
import { LoginPhoneDto } from '../dto/login-phone.dto';
import { ResetPasswordDto } from '../dto/reset-password.dto';
import { ChangePhoneDto } from '../dto/change-phone.dto';

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

  /* ── SMS 验证码 ── */

  @Post('sms/send')
  @HttpCode(HttpStatus.OK)
  @UseGuards(ThrottlerGuard)
  @ApiOperation({ summary: '发送短信验证码' })
  @ApiResponse({ status: 200, description: '验证码发送成功' })
  @ApiResponse({ status: 400, description: '手机号无效 / 日发送限额已满' })
  async sendSmsCode(@Body() dto: SendSmsCodeDto) {
    const result = await this.authService.sendSmsCode(dto.phone, dto.type);
    return {
      code: 0,
      data: result,
      message: '验证码发送成功',
    };
  }

  /* ── 注册 ── */

  @Post('register')
  @ApiOperation({ summary: '手机号注册 (需先获取验证码)' })
  @ApiResponse({ status: 201, description: '注册成功' })
  @ApiResponse({ status: 400, description: '验证码错误' })
  @ApiResponse({ status: 409, description: '手机号已注册' })
  async register(@Body() dto: RegisterDto) {
    const result = await this.authService.register(dto);
    return {
      code: 0,
      data: result,
      message: '注册成功',
    };
  }

  /* ── 密码登录 ── */

  @Post('login')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '密码登录 (手机号/邮箱 + 密码)' })
  @ApiResponse({ status: 200, description: '登录成功' })
  @ApiResponse({ status: 401, description: '账号或密码错误' })
  @ApiResponse({ status: 403, description: '账号已锁定/冻结' })
  async login(@Body() dto: LoginDto, @Ip() ip: string) {
    const result = await this.authService.login({
      ...dto,
      ipAddress: ip,
    });
    return {
      code: 0,
      data: result,
      message: '登录成功',
    };
  }

  /* ── 短信验证码登录 ── */

  @Post('login-phone')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '短信验证码登录' })
  @ApiResponse({ status: 200, description: '登录成功' })
  @ApiResponse({ status: 401, description: '验证码错误或手机号未注册' })
  async loginWithPhone(@Body() dto: LoginPhoneDto, @Ip() ip: string) {
    const result = await this.authService.loginWithPhone(
      dto.phone,
      dto.smsCode,
      dto.deviceInfo,
      ip,
    );
    return {
      code: 0,
      data: result,
      message: '登录成功',
    };
  }

  /* ── 重置密码 ── */

  @Post('reset-password')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '重置密码 (手机号 + 验证码 + 新密码)' })
  @ApiResponse({ status: 200, description: '密码重置成功' })
  @ApiResponse({ status: 400, description: '验证码错误或手机号未注册' })
  async resetPassword(@Body() dto: ResetPasswordDto) {
    await this.authService.resetPassword(dto.phone, dto.smsCode, dto.newPassword);
    return {
      code: 0,
      data: null,
      message: '密码重置成功，请重新登录',
    };
  }

  /* ── 更换手机号 ── */

  @Post('change-phone')
  @HttpCode(HttpStatus.OK)
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiOperation({ summary: '更换绑定手机号 (需登录)' })
  @ApiResponse({ status: 200, description: '手机号更换成功' })
  @ApiResponse({ status: 400, description: '验证码错误' })
  @ApiResponse({ status: 409, description: '新手机号已被使用' })
  async changePhone(@Req() req: any, @Body() dto: ChangePhoneDto) {
    await this.authService.changePhone(req.user.id, dto.newPhone, dto.newSmsCode);
    return {
      code: 0,
      data: null,
      message: '手机号更换成功',
    };
  }

  /* ── Token 刷新 ── */

  @Post('refresh')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '刷新 access token' })
  @ApiResponse({ status: 200, description: 'Token 刷新成功' })
  @ApiResponse({ status: 401, description: 'Refresh token 无效' })
  async refresh(@Body() dto: RefreshTokenDto) {
    const tokens = await this.authService.refreshToken(dto.refreshToken);
    return {
      code: 0,
      data: tokens,
      message: 'Token 刷新成功',
    };
  }

  /* ── 登出 ── */

  @Post('logout')
  @HttpCode(HttpStatus.OK)
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiOperation({ summary: '登出 (撤销所有 refresh token)' })
  async logout(@Req() req: any) {
    await this.authService.logout(req.user.id);
    return {
      code: 0,
      data: null,
      message: '已登出',
    };
  }

  /* ── 修改密码 ── */

  @Post('change-password')
  @HttpCode(HttpStatus.OK)
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiOperation({ summary: '修改密码 (需登录)' })
  async changePassword(@Req() req: any, @Body() dto: ChangePasswordDto) {
    await this.authService.changePassword(req.user.id, dto.oldPassword, dto.newPassword);
    return {
      code: 0,
      data: null,
      message: '密码修改成功',
    };
  }
}
