import { Controller, Get, Post, Body, HttpCode, HttpStatus, Param, Query } from '@nestjs/common';
import { ApiTags, ApiResponse, ApiOperation, ApiParam, ApiQuery } from '@nestjs/swagger';
import { RaceService } from './RaceService';
import { AllRacesPageDTO } from './dtos/AllRacesPageDTO';
import { RaceStatsDTO } from './dtos/RaceStatsDTO';
import { RaceDetailDTO } from './dtos/RaceDetailDTO';
import { RacesPageDataDTO } from './dtos/RacesPageDataDTO';
import { RaceResultsDetailDTO } from './dtos/RaceResultsDetailDTO';
import { RaceWithSOFDTO } from './dtos/RaceWithSOFDTO';
import { RaceProtestsDTO } from './dtos/RaceProtestsDTO';
import { RacePenaltiesDTO } from './dtos/RacePenaltiesDTO';
import { GetRaceDetailParamsDTO } from './dtos/GetRaceDetailParamsDTO';
import { RegisterForRaceParamsDTO } from './dtos/RegisterForRaceParamsDTO';
import { WithdrawFromRaceParamsDTO } from './dtos/WithdrawFromRaceParamsDTO';
import { RaceActionParamsDTO } from './dtos/RaceActionParamsDTO';
import { ImportRaceResultsDTO } from './dtos/ImportRaceResultsDTO';
import { ImportRaceResultsSummaryDTO } from './dtos/ImportRaceResultsSummaryDTO';
import { DashboardOverviewDTO } from './dtos/DashboardOverviewDTO';
import { FileProtestCommandDTO } from './dtos/FileProtestCommandDTO';
import { QuickPenaltyCommandDTO } from './dtos/QuickPenaltyCommandDTO';
import { ApplyPenaltyCommandDTO } from './dtos/ApplyPenaltyCommandDTO';
import { RequestProtestDefenseCommandDTO } from './dtos/RequestProtestDefenseCommandDTO';

@ApiTags('races')
@Controller('races')
export class RaceController {
  constructor(private readonly raceService: RaceService) {}

  @Get('all')
  @ApiOperation({ summary: 'Get all races' })
  @ApiResponse({ status: 200, description: 'List of all races', type: AllRacesPageDTO })
  async getAllRaces(): Promise<AllRacesPageDTO> {
    return this.raceService.getAllRaces();
  }

  @Get('total-races')
  @ApiOperation({ summary: 'Get the total number of races' })
  @ApiResponse({ status: 200, description: 'Total number of races', type: RaceStatsDTO })
  async getTotalRaces(): Promise<RaceStatsDTO> {
    return this.raceService.getTotalRaces();
  }

  @Get('page-data')
  @ApiOperation({ summary: 'Get races page data' })
  @ApiResponse({ status: 200, description: 'Races page data', type: RacesPageDataDTO })
  async getRacesPageData(): Promise<RacesPageDataDTO> {
    return this.raceService.getRacesPageData();
  }

  @Get('all/page-data')
  @ApiOperation({ summary: 'Get all races page data' })
  @ApiResponse({ status: 200, description: 'All races page data', type: RacesPageDataDTO })
  async getAllRacesPageData(): Promise<RacesPageDataDTO> {
    return this.raceService.getAllRacesPageData();
  }

  @Get(':raceId')
  @ApiOperation({ summary: 'Get race detail' })
  @ApiParam({ name: 'raceId', description: 'Race ID' })
  @ApiQuery({ name: 'driverId', description: 'Driver ID' })
  @ApiResponse({ status: 200, description: 'Race detail', type: RaceDetailDTO })
  async getRaceDetail(
    @Param('raceId') raceId: string,
    @Query('driverId') driverId: string,
  ): Promise<RaceDetailDTO> {
    return this.raceService.getRaceDetail({ raceId, driverId });
  }

  @Get(':raceId/results')
  @ApiOperation({ summary: 'Get race results detail' })
  @ApiParam({ name: 'raceId', description: 'Race ID' })
  @ApiResponse({ status: 200, description: 'Race results detail', type: RaceResultsDetailDTO })
  async getRaceResultsDetail(@Param('raceId') raceId: string): Promise<RaceResultsDetailDTO> {
    return this.raceService.getRaceResultsDetail(raceId);
  }

  @Get(':raceId/sof')
  @ApiOperation({ summary: 'Get race with strength of field' })
  @ApiParam({ name: 'raceId', description: 'Race ID' })
  @ApiResponse({ status: 200, description: 'Race with SOF', type: RaceWithSOFDTO })
  async getRaceWithSOF(@Param('raceId') raceId: string): Promise<RaceWithSOFDTO> {
    return this.raceService.getRaceWithSOF(raceId);
  }

