import {
  Body,
  Controller,
  Get,
  Header,
  Param,
  Post,
  Put,
  Query,
  Res,
  UseGuards,
} from '@nestjs/common';
import { ApiBearerAuth, ApiQuery, ApiTags } from '@nestjs/swagger';
import { Response } from 'express';
import { User } from 'src/utils/decorators/user.decorator';
import { SmsService } from '../../sms/sms.service';
import { successfulResult } from '../../utils';
import { Filter } from '../../utils/decorators/filter.decorator';
import { Limit } from '../../utils/decorators/limit.decorator';
import { Page } from '../../utils/decorators/page.decorator';
import { Sort } from '../../utils/decorators/sort.decorator';
import { JwtAuthGuard } from '../auth/jwt/jwt.guard';
import { Permissions } from '../auth/permission/permissions.decorator';
import { PermissionsGuard } from '../auth/permission/permissions.guard';
import { OrderService } from '../order/order.service';
import { PermissionsType } from '../role/entities/permission.entity';
import { AddServiceDto } from './dto/add-service.dto';
import { UpdateServiceReminderDto } from './dto/update-service-reminder.dto';
import { UpdateWeekClosedDto } from './dto/update-week-closed.dto';
import { ServiceReminderStatus } from './entities/service-reminder.entity';
import { ServiceService } from './service.service';

@ApiTags('Service')
@Controller('services')
export class ServiceController {
  constructor(
    private serviceService: ServiceService,
    private orderService: OrderService,
    private sms: SmsService,
  ) {}

  /**
   * -------------------------------------------------------
   * Getting available times list base on date
   */
  @Get('times/available')
  async getTimesAvailable(
    @Query('date') date: string,
    @Query('is_service') isService: string,
  ) {
    const data = await this.serviceService.getTimesAvailable(
      date,
      isService === '1',
    );
    return successfulResult([], data);
  }

  /**
   * -------------------------------------------------------
   * Getting times list for admin
   */
  @Get('times')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.GET_SERVICE_TIME)
  async getTimesByAdmin() {
    const data = await this.serviceService.getTimesByAdmin();
    return successfulResult([], data);
  }

  /**
   * -------------------------------------------------------
   */
  @Get('reminders/:id/admin')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.GET_SERVICE_REMINDER)
  async info(@Param('id') id: number) {
    const data = await this.serviceService.getReminderById(id);
    return successfulResult([], data);
  }

  /**
   * -------------------------------------------------------
   */
  @Get('reminders/admin')
  @ApiQuery({
    name: 'date',
    required: false,
    description: 'e.g. gte:2022-04-16[and]lte:2022-04-16',
  })
  @ApiQuery({
    name: 'status',
    required: false,
    enum: ServiceReminderStatus,
  })
  @ApiQuery({ name: 'sort', required: false, description: 'e.g. id:desc' })
  @ApiQuery({ name: 'limit', required: false, description: 'Default: 20' })
  @ApiQuery({ name: 'page', required: false, description: 'Default: 1' })
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.GET_SERVICE_REMINDER)
  async list(
    @Page() page,
    @Limit(50) limit,
    @Sort() sorts,
    @Filter([['date', 'createdAt', 'DATE'], 'status'])
    filters,
  ) {
    const data = await this.serviceService.getAllReminders(
      page,
      limit,
      filters,
      sorts,
    );
    return successfulResult([], data);
  }

  /**
   * -------------------------------------------------------
   */
  @Get('/export/excel/admin')
  @Header('Content-Type', 'text/xlsx')
  @ApiQuery({
    name: 'date',
    required: false,
    description: 'e.g. gte:2022-04-16[and]lte:2022-04-16',
  })
  @ApiQuery({
    name: 'status',
    required: false,
    enum: ServiceReminderStatus,
  })
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.EXPORT_EXCEL_FROM_SERVICE_REMINDER)
  async exportExcel(
    @Res() res: Response,
    @Filter([['date', 'createdAt', 'DATE'], 'status'])
    filters,
  ) {
    const result = await this.serviceService.exportExcel(filters);
    return res.download(`${result}`);
  }

  /**
   * -------------------------------------------------------
   */
  @Put('reminders/:id/admin')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.UPDATE_SERVICE_REMINDER)
  async updateById(
    @Param('id') id: number,
    @Body() dto: UpdateServiceReminderDto,
  ) {
    await this.serviceService.updateReminderById(id, dto);
    return successfulResult(['تغییرات با موفقیت اعمال شد']);
  }

  /**
   * -------------------------------------------------------
   * add service
   */
  @Post('add/admin')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.ADD_SERVICE)
  async addService(@Body() dto: AddServiceDto) {
    const data = await this.orderService.addService(dto);
    return successfulResult(
      ['سرویس جدید با موفقیت برای این کاربر ثبت شد'],
      data,
    );
  }

  /**
   * -------------------------------------------------------
   * GET /services/week-closed/admin
   */
  @Get('week-closed/admin')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.GET_SERVICE_WEEK_CLOSED)
  async getWeekClosed() {
    const data = await this.serviceService.getWeekClosed();
    return successfulResult([], data);
  }

  /**
   * -------------------------------------------------------
   * Put /services/week-closed/admin
   */
  @Put('week-closed/admin')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.UPDATE_SERVICE_WEEK_CLOSED)
  async updateWeekClosed(
    @Body() dto: UpdateWeekClosedDto,
    @User('id') operatorUserId: string,
  ) {
    await this.serviceService.updateWeekClosed(dto, operatorUserId);
    return successfulResult(['روزهای هفته موردنظر با موفقیت تعیین وضعیت شد.']);
  }
}
