import { AuthMethod, MultiTenancyInterceptor, UseAuth } from '@backend/auth'
import {
	Body,
	Controller,
	Get,
	HttpCode,
	Param,
	ParseArrayPipe,
	ParseIntPipe,
	ParseUUIDPipe,
	Patch,
	Post,
	Put,
	Query,
	UseInterceptors,
} from '@nestjs/common'
import {
	ApiBadRequestResponse,
	ApiBody,
	ApiInternalServerErrorResponse,
	ApiNoContentResponse,
	ApiNotAcceptableResponse,
	ApiOkResponse,
	ApiTags,
	ApiUnprocessableEntityResponse,
} from '@nestjs/swagger'
import { OrderService } from '../services'
import {
	CheckinRequest,
	CreateOrderItemRequest,
	OrderResponse,
	PayOrderItemRequest,
	UpdateItemsStateRequest,
} from '../types'

@UseAuth(AuthMethod.JWT)
@UseInterceptors(MultiTenancyInterceptor)
@Controller('order')
@ApiTags('default')
export class OrderController {
	constructor(private readonly _orderService: OrderService) {}

	@Get('open')
	@ApiOkResponse({ type: OrderResponse, isArray: true })
	@ApiInternalServerErrorResponse()
	async findAllOpenOrder(): Promise<OrderResponse[]> {
		return this._orderService.findAllOpenOrders()
	}

	@Get('reservation')
	@ApiOkResponse({ type: OrderResponse, isArray: true })
	@ApiInternalServerErrorResponse()
	async findOrdersByReservationIds(
		@Query('reservationIds', ParseArrayPipe) reservationIds: string[],
	): Promise<OrderResponse[]> {
		return this._orderService.findByReservationIds(reservationIds)
	}

	@Post()
	@ApiOkResponse({ type: OrderResponse })
	@ApiBadRequestResponse()
	@ApiNotAcceptableResponse()
	@ApiUnprocessableEntityResponse()
	@ApiInternalServerErrorResponse()
	async checkin(@Body() request: CheckinRequest): Promise<OrderResponse> {
		return this._orderService.checkin(request)
	}

	@Put(':orderId/items')
	@ApiBody({ type: [CreateOrderItemRequest] })
	@ApiOkResponse({ type: OrderResponse })
	@ApiBadRequestResponse()
	@ApiInternalServerErrorResponse()
	async addOrderItems(
		@Param('orderId', ParseUUIDPipe) orderId: string,
		@Body() request: CreateOrderItemRequest[],
	): Promise<OrderResponse> {
		return this._orderService.addOrderItems(orderId, request)
	}

	@Put(':orderId/pay')
	@HttpCode(204)
	@ApiBody({ type: [PayOrderItemRequest] })
	@ApiNoContentResponse()
	@ApiBadRequestResponse()
	@ApiUnprocessableEntityResponse()
	@ApiInternalServerErrorResponse()
	async payItemsViaCash(
		@Param('orderId', ParseUUIDPipe) orderId: string,
		@Body() request: PayOrderItemRequest[],
	): Promise<void> {
		return this._orderService.payItemsViaCash(orderId, request)
	}

	@Patch(':orderId/checkout')
	@HttpCode(204)
	@ApiNoContentResponse()
	@ApiBadRequestResponse()
	@ApiInternalServerErrorResponse()
	async checkout(@Param('orderId', ParseUUIDPipe) orderId: string): Promise<void> {
		return this._orderService.checkout(orderId)
	}

	@Patch(':orderId/cancel')
	@HttpCode(204)
	@ApiNoContentResponse()
	@ApiBadRequestResponse()
	@ApiInternalServerErrorResponse()
	async cancel(@Param('orderId', ParseUUIDPipe) orderId: string): Promise<void> {
		return this._orderService.cancelOrder(orderId)
	}

	@Patch(':orderId/open')
	@HttpCode(204)
	@ApiNoContentResponse()
	@ApiBadRequestResponse()
	@ApiInternalServerErrorResponse()
	async reOpenOrder(@Param('orderId', ParseUUIDPipe) orderId: string): Promise<void> {
		return this._orderService.reOpenOrder(orderId)
	}

	@Patch(':orderId/items/state')
	@HttpCode(204)
	@ApiNoContentResponse()
	@ApiBadRequestResponse()
	@ApiInternalServerErrorResponse()
	async updateItemsState(
		@Param('orderId', ParseUUIDPipe) orderId: string,
		@Body() request: UpdateItemsStateRequest,
	): Promise<void> {
		return this._orderService.updateItemsState(orderId, request)
	}

	@Patch(':orderId/items/:itemId/course/:course')
	@HttpCode(204)
	@ApiNoContentResponse()
	@ApiBadRequestResponse()
	@ApiInternalServerErrorResponse()
	async updateItemCourse(
		@Param('orderId', ParseUUIDPipe) orderId: string,
		@Param('itemId', ParseUUIDPipe) itemId: string,
		@Param('course', ParseIntPipe) course: number,
	): Promise<void> {
		return this._orderService.updateItemCourse(orderId, itemId, course)
	}
}
