import { Body, Controller, Get, HttpCode, Param, ParseIntPipe, Post, Put, Query } from '@nestjs/common'
import {
	ApiBadRequestResponse,
	ApiConflictResponse,
	ApiInternalServerErrorResponse,
	ApiNotFoundResponse,
	ApiOkResponse,
	ApiQuery,
	ApiTags,
	ApiUnprocessableEntityResponse,
} from '@nestjs/swagger'
import { ParseDatePipe } from '../../../common'
import { ReservationManagementService } from '../services'
import { ManagedReservationResponse, TimeSlot, UpdateManagedReservationRequest } from '../types'

/**
 * Guest self-service endpoints. Authorization is the management token itself —
 * no tenant header and no JWT: the tenant context is resolved from the token.
 * Cancelling deliberately requires a POST so email-security link scanners
 * (which only issue GETs) can never cancel a reservation.
 */
@Controller('customer/reservation-management')
@ApiTags('customer')
export class CustomerReservationManagementController {
	constructor(private readonly _managementService: ReservationManagementService) {}

	@Get(':token')
	@ApiOkResponse({ type: ManagedReservationResponse })
	@ApiNotFoundResponse()
	@ApiInternalServerErrorResponse()
	async getByToken(@Param('token') token: string): Promise<ManagedReservationResponse> {
		return this._managementService.getByToken(token)
	}

	@Get(':token/slots/:date')
	@ApiQuery({ name: 'timezone', type: String, required: false })
	@ApiQuery({ name: 'partySize', type: Number, required: false })
	@ApiOkResponse({ type: TimeSlot, isArray: true })
	@ApiNotFoundResponse()
	@ApiBadRequestResponse()
	@ApiInternalServerErrorResponse()
	async getTimeSlots(
		@Param('token') token: string,
		@Param('date', new ParseDatePipe()) date: Date,
		@Query('timezone') timezone?: string,
		@Query('partySize', new ParseIntPipe({ optional: true })) partySize?: number,
	): Promise<TimeSlot[]> {
		return this._managementService.getTimeSlotsByToken(token, date, timezone, partySize)
	}

	@Put(':token')
	@ApiOkResponse({ type: ManagedReservationResponse })
	@ApiNotFoundResponse()
	@ApiConflictResponse()
	@ApiUnprocessableEntityResponse()
	@ApiBadRequestResponse()
	@ApiInternalServerErrorResponse()
	async updateByToken(
		@Param('token') token: string,
		@Body() request: UpdateManagedReservationRequest,
	): Promise<ManagedReservationResponse> {
		return this._managementService.updateByToken(token, request)
	}

	@Post(':token/cancel')
	@HttpCode(200)
	@ApiOkResponse({ type: ManagedReservationResponse })
	@ApiNotFoundResponse()
	@ApiConflictResponse()
	@ApiUnprocessableEntityResponse()
	@ApiInternalServerErrorResponse()
	async cancelByToken(@Param('token') token: string): Promise<ManagedReservationResponse> {
		return this._managementService.cancelByToken(token)
	}
}
