import {
  Body,
  Controller,
  Get,
  Param,
  Patch,
  Post,
  Query,
  Req,
  UploadedFile,
  UseGuards,
  UseInterceptors,
} from "@nestjs/common"
import {
  ApiBearerAuth,
  ApiBody,
  ApiConsumes,
  ApiOperation,
  ApiQuery,
  ApiTags,
} from "@nestjs/swagger"
import { AuthGuardMiddleware } from "src/middleware/auth-guard.middleware"
import { UpdateTripBabySeatDto } from "../dto/assign-baby-seat.dto"
import { CreateTripCancellationDto } from "../dto/create-trip-cancellation.dto"
import { CreateTripDto } from "../dto/create-trip.dto"
import { TripFilterDto } from "../dto/filter-trip.dto"
import { AssignFleetsToTripDto } from "../dto/fleet-assignment.dto"
import { PaginationDto } from "../dto/pagination.dto"
import { UpdateTripCancellationDto } from "../dto/update-trip-cancellation.dto"
import { UpdateTripDto } from "../dto/update-trip.dto"
import { TripsService } from "./trips.service"
import { TripAddOnsPricingDto } from "../dto/trip-addons-pricing.dto"
import { TripServicePricingDto } from "../dto/trip-service-pricing.dto"
import { TripPricingDto } from "../dto/trip-base-pricing.dto"
import { CreateTripRequestByCustomerDto } from "../dto/create-trip-request-by-customer.dto"
import { CustomerAuthGuardMiddleware } from "src/middleware/customer-auth-guard.middleware"
import { FileInterceptor } from "@nestjs/platform-express"
import { tripDocumentConfig } from "src/common/file-upload/trip-support-document.config"
import { UpdateTripTypeDto } from "../dto/trip-type.dto"
import { CompleteTripDto } from "../dto/complete-trip.dto"

@Controller("trips")
@ApiTags("Trip")
export class TripsController {
  constructor(private readonly tripsService: TripsService) {}

  @Get("fix-trip-locations")
  async fixTripLocations() {
    return await this.tripsService.fixMissingTripLocations()
  }

  @Post()
  @UseGuards(AuthGuardMiddleware)
  @UseInterceptors(FileInterceptor("trip_document", tripDocumentConfig))
  @ApiBearerAuth("access-token")
  // 👇 This tells Swagger it’s a multipart/form-data upload
  @ApiConsumes("multipart/form-data")
  create(
    @Body() createTripDto: CreateTripDto,
    @UploadedFile() file: Express.Multer.File,
  ) {
    return this.tripsService.create(createTripDto, file)
  }

