import { Controller, Get, Post, Body, Patch, Param, Delete, UseGuards, Query, ValidationPipe } from '@nestjs/common';
import {
  ApiTags,
  ApiOperation,
  ApiCreatedResponse,
  ApiOkResponse,
  ApiNotFoundResponse,
  ApiParam,
  ApiBody,
  ApiBearerAuth,
  ApiQuery,
  ApiHeader,
} from '@nestjs/swagger';
import { ScheduleService } from '../providers/schedule.service';
import { CreateScheduleDto } from '../dto/create-schedule.dto';
import { UpdateScheduleDto } from '../dto/update-schedule.dto';
import { FindSchedulesDto } from '../dto/find-schedules.dto';
import { Schedule } from '../entities/schedule.entity';
import { AdminAuthGuard } from 'src/modules/auth/guards/adminAuth.guard';
import { RestId } from 'src/common/decorators/rest-id.decorator';
import { Permissions } from 'src/common/decorators/permissions.decorator';
import { Permission } from 'src/common/enums/permission.enum';
import { API_HEADER_SLUG } from 'src/common/constants';

@ApiTags('schedules')
@Controller()
export class ScheduleController {
  constructor(private readonly scheduleService: ScheduleService) { }

  @Get('public/schedules/restaurant/:slug')
  @ApiOperation({ summary: 'Get schedule of a restaurant by slug' })
  @ApiHeader(API_HEADER_SLUG)
  @ApiParam({ name: 'slug', description: 'Restaurant Slug' })
  @ApiOkResponse({ description: 'Today schedule of the restaurant', type: Schedule })
  async getTodaySchedules(@Param('slug') slug: string): Promise<Schedule[]> {
    return this.scheduleService.findScheduleBySlug(slug);
  }

  /********************  Admin Routes **********************/

  @UseGuards(AdminAuthGuard)
  @ApiBearerAuth()
  @Permissions(Permission.MANAGE_SCHEDULES)
  @Post('admin/schedules')
  @ApiOperation({ summary: 'Create a new schedule' })
  @ApiBody({ type: CreateScheduleDto })
  @ApiCreatedResponse({ description: 'Schedule created successfully', type: Schedule })
  create(@Body() createScheduleDto: CreateScheduleDto, @RestId() restId: string) {
    return this.scheduleService.create(restId, createScheduleDto);
  }

  @UseGuards(AdminAuthGuard)
  @ApiBearerAuth()
  @Permissions(Permission.MANAGE_SCHEDULES)
  @Get('admin/schedules')
  @ApiOperation({ summary: 'Get all schedules' })
  @ApiQuery({
    name: 'weekDay',
    required: false,
    type: Number,
    description: 'Filter by week days (0=Sunday, 6=Saturday).',
  })
  @ApiOkResponse({ description: 'List of schedules', type: [Schedule] })
  findAll(
    @Query(new ValidationPipe({ transform: true, whitelist: true })) query: FindSchedulesDto,
    @RestId() restId: string,
  ) {
    return this.scheduleService.findAll(restId, query);
  }

  @UseGuards(AdminAuthGuard)
  @ApiBearerAuth()
  @Permissions(Permission.MANAGE_SCHEDULES)
  @Get('admin/schedules/:id')
  @ApiOperation({ summary: 'Get a schedule by ID' })
  @ApiParam({ name: 'id', description: 'Schedule ID' })
  @ApiOkResponse({ description: 'Schedule details', type: Schedule })
  @ApiNotFoundResponse({ description: 'Schedule not found' })
  findOne(@Param('id') id: string, @RestId() restId: string) {
    return this.scheduleService.findOne(id, restId);
  }

  @UseGuards(AdminAuthGuard)
  @ApiBearerAuth()
  @Permissions(Permission.MANAGE_SCHEDULES)
  @Patch('admin/schedules/:id')
  @ApiOperation({ summary: 'Update a schedule' })
  @ApiParam({ name: 'id', description: 'Schedule ID' })
  @ApiBody({ type: UpdateScheduleDto })
  @ApiOkResponse({ description: 'Schedule updated successfully', type: Schedule })
  @ApiNotFoundResponse({ description: 'Schedule not found' })
  update(@Param('id') id: string, @Body() updateScheduleDto: UpdateScheduleDto, @RestId() restId: string) {
    return this.scheduleService.update(id, restId, updateScheduleDto);
  }

  @UseGuards(AdminAuthGuard)
  @ApiBearerAuth()
  @Permissions(Permission.MANAGE_SCHEDULES)
  @Delete('admin/schedules/:id')
  @ApiOperation({ summary: 'Delete a schedule' })
  @ApiParam({ name: 'id', description: 'Schedule ID' })
  @ApiOkResponse({ description: 'Schedule deleted successfully' })
  @ApiNotFoundResponse({ description: 'Schedule not found' })
  remove(@Param('id') id: string, @RestId() restId: string) {
    return this.scheduleService.remove(id, restId);
  }
}
