import { AuthMethod, MultiTenancyInterceptor, UseAuth } from '@backend/auth'
import { Body, Controller, Get, HttpCode, Param, ParseUUIDPipe, Post, Query, UseInterceptors } from '@nestjs/common'
import {
	ApiBadRequestResponse,
	ApiBody,
	ApiInternalServerErrorResponse,
	ApiNoContentResponse,
	ApiNotFoundResponse,
	ApiOkResponse,
	ApiResponse,
	ApiTags,
} from '@nestjs/swagger'
import { TableCombinationService, TableGraphService, TableService } from '../services'
import {
	CreateTableCombinationRequest,
	FindAvailableTableByIdRequest,
	FindAvailableTablesByTimeSlotRequest,
	FindAvailableTablesByTimeSlotResponse,
	SaveTableRequest,
	TableCombinationResponse,
	TableGraphResponse,
	TableResponse,
} from '../types'

@UseAuth(AuthMethod.JWT)
@UseInterceptors(MultiTenancyInterceptor)
@Controller()
@ApiTags('default')
export class RoomPlanController {
	constructor(
		private readonly _tableService: TableService,
		private readonly _tableCombinationService: TableCombinationService,
		private readonly _tableGraphService: TableGraphService,
	) {}

	@Get('table')
	@ApiOkResponse({ type: TableResponse, isArray: true })
	@ApiInternalServerErrorResponse()
	async findAllTables(): Promise<TableResponse[]> {
		return this._tableService.findAll()
	}

	@Get('table/:id')
	@ApiOkResponse({ type: TableResponse })
	@ApiBadRequestResponse()
	@ApiNotFoundResponse()
	@ApiInternalServerErrorResponse()
	async findTableById(@Param('id', ParseUUIDPipe) id: string): Promise<TableResponse> {
		return this._tableService.findById(id)
	}

	@Post('table')
	@HttpCode(200)
	@ApiBody({ type: [SaveTableRequest] })
	@ApiOkResponse({ type: TableResponse, isArray: true })
	@ApiBadRequestResponse()
	@ApiInternalServerErrorResponse()
	async saveTables(@Body() request: SaveTableRequest[]): Promise<TableResponse[]> {
		return this._tableService.saveRoomPlan(request)
	}

	@Get('subscriptions/:userId')
	@ApiOkResponse({ type: TableResponse, isArray: true })
	@ApiBadRequestResponse()
	@ApiInternalServerErrorResponse()
	async findAllSubscribedTablesByUserId(@Param('userId', ParseUUIDPipe) userId: string): Promise<TableResponse[]> {
		return this._tableService.findAllSubscribedTablesByUserId(userId)
	}

	@Post('subscriptions/:userId')
	@HttpCode(204)
	@ApiNoContentResponse()
	@ApiBadRequestResponse()
	@ApiNotFoundResponse()
	@ApiInternalServerErrorResponse()
	async saveUserTableSubscriptions(
		@Param('userId', ParseUUIDPipe) userId: string,
		@Body() tableIds: string[],
	): Promise<void> {
		return this._tableService.saveUserTableSubscriptions(tableIds, userId)
	}

	@Get('table/available/slot')
	@ApiOkResponse({ type: FindAvailableTablesByTimeSlotResponse, isArray: true })
	@ApiBadRequestResponse()
	@ApiInternalServerErrorResponse()
	async findAvailableTablesByTimeSlot(
		@Query() request: FindAvailableTablesByTimeSlotRequest,
	): Promise<FindAvailableTablesByTimeSlotResponse[]> {
		return this._tableService.findAvailableTablesByTimeSlot(request)
	}

	@Get('table/available')
	@ApiOkResponse({ type: FindAvailableTablesByTimeSlotResponse })
	@ApiBadRequestResponse()
	@ApiInternalServerErrorResponse()
	async findAvailableTableById(
		@Query() request: FindAvailableTableByIdRequest,
	): Promise<FindAvailableTablesByTimeSlotResponse> {
		return this._tableService.findAvailableTablesById(request)
	}

	@Get('table/combination')
	@ApiOkResponse({ type: TableCombinationResponse, isArray: true })
	@ApiInternalServerErrorResponse()
	async findAllTableCombinations(): Promise<TableCombinationResponse[]> {
		return this._tableCombinationService.findAll()
	}

	@Post('table/combination')
	@HttpCode(204)
	@ApiBody({ type: [CreateTableCombinationRequest] })
	@ApiNoContentResponse()
	@ApiBadRequestResponse()
	@ApiInternalServerErrorResponse()
	async saveTableCombinations(@Body() request: CreateTableCombinationRequest[]): Promise<void> {
		return this._tableCombinationService.saveMany(request)
	}

	@Get('table/graph')
	@ApiResponse({ type: TableGraphResponse })
	@ApiInternalServerErrorResponse()
	async getTableGraph(): Promise<TableGraphResponse> {
		return this._tableGraphService.getGraph()
	}
}