  @Get()
  @UseGuards(AuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  findAll(@Req() request: any, @Query() filterTripDto: TripFilterDto) {
    return this.tripsService.findAll(
      request.headers["authorization"],
      filterTripDto,
      false,
      false,
    )
  }

  @Get("/mobile-app")
  @UseGuards(CustomerAuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  findAllForMobile(@Req() request: any, @Query() filterTripDto: TripFilterDto) {
    return this.tripsService.findAll(
      request.headers["authorization"],
      filterTripDto,
      true,
      true,
    )
  }

  @Get("/types")
  @UseGuards(AuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  findALlTripType() {
    return this.tripsService.getAllTripTypes()
  }

  @Get("mobile-app/:id")
  @UseGuards(CustomerAuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  findOneForMobile(@Param("id") id: string) {
    return this.tripsService.findOne(+id, true)
  }

  @Get("/timezone")
  @UseGuards(AuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  @ApiOperation({
    summary: "Get selected base pricing for a trip with pricing",
  })
  async getTripTimeZone() {
    return this.tripsService.getTripTimeZone()
  }

  // @Get("/frequent-locations")
  // @UseGuards(CustomerAuthGuardMiddleware)
  // @ApiBearerAuth("access-token")
  // @ApiQuery({
  //   name: "lat",
  //   description: "Latitude of the current location",
  //   required: false,
  // })
  // @ApiQuery({
  //   name: "long",
  //   description: "Longitude of the current location",
  //   required: false,
  // })
  // async getFrequentLocations(
  //   @Req() req: any,
  //   @Query("lat") lat?: string,
  //   @Query("long") long?: string,
  // ) {
  //   const customerId = req?.customer?.customer_id
  //   const currentLat = lat ? parseFloat(lat) : undefined
  //   const currentLong = long ? parseFloat(long) : undefined

  //   return this.tripsService.findFrequentlyUsedDropoffLocations(
  //     customerId,
  //     currentLat,
  //     currentLong,
  //   )
  // }

  @Get("/frequent-locations")
  @UseGuards(CustomerAuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  @ApiQuery({
    name: "place_id",
    description:
      "Google Place ID of the current location to exclude from results",
    required: false,
  })
  async getFrequentLocations(
    @Req() req: any,
    @Query("place_id") placeId?: string,
  ) {
    const customerId = Number(req?.customer?.customer_id)

    return this.tripsService.findFrequentlyUsedDropoffLocations(
      customerId,
      placeId,
    )
  }

  @Get(":id")
  @UseGuards(AuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  findOne(@Param("id") id: string) {
    return this.tripsService.findOne(+id, false)
  }

  @Patch(":id")
  @UseGuards(AuthGuardMiddleware)
  @UseInterceptors(FileInterceptor("trip_document", tripDocumentConfig))
  @ApiBearerAuth("access-token")
  @ApiConsumes("multipart/form-data")
  @ApiBody({
    type: UpdateTripDto,
    description: "Update trip with optional document",
  })
  update(
    @Param("id") id: string,
    @Req() req: any,
    @Body() updateTripDto: UpdateTripDto,
    @UploadedFile() file?: Express.Multer.File,
  ) {
    const userId = req?.user?.user?.id
    const teamMemberId = req?.user?.user?.team_member_id
    return this.tripsService.update(
      +id,
      updateTripDto,
      file,
      userId,
      teamMemberId,
    )
  }

  @Post(":id/assign-fleets")
  @UseGuards(AuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  async assignFleetsToTrip(
    @Param("id") trip_id: number,
    @Body() assignFleetsTripDto: AssignFleetsToTripDto,
  ) {
    return this.tripsService.assignFleetsToTrip(trip_id, assignFleetsTripDto)
  }

  @Patch("assign/baby-seats")
  @UseGuards(AuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  async updateTripBabySeats(@Body() updateDto: UpdateTripBabySeatDto) {
    return this.tripsService.updateTripBabySeats(updateDto)
  }

  @Get("/available-driver/:tripId")
  @UseGuards(AuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  async getAvailableDriver(
    @Param("tripId") tripId: number,
    @Query() paginationDto: PaginationDto,
  ) {
    return this.tripsService.getAvailableDriversForTrip(tripId, paginationDto)
  }

  @Post("cancel")
  @UseGuards(AuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  async createTripCancellation(
    @Body() createTripCancellationDto: CreateTripCancellationDto,
  ) {
    return this.tripsService.createTripCancellation(
      createTripCancellationDto,
      "team_member",
    )
  }

  @Post("customer-cancel")
  @UseGuards(CustomerAuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  async createCustomerTripCancellation(
    @Body() createTripCancellationDto: CreateTripCancellationDto,
  ) {
    return this.tripsService.createTripCancellation(
      createTripCancellationDto,
      "customer",
    )
  }

  @Get("cancel/:tripId")
  @UseGuards(AuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  async getTripCancellation(@Param("tripId") tripId: number) {
    return this.tripsService.getTripCancellation(tripId)
  }

  @Patch("cancel/:tripId/update/:id")
  @UseGuards(AuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  async updateTripCancellation(
    @Param("tripId") tripId: number,
    @Param("canceledById") canceledById: number,
    @Body() updateTripCancellationDto: UpdateTripCancellationDto,
  ) {
    return this.tripsService.updateTripCancellation(
      canceledById,
      tripId,
      updateTripCancellationDto,
    )
  }

  @Get(":tripId/selected-addons")
  @UseGuards(AuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  @ApiOperation({ summary: "Get selected add-ons for a trip with pricing" })
  async getSelectedAddOnsForTrip(@Param("tripId") trip_id: number) {
    return this.tripsService.getSelectedAddOnsForTrip(trip_id)
  }

  @Get(":tripId/contract-charges")
  @UseGuards(AuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  async getChargeType(@Param("tripId") trip_id: number) {
    return this.tripsService.getChargeTypeForTrips(trip_id)
  }

  @Get(":tripId/base-price")
  @UseGuards(AuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  @ApiOperation({
    summary: "Get selected base pricing for a trip with pricing",
  })
  async getTripBasePricing(@Param("tripId") trip_id: number) {
    return this.tripsService.getTripBasePrice(trip_id)
  }

  @Post("calculate-pricing")
  @UseGuards(AuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  @ApiOperation({
    summary: "Calculate total trip pricing",
  })
  async calculateTripPricing(@Body("trip_id") trip_id: number) {
    return this.tripsService.calculateTripPrice(trip_id)
  }

  @Patch("price/add-ons-pricing")
  @UseGuards(AuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  async tripAddOnPricing(@Body() dto: TripAddOnsPricingDto) {
    return this.tripsService.tripsAddOnsPricing(dto)
  }

  @Patch("price/service-charge/pricing")
  @UseGuards(AuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  async tripServicePricing(@Body() dto: TripServicePricingDto) {
    return this.tripsService.tripsServicePricing(dto)
  }

  @Patch("/status/:tripId")
  @UseGuards(AuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  async updateTripStatus(
    @Req() request: any,
    @Param("tripId") trip_id: number,
    @Body("estimated_time") estimated_time: string,
  ) {
    return this.tripsService.updateTripStatusToPickup(
      trip_id,
      request.headers["authorization"],
      estimated_time,
    )
  }

  @Patch("price/base-pricing")
  @UseGuards(AuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  async tripBasePricing(@Body() tripPricingDto: TripPricingDto) {
    return this.tripsService.updateTripBasePricing(tripPricingDto)
  }

  @Post("trip-request-by-customer/mobile")
  @UseGuards(CustomerAuthGuardMiddleware)
  @UseInterceptors(FileInterceptor("trip_document", tripDocumentConfig))
  @ApiBearerAuth("access-token")
  @ApiConsumes("multipart/form-data")
  @ApiBody({
    schema: {
      type: "object",
      properties: {
        pickup_datetime: { type: "string", example: "2025-10-10T10:30:00Z" },
        pick_up_location: { type: "string", example: "City Center Hospital" },

        pickup_location_lan: {
          type: "string",
          example: "23.0225",
          description: "Pickup latitude",
        },
        pickup_location_long: {
          type: "string",
          example: "72.5714",
          description: "Pickup longitude",
        },

        drop_off_location: {
          type: "string",
          example: "Airport Terminal 3",
        },

        dropoff_location_lan: {
          type: "string",
          example: "23.0500",
          description: "Dropoff latitude",
        },
        dropoff_location_long: {
          type: "string",
          example: "72.6000",
          description: "Dropoff longitude",
        },

        luggage_information: {
          type: "string",
          example: "2 suitcases and 1 backpack",
        },
        trip_document: {
          type: "string",
          format: "binary",
          description: "Optional trip-related file",
        },
        additional_notes: {
          type: "string",
          example: "Customer has a medical condition",
        },
        dispatch_note: { type: "string", example: "Handle with care" },
      },
    },
  })
  async createTripRequest(
    @Req() req: any,
    @Body() tripRequestDto: CreateTripRequestByCustomerDto,
    @UploadedFile() tripDocument?: Express.Multer.File,
  ) {
    tripRequestDto.customer_id = req?.customer?.customer_id

    return this.tripsService.createTripRequestByCustomer(
      tripRequestDto,
      tripDocument,
    )
  }

  @Get(":id/timeline")
  @UseGuards(AuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  async getTripStatusHistory(@Param("id") id: string) {
    return this.tripsService.getTripStatusHistory(+id)
  }

  @Patch("/trip-type/:id")
  @UseGuards(AuthGuardMiddleware)
  updateTripType(@Param("id") id: string, @Body() dto: UpdateTripTypeDto) {
    return this.tripsService.updateTripType(id, dto)
  }

  @Post("/complete-past-trips")
  @UseGuards(AuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  completePastTrips() {
    return this.tripsService.completePastTrips()
  }

  @Patch("/complete-trip/:id")
  @UseGuards(AuthGuardMiddleware)
  completeTrip(@Param("id") tripId: string, @Body() dto: CompleteTripDto) {
    return this.tripsService.completeTrip(+tripId, dto)
  }

  @Post("/calculate-trip-pricing")
  @UseGuards(AuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  calculatePricing() {
    return this.tripsService.calculateTripPricing()
  }

  @Patch("/trips/:id/status/draft")
  @UseGuards(AuthGuardMiddleware)
  @ApiBearerAuth("access-token")
  changeDraft(@Param("id") tripId: string) {
    return this.tripsService.changeStatusToDraft(+tripId)
  }
}
