import {
  Body,
  Controller,
  Post,
  HttpCode,
  HttpStatus,
  UseGuards,
  Get,
  Patch,
  Delete,
  Param,
  Request,
  Query,
  UnauthorizedException,
} from "@nestjs/common";
import {
  ApiTags,
  ApiOperation,
  ApiResponse,
  ApiBody,
  ApiBearerAuth,
} from "@nestjs/swagger";
import { IsPublic } from "@tria-plc/api-common/modules/auth/decorators/public.decorator";
import { PassengerAuthService } from "./passenger-auth.service";
import {
  RegisterDto,
  LoginDto,
  ResendRegistrationCodeDto,
  FaydaRequestPasswordSetupDto,
  FaydaVerifyAndLoginDto,
} from "./auth.dto";
import { JwtGuard } from "../../common/jwt.guard";

@ApiTags("Passenger Auth")
@Controller("auth")
// @Throttle({ auth: { limit: 5, ttl: 60_000 } })
export class AuthController {
  constructor(private passengerAuthService: PassengerAuthService) {}

  @Post("register")
  @IsPublic()
  @ApiOperation({
    summary: "Register new passenger account (sends SMS verification code)",
  })
  @ApiResponse({
    status: 201,
    description:
      "Account created as pending. A verification code is sent via SMS — complete signup via PATCH /v1/auth/set-password.",
  })
  @ApiResponse({
    status: 409,
    description: "Email or phone already registered",
  })
  @ApiBody({ type: RegisterDto })
  register(@Request() req: any, @Body() dto: RegisterDto) {
    return this.passengerAuthService.register(dto, req);
  }

  @Post("register/resend-code")
  @IsPublic()
  @HttpCode(HttpStatus.OK)
  @ApiOperation({
    summary: "Resend the registration verification code for a pending account",
  })
  @ApiResponse({
    status: 200,
    description: "Verification code re-sent if the account is pending.",
  })
  @ApiBody({ type: ResendRegistrationCodeDto })
  resendRegistrationCode(
    @Request() req: any,
    @Body() dto: ResendRegistrationCodeDto,
  ) {
    return this.passengerAuthService.resendRegistrationCode(dto, req);
  }

  @Post("login")
  @IsPublic()
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: "Login with email and password" })
  @ApiResponse({
    status: 200,
    description: "Login successful. Returns token + passengerId.",
  })
  @ApiResponse({ status: 401, description: "Invalid credentials" })
  @ApiBody({ type: LoginDto })
  login(@Request() req: any, @Body() dto: LoginDto) {
    return this.passengerAuthService.login(dto, req);
  }

  @Post("logout")
  @HttpCode(HttpStatus.OK)
  @UseGuards(JwtGuard)
  @ApiBearerAuth("JWT-auth")
  @ApiOperation({ summary: "Logout current user" })
  @ApiResponse({ status: 200, description: "Logout successful" })
  @ApiResponse({ status: 401, description: "Unauthorized" })
  logout(@Request() req: any) {
    if (!req.user?.id)
      throw new UnauthorizedException("User not authenticated");
    return this.passengerAuthService.logout(req.user, req);
  }

  @Get("me")
  @UseGuards(JwtGuard)
  @ApiBearerAuth("JWT-auth")
  @ApiOperation({
    summary:
      "[DEV] Inspect raw JWT payload — shows full req.user from JwtGuard",
  })
  @ApiResponse({
    status: 200,
    description: "Returns the full req.user object set by JwtGuard",
  })
  @ApiResponse({ status: 401, description: "Unauthorized" })
  getMe(@Request() req: any) {
    return { user: req.user };
  }

  @Get("profile")
  @UseGuards(JwtGuard)
  @ApiBearerAuth("JWT-auth")
  @ApiOperation({ summary: "Get current user profile" })
  @ApiResponse({
    status: 200,
    description: "User profile retrieved successfully",
  })
  @ApiResponse({ status: 401, description: "Unauthorized" })
  getProfile(@Request() req: any) {
    const userId = req.user?.id;
    if (!userId) throw new UnauthorizedException("User not authenticated");
    return this.passengerAuthService.getProfile(userId);
  }

  // TODO: admin user management endpoints — implement when admin module is ready

  @Get("users")
  @UseGuards(JwtGuard)
  @ApiBearerAuth("JWT-auth")
  @ApiOperation({ summary: "List all users (admin)" })
  listUsers(
    @Query("search") search?: string,
    @Query("role") role?: string,
    @Query("status") status?: string,
    @Query("page") page?: string,
    @Query("pageSize") pageSize?: string,
  ) {
    return this.passengerAuthService.listUsers({
      search,
      role,
      status,
      page: page ? +page : 1,
      pageSize: pageSize ? +pageSize : 20,
    });
  }

  @Post("users")
  @UseGuards(JwtGuard)
  @ApiBearerAuth("JWT-auth")
  @ApiOperation({ summary: "Create user (admin)" })
  createUser(@Body() body: any) {
    return this.passengerAuthService.createUser(body);
  }

  @Patch("users/:id")
  @UseGuards(JwtGuard)
  @ApiBearerAuth("JWT-auth")
  @ApiOperation({ summary: "Update user (admin)" })
  updateUser(@Param("id") id: string, @Body() body: any) {
    return this.passengerAuthService.updateUser(id, body);
  }

  @Delete("users/:id")
  @UseGuards(JwtGuard)
  @ApiBearerAuth("JWT-auth")
  @ApiOperation({ summary: "Delete user (admin)" })
  deleteUser(@Param("id") id: string) {
    return this.passengerAuthService.deleteUser(id);
  }

  @Post("users/:id/reset-password")
  @UseGuards(JwtGuard)
  @ApiBearerAuth("JWT-auth")
  @ApiOperation({ summary: "Reset user password (admin)" })
  resetPassword(
    @Param("id") id: string,
    @Body() body: { tempPassword: string },
  ) {
    return this.passengerAuthService.resetUserPassword(id, body.tempPassword);
  }

  @Post("fayda/request-password-setup")
  @IsPublic()
  @HttpCode(HttpStatus.OK)
  @ApiOperation({
    summary: "Send OTP to phone for Fayda-verified account password setup",
  })
  @ApiResponse({
    status: 200,
    description: "OTP sent to registered phone number",
  })
  @ApiBody({ type: FaydaRequestPasswordSetupDto })
  requestFaydaPasswordSetup(
    @Body() dto: FaydaRequestPasswordSetupDto,
    @Request() req: any,
  ) {
    return this.passengerAuthService.requestFaydaPasswordSetup(
      dto.phoneNumber,
      req,
    );
  }

  @Post("fayda/verify-and-login")
  @IsPublic()
  @HttpCode(HttpStatus.OK)
  @ApiOperation({
    summary: "Verify OTP and receive session token for Fayda-verified account",
  })
  @ApiResponse({
    status: 200,
    description:
      "Returns token + requiresPassword flag. Use token with POST /v1/auth/set-fayda-password.",
  })
  @ApiBody({ type: FaydaVerifyAndLoginDto })
  verifyFaydaAndLogin(@Body() dto: FaydaVerifyAndLoginDto) {
    return this.passengerAuthService.verifyFaydaAndLogin(
      dto.phoneNumber,
      dto.otp,
    );
  }
}
