import { Controller, Get, Post, Param, Query, Body } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiQuery, ApiBody } from '@nestjs/swagger';
import { Public } from '../decorators/public.decorator';
import { CsvBookingService } from '../services/csv-booking.service';
import {
  CarrierDocumentsResponseDto,
  VerifyDocumentAccessDto,
  DocumentAccessRequirementsDto,
} from '../dto/carrier-documents.dto';

/**
 * CSV Booking Actions Controller (Public Routes)
 *
 * Handles public accept/reject actions from carrier emails
 * Separated from main controller to avoid routing conflicts
 */
@ApiTags('CSV Booking Actions')
@Controller('csv-booking-actions')
export class CsvBookingActionsController {
  constructor(private readonly csvBookingService: CsvBookingService) {}

  /**
   * Accept a booking request (PUBLIC - token-based)
   *
   * GET /api/v1/csv-booking-actions/accept/:token
   */
  @Public()
  @Get('accept/:token')
  @ApiOperation({
    summary: 'Accept booking request (public)',
    description:
      'Public endpoint for carriers to accept a booking via email link. Updates booking status and notifies the user.',
  })
  @ApiParam({ name: 'token', description: 'Booking confirmation token (UUID)' })
  @ApiResponse({
    status: 200,
    description: 'Booking accepted successfully.',
  })
  @ApiResponse({ status: 404, description: 'Booking not found or invalid token' })
  @ApiResponse({
    status: 400,
    description: 'Booking cannot be accepted (invalid status or expired)',
  })
  async acceptBooking(@Param('token') token: string) {
    // Accept the booking
    const booking = await this.csvBookingService.acceptBooking(token);

    // Return simple success response
    return {
      success: true,
      bookingId: booking.id,
      action: 'accepted',
    };
  }

  /**
   * Reject a booking request (PUBLIC - token-based)
   *
   * GET /api/v1/csv-booking-actions/reject/:token
   */
  @Public()
  @Get('reject/:token')
  @ApiOperation({
    summary: 'Reject booking request (public)',
    description:
      'Public endpoint for carriers to reject a booking via email link. Updates booking status and notifies the user.',
  })
  @ApiParam({ name: 'token', description: 'Booking confirmation token (UUID)' })
  @ApiQuery({
    name: 'reason',
    required: false,
    description: 'Rejection reason',
    example: 'No capacity available',
  })
  @ApiResponse({
    status: 200,
    description: 'Booking rejected successfully.',
  })
  @ApiResponse({ status: 404, description: 'Booking not found or invalid token' })
  @ApiResponse({
    status: 400,
    description: 'Booking cannot be rejected (invalid status or expired)',
  })
  async rejectBooking(@Param('token') token: string, @Query('reason') reason: string) {
    // Reject the booking
    const booking = await this.csvBookingService.rejectBooking(token, reason);

    // Return simple success response
    return {
      success: true,
      bookingId: booking.id,
      action: 'rejected',
      reason: reason || null,
    };
  }

  /**
   * Check document access requirements (PUBLIC - token-based)
   *
   * GET /api/v1/csv-booking-actions/documents/:token/requirements
   */
  @Public()
  @Get('documents/:token/requirements')
  @ApiOperation({
    summary: 'Check document access requirements (public)',
    description:
      'Check if a password is required to access booking documents. Use this before showing the password form.',
  })
  @ApiParam({ name: 'token', description: 'Booking confirmation token (UUID)' })
  @ApiResponse({
    status: 200,
    description: 'Access requirements retrieved successfully.',
    type: DocumentAccessRequirementsDto,
  })
  @ApiResponse({ status: 404, description: 'Booking not found or invalid token' })
  async getDocumentAccessRequirements(
    @Param('token') token: string
  ): Promise<DocumentAccessRequirementsDto> {
    return this.csvBookingService.checkDocumentAccessRequirements(token);
  }

  /**
   * Get booking documents for carrier with password verification (PUBLIC - token-based)
   *
   * POST /api/v1/csv-booking-actions/documents/:token
   */
  @Public()
  @Post('documents/:token')
  @ApiOperation({
    summary: 'Get booking documents with password (public)',
    description:
      'Public endpoint for carriers to access booking documents after acceptance. Requires password verification. Returns booking summary and documents with signed download URLs.',
  })
  @ApiParam({ name: 'token', description: 'Booking confirmation token (UUID)' })
  @ApiBody({ type: VerifyDocumentAccessDto })
  @ApiResponse({
    status: 200,
    description: 'Booking documents retrieved successfully.',
    type: CarrierDocumentsResponseDto,
  })
  @ApiResponse({ status: 404, description: 'Booking not found or invalid token' })
  @ApiResponse({ status: 400, description: 'Booking has not been accepted yet' })
  @ApiResponse({ status: 401, description: 'Invalid password' })
  async getBookingDocumentsWithPassword(
    @Param('token') token: string,
    @Body() dto: VerifyDocumentAccessDto
  ): Promise<CarrierDocumentsResponseDto> {
    return this.csvBookingService.getDocumentsForCarrier(token, dto.password);
  }

  /**
   * Get booking documents for carrier (PUBLIC - token-based) - Legacy without password
   * Kept for backward compatibility with bookings created before password protection
   *
   * GET /api/v1/csv-booking-actions/documents/:token
   */
  @Public()
  @Get('documents/:token')
  @ApiOperation({
    summary: 'Get booking documents (public) - Legacy',
    description:
      'Public endpoint for carriers to access booking documents. For new bookings, use POST with password instead.',
  })
  @ApiParam({ name: 'token', description: 'Booking confirmation token (UUID)' })
  @ApiResponse({
    status: 200,
    description: 'Booking documents retrieved successfully.',
    type: CarrierDocumentsResponseDto,
  })
  @ApiResponse({ status: 404, description: 'Booking not found or invalid token' })
  @ApiResponse({ status: 400, description: 'Booking has not been accepted yet' })
  @ApiResponse({ status: 401, description: 'Password required for this booking' })
  async getBookingDocuments(@Param('token') token: string): Promise<CarrierDocumentsResponseDto> {
    return this.csvBookingService.getDocumentsForCarrier(token);
  }
}
