import { Body, Controller, Delete, Get, Param, Patch, Post, Query, UseGuards } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiBearerAuth, ApiParam, ApiQuery, ApiBody, ApiResponse } from '@nestjs/swagger';
import { FleetService } from './fleet.service';
import { CreateTrainDto, CreateCoachDto, UpdateCoachDto, AssignCoachDto, ListCoachesDto, CreateCoachTypeDto, UpdateCoachTypeDto, CreateClassDto, UpdateClassDto, GenerateSeatMapDto } from './fleet.dto';
import { JwtGuard } from '../../common/jwt.guard';
import { PassengerAdmin, PassengerStaff } from '../../common/passenger-guards';
import { PASSENGER_PERMS } from '../../seed/passenger-permissions.registry';

@ApiTags('Fleet')
@Controller('fleet')
@UseGuards(JwtGuard)
@ApiBearerAuth('JWT-auth')
export class FleetController {
  constructor(private service: FleetService) {}

  // Coach Type Endpoints
  @Get('coach-types')
  @ApiOperation({ summary: 'List all coach types' })
  @ApiResponse({ status: 200, description: 'Array of coach types' })
  getCoachTypes() {
    return this.service.getCoachTypes();
  }

  @Post('coach-types')
  @PassengerStaff([PASSENGER_PERMS.coaches.manage, PASSENGER_PERMS.admin])
  @ApiOperation({ summary: 'Create a coach type' })
  @ApiBody({ type: CreateCoachTypeDto })
  @ApiResponse({ status: 201, description: 'Coach type created' })
  createCoachType(@Body() dto: CreateCoachTypeDto) {
    return this.service.createCoachType(dto);
  }

  @Patch('coach-types/:id')
  @PassengerStaff([PASSENGER_PERMS.coaches.manage, PASSENGER_PERMS.admin])
  @ApiOperation({ summary: 'Update a coach type' })
  @ApiParam({ name: 'id', description: 'Coach Type UUID' })
  @ApiBody({ type: UpdateCoachTypeDto })
  @ApiResponse({ status: 200, description: 'Coach type updated' })
  @ApiResponse({ status: 404, description: 'Coach type not found' })
  updateCoachType(@Param('id') id: string, @Body() dto: UpdateCoachTypeDto) {
    return this.service.updateCoachType(id, dto);
  }

  @Delete('coach-types/:id')
  @PassengerAdmin()
  @ApiBearerAuth('IAM-auth')
  @ApiOperation({ summary: 'Delete a coach type' })
  @ApiParam({ name: 'id', description: 'Coach Type UUID' })
  @ApiResponse({ status: 200, description: 'Coach type deleted' })
  @ApiResponse({ status: 404, description: 'Coach type not found' })
  deleteCoachType(@Param('id') id: string) {
    return this.service.deleteCoachType(id);
  }

  // Class Endpoints
  @Get('classes')
  @ApiOperation({ summary: 'List all classes' })
  @ApiQuery({ name: 'coachTypeId', required: false, description: 'Filter by coach type' })
  @ApiResponse({ status: 200, description: 'Array of classes' })
  getClasses(@Query('coachTypeId') coachTypeId?: string) {
    return this.service.getClasses(coachTypeId);
  }

  @Post('classes')
  @PassengerStaff([PASSENGER_PERMS.classes.manage, PASSENGER_PERMS.admin])
  @ApiOperation({ summary: 'Create a class' })
  @ApiBody({ type: CreateClassDto })
  @ApiResponse({ status: 201, description: 'Class created' })
  createClass(@Body() dto: CreateClassDto) {
    return this.service.createClass(dto);
  }

  @Patch('classes/:id')
  @PassengerStaff([PASSENGER_PERMS.classes.manage, PASSENGER_PERMS.admin])
  @ApiOperation({ summary: 'Update a class' })
  @ApiParam({ name: 'id', description: 'Class UUID' })
  @ApiBody({ type: UpdateClassDto })
  @ApiResponse({ status: 200, description: 'Class updated' })
  @ApiResponse({ status: 404, description: 'Class not found' })
  updateClass(@Param('id') id: string, @Body() dto: UpdateClassDto) {
    return this.service.updateClass(id, dto);
  }

  @Delete('classes/:id')
  @PassengerAdmin()
  @ApiBearerAuth('IAM-auth')
  @ApiOperation({ summary: 'Delete a class' })
  @ApiParam({ name: 'id', description: 'Class UUID' })
  @ApiQuery({ name: 'cascade', required: false, type: Boolean, description: 'Force delete with all related data' })
  @ApiResponse({ status: 200, description: 'Class deleted' })
  @ApiResponse({ status: 404, description: 'Class not found' })
  deleteClass(@Param('id') id: string, @Query('cascade') cascade?: string) {
    return this.service.deleteClass(id, cascade === 'true');
  }

