import {
  Controller,
  Get,
  Query,
  HttpCode,
  HttpStatus,
  Logger,
  UsePipes,
  ValidationPipe,
  UseGuards,
} from '@nestjs/common';
import {
  ApiTags,
  ApiOperation,
  ApiResponse,
  ApiBadRequestResponse,
  ApiInternalServerErrorResponse,
  ApiBearerAuth,
} from '@nestjs/swagger';
import { PortSearchRequestDto, PortSearchResponseDto } from '../dto/port.dto';
import { PortMapper } from '../mappers/port.mapper';
import { PortSearchService } from '@domain/services/port-search.service';
import { JwtAuthGuard } from '../guards/jwt-auth.guard';
import { CurrentUser, UserPayload } from '../decorators/current-user.decorator';

@ApiTags('Ports')
@Controller('ports')
@ApiBearerAuth()
export class PortsController {
  private readonly logger = new Logger(PortsController.name);

  constructor(private readonly portSearchService: PortSearchService) {}

  @Get('search')
  @UseGuards(JwtAuthGuard)
  @HttpCode(HttpStatus.OK)
  @UsePipes(new ValidationPipe({ transform: true, whitelist: true }))
  @ApiOperation({
    summary: 'Search ports (autocomplete)',
    description:
      'Search for maritime ports by name, city, or UN/LOCODE code. Returns up to 50 results ordered by relevance. Requires authentication.',
  })
  @ApiResponse({
    status: HttpStatus.OK,
    description: 'Port search completed successfully',
    type: PortSearchResponseDto,
  })
  @ApiResponse({
    status: 401,
    description: 'Unauthorized - missing or invalid token',
  })
  @ApiBadRequestResponse({
    description: 'Invalid request parameters',
    schema: {
      example: {
        statusCode: 400,
        message: ['query must be a string'],
        error: 'Bad Request',
      },
    },
  })
  @ApiInternalServerErrorResponse({
    description: 'Internal server error',
  })
  async searchPorts(
    @Query() dto: PortSearchRequestDto,
    @CurrentUser() user: UserPayload
  ): Promise<PortSearchResponseDto> {
    const startTime = Date.now();
    this.logger.log(
      `[User: ${user.email}] Searching ports: query="${dto.query}", limit=${dto.limit || 10}, country=${dto.countryFilter || 'all'}`
    );

    try {
      // Call domain service
      const result = await this.portSearchService.search({
        query: dto.query,
        limit: dto.limit,
        countryFilter: dto.countryFilter,
      });

      const duration = Date.now() - startTime;
      this.logger.log(
        `[User: ${user.email}] Port search completed: ${result.totalMatches} results in ${duration}ms`
      );

      // Map to response DTO
      return PortMapper.toSearchResponseDto(result.ports, result.totalMatches);
    } catch (error: any) {
      const duration = Date.now() - startTime;
      this.logger.error(
        `[User: ${user.email}] Port search failed after ${duration}ms: ${error?.message || 'Unknown error'}`,
        error?.stack
      );
      throw error;
    }
  }
}
