import {
  Body,
  Controller,
  Get,
  HttpCode,
  HttpStatus,
  Param,
  Post,
  Req,
  UploadedFiles,
  UseGuards,
  UseInterceptors,
} from '@nestjs/common';
import { FileFieldsInterceptor } from '@nestjs/platform-express';
import { MEDIA_MAX_SIZE_BYTES } from '../../common/media/allowed-media';
import { ApiBearerAuth, ApiBody, ApiConsumes, ApiTags } from '@nestjs/swagger';
import { Request } from 'express';
import { Throttle } from '../../common/decorators/throttle.decorator';
import { CurrentUser } from '../../common/decorators/current-user.decorator';
import { SuperAdminPermissions } from '../../common/decorators/superadmin-permissions.decorator';
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
import { SuperAdminPermissionsGuard } from '../../common/guards/superadmin-permissions.guard';
import { SuperAdminJwtAuthGuard } from '../../common/guards/super-admin-jwt-auth.guard';
import { JwtPayload } from '../../common/interfaces/jwt-payload.interface';
import { AuthService } from './auth.service';
import { ChangePasswordDto } from './dto/change-password.dto';
import { ForgotPasswordDto } from './dto/forgot-password.dto';
import { GoogleTokenLoginDto } from './dto/google-token-login.dto';
import { LoginDto } from './dto/login.dto';
import { RegisterBasicDto } from './dto/register-basic.dto';
import { ResetPasswordDto } from './dto/reset-password.dto';
import { RefreshTokenDto } from './dto/refresh-token.dto';
import { GoogleAuthGuard } from './guards/google-auth.guard';
import { RegisterDto } from './dto/register.dto';
import { SendEmailVerificationDto } from './dto/send-email-verification.dto';
import { SignupCompleteDto } from './dto/signup-complete.dto';
import { SignupStartDto } from './dto/signup-start.dto';
import { SignupVerifyDto } from './dto/signup-verify.dto';
import { SuperAdminLoginDto } from './dto/super-admin-login.dto';
import { VerifyEmailDto } from './dto/verify-email.dto';
import { VerifyResetCodeDto } from './dto/verify-reset-code.dto';
import { SUPERADMIN_PERMISSIONS } from '../superadmin/superadmin-permissions';

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

  @Post('register')
  @Throttle(10, 60_000)
  async register(@Body() dto: RegisterDto) {
    return this.authService.register(dto);
  }

  @Post('register-basic')
  @Throttle(10, 60_000)
  async registerBasic(@Body() dto: RegisterBasicDto) {
    return this.authService.registerBasic(dto);
  }

  @Post('signup/start')
  @Throttle(10, 60_000)
  async signupStart(@Body() dto: SignupStartDto) {
    return this.authService.signupStart(dto);
  }

  @HttpCode(HttpStatus.OK)
  @Post('signup/verify')
  @Throttle(20, 60_000)
  async signupVerify(@Body() dto: SignupVerifyDto) {
    return this.authService.signupVerify(dto);
  }

  @HttpCode(HttpStatus.OK)
  @Post('signup/complete')
  @Throttle(10, 60_000)
  @UseInterceptors(
    FileFieldsInterceptor([{ name: 'avatarFile', maxCount: 1 }], {
      limits: { fileSize: MEDIA_MAX_SIZE_BYTES.userImage, files: 1 },
    }),
  )
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        signupToken: { type: 'string' },
        musicRoles: { type: 'array', items: { type: 'string' } },
        musicGenres: { type: 'array', items: { type: 'string' } },
        experienceLevel: { type: 'string' },
        favoriteInstruments: { type: 'array', items: { type: 'string' } },
        favoriteMaqamat: { type: 'array', items: { type: 'string' } },
        stageName: { type: 'string' },
        name: { type: 'string' },
        username: { type: 'string' },
        bio: { type: 'string' },
        location: { type: 'string' },
        latitude: { type: 'number' },
        longitude: { type: 'number' },
        isPrivate: { type: 'boolean' },
        avatarFile: { type: 'string', format: 'binary' },
      },
      required: ['signupToken', 'name'],
    },
  })
  async signupComplete(
    @Body() dto: SignupCompleteDto,
    @UploadedFiles()
    files?: {
      avatarFile?: Array<{
        mimetype?: string;
        size: number;
        buffer: Buffer;
        originalname?: string;
      }>;
    },
  ) {
    return this.authService.signupComplete(dto, files?.avatarFile?.[0]);
  }

  @HttpCode(HttpStatus.OK)
  @Post('login')
  @Throttle(20, 60_000)
  async login(@Body() dto: LoginDto) {
    return this.authService.login(dto);
  }

  @HttpCode(HttpStatus.OK)
  @Post('refresh')
  @Throttle(30, 60_000)
  async refresh(@Body() dto: RefreshTokenDto) {
    return this.authService.refresh(dto);
  }

  @HttpCode(HttpStatus.OK)
  @Post('logout')
  async logout(@Body() dto: RefreshTokenDto): Promise<{ message: string }> {
    await this.authService.logout(dto);
    return { message: 'Logged out successfully' };
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @HttpCode(HttpStatus.OK)
  @Post('change-password')
  async changePassword(@CurrentUser() user: JwtPayload, @Body() dto: ChangePasswordDto) {
    return this.authService.changePassword(user.sub, dto);
  }

  @HttpCode(HttpStatus.OK)
  @Post('forgot-password')
  @Throttle(8, 60_000)
  async forgotPassword(@Body() dto: ForgotPasswordDto) {
    return this.authService.forgotPassword(dto);
  }

  @HttpCode(HttpStatus.OK)
  @Post('verify-reset-code')
  @Throttle(20, 60_000)
  async verifyResetCode(@Body() dto: VerifyResetCodeDto) {
    return this.authService.verifyResetCode(dto);
  }

  @HttpCode(HttpStatus.OK)
  @Post('reset-password')
  @Throttle(10, 60_000)
  async resetPassword(@Body() dto: ResetPasswordDto) {
    return this.authService.resetPassword(dto);
  }

  @HttpCode(HttpStatus.OK)
  @Post('send-email-verification')
  @Throttle(8, 60_000)
  async sendEmailVerification(@Body() dto: SendEmailVerificationDto) {
    return this.authService.sendEmailVerification(dto);
  }

  @HttpCode(HttpStatus.OK)
  @Post('verify-email')
  @Throttle(20, 60_000)
  async verifyEmail(@Body() dto: VerifyEmailDto) {
    return this.authService.verifyEmail(dto);
  }

  @HttpCode(HttpStatus.OK)
  @Post('superadmin/login')
  @Throttle(10, 60_000)
  async superAdminLogin(@Body() dto: SuperAdminLoginDto) {
    return this.authService.superAdminLogin(dto);
  }

  @HttpCode(HttpStatus.OK)
  @Post('superadmin/refresh')
  @Throttle(20, 60_000)
  async superAdminRefresh(@Body() dto: RefreshTokenDto) {
    return this.authService.superAdminRefresh(dto);
  }

  @HttpCode(HttpStatus.OK)
  @Post('superadmin/logout')
  async superAdminLogout(@Body() dto: RefreshTokenDto): Promise<{ message: string }> {
    await this.authService.superAdminLogout(dto);
    return { message: 'Superadmin logged out successfully' };
  }

  @Get('google')
  @UseGuards(GoogleAuthGuard)
  async googleAuth(): Promise<void> {
    return;
  }

  @Get('google/callback')
  @UseGuards(GoogleAuthGuard)
  async googleCallback(
    @Req()
    req: Request & {
      user: { googleId: string; email: string; name: string; avatar?: string };
    },
  ) {
    return this.authService.loginWithGoogle(req.user);
  }

  @HttpCode(HttpStatus.OK)
  @Post('google/token')
  @Throttle(20, 60_000)
  async googleTokenLogin(@Body() dto: GoogleTokenLoginDto) {
    return this.authService.loginWithGoogleIdToken(dto);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Get('sessions')
  async listMySessions(@CurrentUser() user: JwtPayload) {
    return this.authService.listUserSessions(user.sub);
  }

  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @Post('sessions/:jti/revoke')
  async revokeSession(@CurrentUser() user: JwtPayload, @Param('jti') jti: string) {
    await this.authService.revokeUserSession(user.sub, jti);
    return { success: true };
  }

  @ApiBearerAuth()
  @UseGuards(SuperAdminJwtAuthGuard, SuperAdminPermissionsGuard)
  @SuperAdminPermissions(SUPERADMIN_PERMISSIONS.SESSIONS_MANAGE)
  @Get('superadmin/sessions')
  async listSuperAdminSessions(@CurrentUser() user: JwtPayload) {
    return this.authService.listSuperAdminSessions(user.email ?? '');
  }

  @ApiBearerAuth()
  @UseGuards(SuperAdminJwtAuthGuard, SuperAdminPermissionsGuard)
  @SuperAdminPermissions(SUPERADMIN_PERMISSIONS.SESSIONS_MANAGE)
  @Post('superadmin/sessions/:sessionId/revoke')
  async revokeSuperAdminSession(
    @CurrentUser() user: JwtPayload,
    @Param('sessionId') sessionId: string,
  ) {
    await this.authService.revokeSuperAdminSession(user.email ?? '', sessionId);
    return { success: true };
  }
}
