import { Body, Controller, Delete, Get, Param, Patch, Post, Query, Request, UseGuards } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
import { IsInt, IsOptional, IsPositive, IsString } from 'class-validator';
import { ExcessBaggageService } from './excess-baggage.service';
import {
  LogExcessBaggageDto,
  WaiveChargeDto,
  InitiateExcessPaymentDto,
} from './excess-baggage.dto';
import { JwtGuard as IamJwtGuard } from '@tria-plc/api-common/modules/auth/services/jwt.guard';
import { PassengerAdmin } from '../../common/passenger-guards';

class UpsertBaggageAllowanceDto {
  @IsString() seatClassId: string;
  @IsOptional() @IsInt() maxWeightKg?: number;
  @IsOptional() @IsInt() maxPiecesCount?: number;
  @IsInt() @IsPositive() excessFeePerKg: number;
}

// ── IAM-protected agent/supervisor routes ────────────────────────────────────
@ApiTags('Excess Luggage')
@Controller('agents/excess-baggage')
@UseGuards(IamJwtGuard)
@ApiBearerAuth('IAM-auth')
export class ExcessBaggageAgentController {
  constructor(private service: ExcessBaggageService) {}

  @Post()
  @ApiOperation({ summary: 'Log excess baggage charge and optionally collect cash' })
  logCharge(@Request() req: any, @Body() dto: LogExcessBaggageDto) {
    dto.agentId = req.user?.id ?? req.user?.sub ?? dto.agentId;
    return this.service.logCharge(dto);
  }

  @Get()
  @ApiOperation({ summary: 'List all excess baggage charges (admin/supervisor)' })
  getAll(
    @Query('status') status?: string,
    @Query('bookingRef') bookingRef?: string,
    @Query('dateFrom') dateFrom?: string,
    @Query('dateTo') dateTo?: string,
    @Query('page') page?: string,
    @Query('pageSize') pageSize?: string,
  ) {
    return this.service.getAll({
      status,
      bookingRef,
      dateFrom,
      dateTo,
      page: page ? parseInt(page) : undefined,
      pageSize: pageSize ? parseInt(pageSize) : undefined,
    });
  }

  @Get('allowances')
  @ApiOperation({ summary: 'List all baggage allowance rules' })
  getAllowances() {
    return this.service.getAllowances();
  }

  @Post('allowances')
  @ApiOperation({ summary: 'Create baggage allowance rule for a seat class' })
  createAllowance(@Body() dto: UpsertBaggageAllowanceDto) {
    return this.service.upsertAllowance(dto);
  }

  @Patch('allowances/:id')
  @ApiOperation({ summary: 'Update baggage allowance rule' })
  updateAllowance(@Param('id') id: string, @Body() dto: Partial<UpsertBaggageAllowanceDto>) {
    return this.service.updateAllowance(id, dto);
  }

  @Delete('allowances/:id')
  @PassengerAdmin()
  @ApiBearerAuth('IAM-auth')
  @ApiOperation({ summary: 'Delete baggage allowance rule' })
  deleteAllowance(@Param('id') id: string) {
    return this.service.deleteAllowance(id);
  }

  @Get(':id')
  @ApiOperation({ summary: 'Get a single charge by ID (agent polling)' })
  getCharge(@Param('id') id: string) {
    return this.service.getCharge(id);
  }

  @Post(':id/resend')
  @ApiOperation({ summary: 'Resend payment link (extends expiry by 30 min)' })
  resendLink(@Param('id') id: string) {
    return this.service.resendLink(id);
  }

  @Patch(':id/waive')
  @ApiOperation({ summary: 'Waive a charge (supervisor only)' })
  waiveCharge(@Param('id') id: string, @Body() dto: WaiveChargeDto) {
    return this.service.waiveCharge(id, dto);
  }

  @Delete(':id')
  @PassengerAdmin()
  @ApiBearerAuth('IAM-auth')
  @ApiOperation({ summary: 'Delete excess baggage charge (admin only)' })
  deleteCharge(@Param('id') id: string) {
    return this.service.deleteCharge(id);
  }
}

// ── Public pay-by-token routes (passenger self-service) ──────────────────────
@ApiTags('Excess Luggage')
@Controller('excess-baggage')
export class ExcessBaggagePublicController {
  constructor(private service: ExcessBaggageService) {}

  @Get('pay/:token')
  @ApiOperation({ summary: 'Retrieve charge details by payment token (public)' })
  getByToken(@Param('token') token: string) {
    return this.service.getByToken(token);
  }

  @Post('pay/:token/initiate')
  @ApiOperation({ summary: 'Passenger initiates payment for excess baggage charge' })
  initiatePayment(
    @Param('token') token: string,
    @Body() dto: InitiateExcessPaymentDto,
  ) {
    return this.service.initiatePayment(token, dto);
  }
}
