import { Body, Controller, Get, Inject, NotFoundException, Param, Post, Put, Req } from '@nestjs/common';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';

import { Public } from '../auth/Public';
import { DriverService } from './DriverService';
import { CompleteOnboardingInputDTO } from './dtos/CompleteOnboardingInputDTO';
import { CompleteOnboardingOutputDTO } from './dtos/CompleteOnboardingOutputDTO';
import { DriverRegistrationStatusDTO } from './dtos/DriverRegistrationStatusDTO';
import { DriversLeaderboardDTO } from './dtos/DriversLeaderboardDTO';
import { DriverStatsDTO } from './dtos/DriverStatsDTO';
import { GetDriverLiveriesOutputDTO } from './dtos/GetDriverLiveriesOutputDTO';
import { GetDriverOutputDTO } from './dtos/GetDriverOutputDTO';
import { GetDriverProfileOutputDTO } from './dtos/GetDriverProfileOutputDTO';

type AuthenticatedRequest = {
  user?: { userId: string; primaryDriverId?: string };
};


@ApiTags('drivers')
@Controller('drivers')
export class DriverController {
  constructor(@Inject(DriverService) private readonly driverService: DriverService) {}

  @Public()
  @Get('leaderboard')
  @ApiOperation({ summary: 'Get drivers leaderboard' })
  @ApiResponse({ status: 200, description: 'List of drivers for the leaderboard', type: DriversLeaderboardDTO })
  async getDriversLeaderboard(): Promise<DriversLeaderboardDTO> {
    return await this.driverService.getDriversLeaderboard();
  }

  @Public()
  @Get('total-drivers')
  @ApiOperation({ summary: 'Get the total number of drivers' })
  @ApiResponse({ status: 200, description: 'Total number of drivers', type: DriverStatsDTO })
  async getTotalDrivers(): Promise<DriverStatsDTO> {
    return await this.driverService.getTotalDrivers();
  }

  @Get('current')
  @ApiOperation({ summary: 'Get current authenticated driver' })
  @ApiResponse({ status: 200, description: 'Current driver data', type: GetDriverOutputDTO })
  @ApiResponse({ status: 404, description: 'Driver not found' })
  async getCurrentDriver(@Req() req: AuthenticatedRequest): Promise<GetDriverOutputDTO | null> {
    const driverId = req.user?.primaryDriverId;
    if (!driverId) {
      return null;
    }

    return await this.driverService.getDriver(driverId);
  }

  @Post('complete-onboarding')
  @ApiOperation({ summary: 'Complete driver onboarding for a user' })
  @ApiResponse({ status: 200, description: 'Onboarding complete', type: CompleteOnboardingOutputDTO })
  async completeOnboarding(
    @Body() input: CompleteOnboardingInputDTO,
    @Req() req: AuthenticatedRequest,
  ): Promise<CompleteOnboardingOutputDTO> {
    const userId = req.user?.userId;
    if (!userId) {
      throw new Error('Unauthorized');
    }
    return await this.driverService.completeOnboarding(userId, input);
  }

  @Public()
  @Get(':driverId/races/:raceId/registration-status')
  @ApiOperation({ summary: 'Get driver registration status for a specific race' })
  @ApiResponse({ status: 200, description: 'Driver registration status', type: DriverRegistrationStatusDTO })
  async getDriverRegistrationStatus(
    @Param('driverId') driverId: string,
    @Param('raceId') raceId: string,
  ): Promise<DriverRegistrationStatusDTO> {
    return await this.driverService.getDriverRegistrationStatus({ driverId, raceId });
  }

  @Public()
  @Get(':driverId')
  @ApiOperation({ summary: 'Get driver by ID' })
  @ApiResponse({ status: 200, description: 'Driver data', type: GetDriverOutputDTO })
  @ApiResponse({ status: 404, description: 'Driver not found' })
  async getDriver(@Param('driverId') driverId: string): Promise<GetDriverOutputDTO> {
    const result = await this.driverService.getDriver(driverId);
    if (!result) {
      throw new NotFoundException('Driver not found');
    }
    return result;
  }

  @Public()
  @Get(':driverId/profile')
  @ApiOperation({ summary: 'Get driver profile with full details' })
  @ApiResponse({ status: 200, description: 'Driver profile data', type: GetDriverProfileOutputDTO })
  @ApiResponse({ status: 404, description: 'Driver not found' })
  async getDriverProfile(@Param('driverId') driverId: string): Promise<GetDriverProfileOutputDTO> {
    try {
      return await this.driverService.getDriverProfile(driverId);
    } catch (error) {
      throw new NotFoundException('Driver not found');
    }
  }

  @Put(':driverId/profile')
  @ApiOperation({ summary: 'Update driver profile' })
  @ApiResponse({ status: 200, description: 'Driver profile updated', type: GetDriverOutputDTO })
  async updateDriverProfile(
    @Param('driverId') driverId: string,
    @Body() body: { bio?: string; country?: string },
  ): Promise<GetDriverOutputDTO | null> {
    return await this.driverService.updateDriverProfile(driverId, body.bio, body.country);
  }

  @Public()
  @Get(':driverId/liveries')
  @ApiOperation({ summary: 'Get driver liveries' })
  @ApiResponse({ status: 200, description: 'List of driver liveries', type: GetDriverLiveriesOutputDTO })
  async getDriverLiveries(@Param('driverId') driverId: string): Promise<GetDriverLiveriesOutputDTO> {
    return await this.driverService.getDriverLiveries(driverId);
  }

  // Add other Driver endpoints here based on other presenters
}
