import {
  Controller,
  Post,
  Body,
  Inject,
  BadRequestException,
  HttpCode,
  HttpStatus,
} from '@nestjs/common';
import { SmsService } from '../../../infrastructure/sms/sms.service';
import { REDIS_CLIENT } from '../../../infrastructure/redis/redis.provider';
import Redis from 'ioredis';

const OTP_TTL = 300; // 5 minutes
const RATE_LIMIT_TTL = 60; // 1 per minute per phone

function generateCode(): string {
  return Math.floor(100000 + Math.random() * 900000).toString();
}

@Controller('api/v1/auth/sms')
export class SmsController {
  constructor(
    private readonly smsService: SmsService,
    @Inject(REDIS_CLIENT) private readonly redis: Redis,
  ) {}

  /**
   * POST /api/v1/auth/sms/send
   * Send OTP to phone. Rate-limited: 1 per minute per phone number.
   * purpose: 'register' | 'login'
   */
  @Post('send')
  @HttpCode(HttpStatus.OK)
  async sendOtp(@Body() body: { phone: string; purpose?: string }) {
    const phone = (body.phone || '').trim();
    if (!phone) throw new BadRequestException('手机号不能为空');

    const rateKey = `sms:rate:${phone}`;
    const already = await this.redis.get(rateKey);
    if (already) {
      throw new BadRequestException('发送太频繁，请 60 秒后再试');
    }

    const code = generateCode();
    const otpKey = `sms:otp:${phone}`;

    // Store OTP first, then send (avoid race condition)
    await this.redis.set(otpKey, code, 'EX', OTP_TTL);
    await this.redis.set(rateKey, '1', 'EX', RATE_LIMIT_TTL);

    const result = await this.smsService.sendVerificationCode(phone, code);
    if (!result.success) {
      // Clean up if SMS actually failed
      await this.redis.del(otpKey);
      await this.redis.del(rateKey);
      throw new BadRequestException(result.message || '短信发送失败，请稍后重试');
    }

    return { message: '验证码已发送', expiresIn: OTP_TTL };
  }

  /**
   * POST /api/v1/auth/sms/verify
   * Verify OTP only (does not log in). Returns 200 on success.
   */
  @Post('verify')
  @HttpCode(HttpStatus.OK)
  async verifyOtp(@Body() body: { phone: string; code: string }) {
    const phone = (body.phone || '').trim();
    const code = (body.code || '').trim();
    if (!phone || !code) throw new BadRequestException('手机号和验证码不能为空');

    const otpKey = `sms:otp:${phone}`;
    const stored = await this.redis.get(otpKey);

    if (!stored || stored !== code) {
      throw new BadRequestException('验证码错误或已过期');
    }

    return { verified: true };
  }
}