  // Seat Class Endpoints (DEPRECATED - use Classes endpoints instead)
  @Get('seat-classes')
  @ApiOperation({ summary: 'List all classes (DEPRECATED - use /fleet/classes)' })
  @ApiQuery({ name: 'coachTypeId', required: false, description: 'Filter by coach type' })
  @ApiResponse({ status: 200, description: 'Array of classes' })
  getSeatClasses(@Query('coachTypeId') coachTypeId?: string) {
    return this.service.getClasses(coachTypeId);
  }

  @Post('seat-classes')
  @PassengerStaff([PASSENGER_PERMS.classes.manage, PASSENGER_PERMS.admin])
  @ApiOperation({ summary: 'Create a class (DEPRECATED - use /fleet/classes)' })
  @ApiBody({ type: CreateClassDto })
  @ApiResponse({ status: 201, description: 'Class created' })
  createSeatClass(@Body() dto: CreateClassDto) {
    return this.service.createClass(dto);
  }

  @Patch('seat-classes/:id')
  @PassengerStaff([PASSENGER_PERMS.classes.manage, PASSENGER_PERMS.admin])
  @ApiOperation({ summary: 'Update a class (DEPRECATED - use /fleet/classes)' })
  @ApiParam({ name: 'id', description: 'Class UUID' })
  @ApiBody({ type: UpdateClassDto })
  @ApiResponse({ status: 200, description: 'Class updated' })
  @ApiResponse({ status: 404, description: 'Class not found' })
  updateSeatClass(@Param('id') id: string, @Body() dto: UpdateClassDto) {
    return this.service.updateClass(id, dto);
  }

  @Delete('seat-classes/:id')
  @PassengerAdmin()
  @ApiBearerAuth('IAM-auth')
  @ApiOperation({ summary: 'Delete a class (DEPRECATED - use /fleet/classes)' })
  @ApiParam({ name: 'id', description: 'Class UUID' })
  @ApiQuery({ name: 'cascade', required: false, type: Boolean, description: 'Force delete with all related data' })
  @ApiResponse({ status: 200, description: 'Class deleted' })
  @ApiResponse({ status: 404, description: 'Class not found' })
  deleteSeatClass(@Param('id') id: string, @Query('cascade') cascade?: string) {
    return this.service.deleteClass(id, cascade === 'true');
  }

  // Train Endpoints
  @Get('trains')
  @ApiOperation({ summary: 'List all trains with their recent schedules' })
  @ApiResponse({ status: 200, description: 'Array of trains' })
  getTrains() {
    return this.service.getTrains();
  }

  @Post('trains')
  @PassengerStaff([PASSENGER_PERMS.trains.manage, PASSENGER_PERMS.admin])
  @ApiOperation({ summary: 'Create a train service' })
  @ApiBody({ type: CreateTrainDto })
  @ApiResponse({ status: 201, description: 'Train created' })
  createTrain(@Body() dto: CreateTrainDto) {
    return this.service.createTrain(dto);
  }

  @Patch('trains/:id')
  @PassengerStaff([PASSENGER_PERMS.trains.manage, PASSENGER_PERMS.admin])
  @ApiOperation({ summary: 'Update a train service' })
  @ApiParam({ name: 'id', description: 'Train UUID' })
  @ApiBody({ type: CreateTrainDto })
  @ApiResponse({ status: 200, description: 'Train updated' })
  @ApiResponse({ status: 404, description: 'Train not found' })
  updateTrain(@Param('id') id: string, @Body() dto: CreateTrainDto) {
    return this.service.updateTrain(id, dto);
  }

  @Delete('trains/:id')
  @PassengerAdmin()
  @ApiBearerAuth('IAM-auth')
  @ApiOperation({ summary: 'Delete a train service' })
  @ApiParam({ name: 'id', description: 'Train UUID' })
  @ApiQuery({ name: 'cascade', required: false, type: Boolean, description: 'Force delete with all related data' })
  @ApiResponse({ status: 200, description: 'Train deleted' })
  @ApiResponse({ status: 404, description: 'Train not found' })
  deleteTrain(@Param('id') id: string, @Query('cascade') cascade?: string) {
    return this.service.deleteTrain(id, cascade === 'true');
  }

  @Patch('trains/:id/restore')
  @PassengerStaff([PASSENGER_PERMS.trains.manage, PASSENGER_PERMS.admin])
  @ApiOperation({ summary: 'Restore (reactivate) a deactivated train' })
  @ApiParam({ name: 'id', description: 'Train UUID' })
  @ApiResponse({ status: 200, description: 'Train restored' })
  @ApiResponse({ status: 404, description: 'Train not found' })
  restoreTrain(@Param('id') id: string) {
    return this.service.restoreTrain(id);
  }