  @Get(':raceId/protests')
  @ApiOperation({ summary: 'Get race protests' })
  @ApiParam({ name: 'raceId', description: 'Race ID' })
  @ApiResponse({ status: 200, description: 'Race protests', type: RaceProtestsDTO })
  async getRaceProtests(@Param('raceId') raceId: string): Promise<RaceProtestsDTO> {
    return this.raceService.getRaceProtests(raceId);
  }

  @Get(':raceId/penalties')
  @ApiOperation({ summary: 'Get race penalties' })
  @ApiParam({ name: 'raceId', description: 'Race ID' })
  @ApiResponse({ status: 200, description: 'Race penalties', type: RacePenaltiesDTO })
  async getRacePenalties(@Param('raceId') raceId: string): Promise<RacePenaltiesDTO> {
    return this.raceService.getRacePenalties(raceId);
  }

  @Post(':raceId/register')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Register for race' })
  @ApiParam({ name: 'raceId', description: 'Race ID' })
  @ApiResponse({ status: 200, description: 'Successfully registered for race' })
  async registerForRace(
    @Param('raceId') raceId: string,
    @Body() body: Omit<RegisterForRaceParamsDTO, 'raceId'>,
  ): Promise<void> {
    return this.raceService.registerForRace({ raceId, ...body });
  }

  @Post(':raceId/withdraw')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Withdraw from race' })
  @ApiParam({ name: 'raceId', description: 'Race ID' })
  @ApiResponse({ status: 200, description: 'Successfully withdrew from race' })
  async withdrawFromRace(
    @Param('raceId') raceId: string,
    @Body() body: Omit<WithdrawFromRaceParamsDTO, 'raceId'>,
  ): Promise<void> {
    return this.raceService.withdrawFromRace({ raceId, ...body });
  }

  @Post(':raceId/cancel')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Cancel race' })
  @ApiParam({ name: 'raceId', description: 'Race ID' })
  @ApiResponse({ status: 200, description: 'Successfully cancelled race' })
  async cancelRace(@Param('raceId') raceId: string): Promise<void> {
    return this.raceService.cancelRace({ raceId });
  }

  @Post(':raceId/complete')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Complete race' })
  @ApiParam({ name: 'raceId', description: 'Race ID' })
  @ApiResponse({ status: 200, description: 'Successfully completed race' })
  async completeRace(@Param('raceId') raceId: string): Promise<void> {
    return this.raceService.completeRace({ raceId });
  }

  @Post(':raceId/import-results')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Import race results' })
  @ApiParam({ name: 'raceId', description: 'Race ID' })
  @ApiResponse({ status: 200, description: 'Successfully imported race results', type: ImportRaceResultsSummaryDTO })
  async importRaceResults(
    @Param('raceId') raceId: string,
    @Body() body: Omit<ImportRaceResultsDTO, 'raceId'>,
  ): Promise<ImportRaceResultsSummaryDTO> {
    return this.raceService.importRaceResults({ raceId, ...body });
  }

  @Get('dashboard/overview')
  @ApiOperation({ summary: 'Get dashboard overview' })
  @ApiQuery({ name: 'driverId', description: 'Driver ID' })
  @ApiResponse({ status: 200, description: 'Dashboard overview', type: DashboardOverviewDTO })
  async getDashboardOverview(@Query('driverId') driverId: string): Promise<DashboardOverviewDTO> {
    return this.raceService.getDashboardOverview(driverId);
  }

  @Post('protests/file')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'File a protest' })
  @ApiResponse({ status: 200, description: 'Protest filed successfully' })
  async fileProtest(@Body() body: FileProtestCommandDTO): Promise<any> {
    return this.raceService.fileProtest(body);
  }

  @Post('penalties/quick')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Apply a quick penalty' })
  @ApiResponse({ status: 200, description: 'Penalty applied successfully' })
  async applyQuickPenalty(@Body() body: QuickPenaltyCommandDTO): Promise<any> {
    return this.raceService.applyQuickPenalty(body);
  }

  @Post('penalties/apply')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Apply a penalty' })
  @ApiResponse({ status: 200, description: 'Penalty applied successfully' })
  async applyPenalty(@Body() body: ApplyPenaltyCommandDTO): Promise<any> {
    return this.raceService.applyPenalty(body);
  }

  @Post('protests/defense/request')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Request protest defense' })
  @ApiResponse({ status: 200, description: 'Defense requested successfully' })
  async requestProtestDefense(@Body() body: RequestProtestDefenseCommandDTO): Promise<any> {
    return this.raceService.requestProtestDefense(body);
  }
}