  // Coach Endpoints
  @Get('coaches')
  @ApiOperation({ summary: 'List coaches with seat status summary' })
  @ApiQuery({ name: 'status', required: false, description: 'Filter by status: ACTIVE, INACTIVE' })
  @ApiQuery({ name: 'scheduleId', required: false, description: 'Filter coaches assigned to schedule' })
  @ApiResponse({ 
    status: 200, 
    description: 'Array of coaches',
    schema: {
      example: [
        {
          id: '550e8400-e29b-41d4-a716-446655440000',
          number: 'HSC-0001',
          sequence: 1,
          coachTypeId: 'coach-type-uuid',
          coachType: {
            id: 'coach-type-uuid',
            code: 'HSC',
            name: 'Hard Seat Coach'
          },
          arrangement: '2+2',
          capacity: 60,
          status: 'ACTIVE',
          totalSeats: 60,
          availableSeats: 45,
          occupiedSeats: 15,
          blockedSeats: 0,
          createdAt: '2024-01-15T10:30:00.000Z',
          updatedAt: '2024-01-15T10:30:00.000Z'
        }
      ]
    }
  })
  listCoaches(
    @Query('status') status?: string,
    @Query('scheduleId') scheduleId?: string,
  ) {
    const dto: ListCoachesDto = {
      status,
      scheduleId,
    };
    return this.service.listCoaches(dto);
  }

  @Get('coaches/utilization')
  @ApiOperation({ summary: 'Coach utilization report — seats, bookings, and assignment history per coach' })
  @ApiResponse({ status: 200, description: 'Coach utilization data' })
  getCoachUtilization() {
    return this.service.getCoachUtilization();
  }

  @Get('coaches/:id')
  @ApiOperation({ summary: 'Get single coach with seat layout' })
  @ApiParam({ name: 'id', description: 'Coach UUID' })
  @ApiResponse({ 
    status: 200, 
    description: 'Coach detail with seats by row',
    schema: {
      example: {
        id: '550e8400-e29b-41d4-a716-446655440000',
        number: 'HSC-0001',
        sequence: 1,
        coachTypeId: 'coach-type-uuid',
        coachType: {
          id: 'coach-type-uuid',
          code: 'HSC',
          name: 'Hard Seat Coach'
        },
        arrangement: '2+2',
        capacity: 60,
        status: 'ACTIVE',
        seats: [
          {
            id: 'seat-uuid-1',
            seatNumber: '1A',
            status: 'AVAILABLE',
            class: {
              id: 'class-uuid',
              name: 'Economy',
              baseFareMinor: 5000
            }
          }
        ],
        createdAt: '2024-01-15T10:30:00.000Z',
        updatedAt: '2024-01-15T10:30:00.000Z'
      }
    }
  })
  @ApiResponse({ status: 404, description: 'Coach not found' })
  getCoach(@Param('id') id: string) {
    return this.service.getCoach(id);
  }

  @Post('coaches')
  @PassengerStaff([PASSENGER_PERMS.coaches.manage, PASSENGER_PERMS.admin])
  @ApiOperation({ summary: 'Create a coach with auto-generated seat numbers' })
  @ApiBody({ type: CreateCoachDto })
  @ApiResponse({ 
    status: 201, 
    description: 'Coach created',
    schema: {
      example: {
        id: '550e8400-e29b-41d4-a716-446655440000',
        number: 'HSC-0001',
        sequence: 1,
        coachTypeId: 'coach-type-uuid',
        arrangement: '2+2',
        capacity: 60,
        status: 'ACTIVE',
        createdAt: '2024-01-15T10:30:00.000Z',
        updatedAt: '2024-01-15T10:30:00.000Z'
      }
    }
  })
  @ApiResponse({ status: 400, description: 'Invalid arrangement format' })
  createCoach(@Body() dto: CreateCoachDto) {
    return this.service.createCoach(dto);
  }

  @Patch('coaches/:id')
  @PassengerStaff([PASSENGER_PERMS.coaches.manage, PASSENGER_PERMS.admin])
  @ApiOperation({ summary: 'Update coach properties' })
  @ApiParam({ name: 'id', description: 'Coach UUID' })
  @ApiBody({ type: UpdateCoachDto })
  @ApiResponse({ 
    status: 200, 
    description: 'Coach updated',
    schema: {
      example: {
        id: '550e8400-e29b-41d4-a716-446655440000',
        number: 'HSC-0001',
        sequence: 1,
        coachTypeId: 'coach-type-uuid',
        arrangement: '2+2',
        capacity: 60,
        status: 'ACTIVE',
        createdAt: '2024-01-15T10:30:00.000Z',
        updatedAt: '2024-01-15T10:30:00.000Z'
      }
    }
  })
  @ApiResponse({ status: 404, description: 'Coach not found' })
  updateCoach(@Param('id') id: string, @Body() dto: UpdateCoachDto) {
    return this.service.updateCoach(id, dto);
  }

  @Delete('coaches/:id')
  @PassengerAdmin()
  @ApiBearerAuth('IAM-auth')
  @ApiOperation({ summary: 'Delete a coach' })
  @ApiParam({ name: 'id', description: 'Coach UUID' })
  @ApiQuery({ name: 'cascade', required: false, type: Boolean, description: 'Force delete with all related data' })
  @ApiResponse({ status: 200, description: 'Coach deleted successfully' })
  @ApiResponse({ status: 404, description: 'Coach not found' })
  deleteCoach(@Param('id') id: string, @Query('cascade') cascade?: string) {
    return this.service.deleteCoach(id, cascade === 'true');
  }

  @Post('assignments')
  @PassengerStaff([PASSENGER_PERMS.coaches.manage, PASSENGER_PERMS.admin])
  @ApiOperation({ summary: 'Assign a coach to a schedule' })
  @ApiBody({ type: AssignCoachDto })
  @ApiResponse({ status: 201, description: 'Coach assigned' })
  @ApiResponse({ status: 404, description: 'Schedule or coach not found' })
  assignCoach(@Body() dto: AssignCoachDto) {
    return this.service.assignCoach(dto);
  }

  @Delete('assignments/:id')
  @PassengerAdmin()
  @ApiBearerAuth('IAM-auth')
  @ApiOperation({ summary: 'Remove a coach assignment' })
  @ApiParam({ name: 'id', description: 'Assignment UUID' })
  @ApiResponse({ status: 200, description: 'Assignment removed' })
  @ApiResponse({ status: 404, description: 'Assignment not found' })
  removeAssignment(@Param('id') id: string) {
    return this.service.removeAssignment(id);
  }

  @Post('seatmap/generate')
  @ApiOperation({
    summary: 'Preview bed seat map — ECONOMY_BED or VIP_BED',
    description: `Generates a structured seat map for bed coaches without persisting anything.

**ECONOMY_BED**: 6 beds per room — Left(Lower/Middle/Upper) + Right(Lower/Middle/Upper)

**VIP_BED**: 4 beds per room — Left(Lower/Upper) + Right(Lower/Upper)

Use this to preview the full flat seat list before creating coaches.`,
  })
  @ApiBody({ type: GenerateSeatMapDto })
  @ApiResponse({
    status: 201,
    description: 'Generated seat map preview',
    schema: {
      example: {
        coachCount: 1, roomsPerCoach: 2, roomType: 'ECONOMY_BED', bedsPerRoom: 6, totalBeds: 12,
        seats: [
          { seat_id: 'C1-C1-R1-S1', coach_id: 'C1', room_id: 'C1-R1', category: 'ECONOMY_BED', position: 'LEFT',  bed_type: 'LOWER',  sequence_number: 1, status: 'AVAILABLE' },
          { seat_id: 'C1-C1-R1-S2', coach_id: 'C1', room_id: 'C1-R1', category: 'ECONOMY_BED', position: 'LEFT',  bed_type: 'MIDDLE', sequence_number: 2, status: 'AVAILABLE' },
          { seat_id: 'C1-C1-R1-S3', coach_id: 'C1', room_id: 'C1-R1', category: 'ECONOMY_BED', position: 'LEFT',  bed_type: 'UPPER',  sequence_number: 3, status: 'AVAILABLE' },
          { seat_id: 'C1-C1-R1-S4', coach_id: 'C1', room_id: 'C1-R1', category: 'ECONOMY_BED', position: 'RIGHT', bed_type: 'LOWER',  sequence_number: 4, status: 'AVAILABLE' },
          { seat_id: 'C1-C1-R1-S5', coach_id: 'C1', room_id: 'C1-R1', category: 'ECONOMY_BED', position: 'RIGHT', bed_type: 'MIDDLE', sequence_number: 5, status: 'AVAILABLE' },
          { seat_id: 'C1-C1-R1-S6', coach_id: 'C1', room_id: 'C1-R1', category: 'ECONOMY_BED', position: 'RIGHT', bed_type: 'UPPER',  sequence_number: 6, status: 'AVAILABLE' },
        ],
      },
    },
  })
  generateSeatMap(@Body() dto: GenerateSeatMapDto) {
    return this.service.generateSeatMapPreview(dto);
  }

  @Get('analytics')
  @ApiOperation({ summary: 'Fleet analytics and occupancy metrics' })
  @ApiResponse({ status: 200, description: 'Occupancy statistics' })
  getAnalytics() {
    return this.service.getAnalytics();
  }
}
