import {
  Body,
  Controller,
  Get,
  HttpCode,
  HttpStatus,
  Param,
  Post,
  UseGuards,
} from '@nestjs/common';
import { ApiBearerAuth, ApiQuery, ApiTags } from '@nestjs/swagger';
import { DrivingOffenseService } from './driving-offense.service';
import { JwtAuthGuard } from '../auth/jwt/jwt.guard';
import { PermissionsGuard } from '../auth/permission/permissions.guard';
import { User } from '../../utils/decorators/user.decorator';
import { successfulResult } from '../../utils';
import { Permissions } from '../auth/permission/permissions.decorator';
import { PermissionsType } from '../role/entities/permission.entity';
import { Page } from 'src/utils/decorators/page.decorator';
import { Limit } from 'src/utils/decorators/limit.decorator';
import { Sort } from 'src/utils/decorators/sort.decorator';
import { Filter } from 'src/utils/decorators/filter.decorator';
import {
  DrivingOffenseClient,
  DrivingOffenseStatus,
  DrivingOffenseType,
} from './entities/driving-offense.entity';
import { CreateDrivingOffenseRequestDto } from './dto/create-driving-offense-request.dto';
import { PayDrivingOffenseInquiryDto } from './dto/pay-driving-offense-inquiry.dto';
import { UserEntity } from '../user/entities/user.entity';
import { PayDrivingOffenseBillDto } from './dto/pay-driving-offense-bill.dto';

@ApiTags('Driving Offense')
@Controller('driving-offenses')
export class DrivingOffenseController {
  constructor(private drivingOffenseService: DrivingOffenseService) {}

  /**
   * -------------------------------------------------------
   * POST /driving-offenses/request/me
   */
  @Post('/request/me')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  @HttpCode(HttpStatus.CREATED)
  async addRequest(
    @Body() dto: CreateDrivingOffenseRequestDto,
    @User() user: UserEntity,
  ) {
    const data = await this.drivingOffenseService.addRequest(dto, user);
    return successfulResult(
      ['درخواست استعلام جریمه رانندگی، باموفقیت ثبت شد'],
      data,
    );
  }

  /**
   * -------------------------------------------------------
   * POST /driving-offenses/pay-inquiry/me
   */
  @Post('/pay-inquiry/me')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  async payInquiry(
    @Body() dto: PayDrivingOffenseInquiryDto,
    @User() user: UserEntity,
  ) {
    const data = await this.drivingOffenseService.payInquiry(dto, user);
    return successfulResult(['در حال ارسال به بانک'], data);
  }

  /**
   * -------------------------------------------------------
   * GET /driving-offenses/1/do-inquiry/me
   * call from front or payment service
   */
  @Get('/:id/do-inquiry/me')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  async doInquiry(
    @Param('id') drivingOffenseId: number,
    @User() user: UserEntity,
  ) {
    const data = await this.drivingOffenseService.doInquiry(
      null,
      drivingOffenseId,
      user,
    );
    return successfulResult([], data);
  }

  /**
   * -------------------------------------------------------
   * POST /driving-offenses/pay-bills/me
   */
  @Post('/pay-bills/me')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  async payBills(
    @Body() dto: PayDrivingOffenseBillDto,
    @User() user: UserEntity,
  ) {
    const data = await this.drivingOffenseService.payDrivingOffenseBill(
      dto,
      user,
    );
    return successfulResult(['در حال ارسال به بانک'], data);
  }

  /**
   * -------------------------------------------------------
   * POST /driving-offenses/1/pay-result-bills/me
   */
  @Get('/:paymentKey/pay-result-bills/me')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  async resultBills(@Param('paymentKey') paymentKey: string) {
    const data = await this.drivingOffenseService.resultDrivingOffenseBill(
      paymentKey,
    );
    return successfulResult(['در حال ارسال به بانک'], data);
  }
  /**
   * -------------------------------------------------------
   * GET /driving-offenses/admin
   */
  @Get('/admin')
  @ApiQuery({ name: 'user_id', required: false })
  @ApiQuery({ name: 'car_id', required: false })
  @ApiQuery({ name: 'status', required: false, enum: DrivingOffenseStatus })
  @ApiQuery({ name: 'type', required: false, enum: DrivingOffenseType })
  @ApiQuery({ name: 'client', required: false, enum: DrivingOffenseClient })
  @ApiQuery({
    name: 'date',
    required: false,
    description: 'e.g. gte:2022-04-16[and]lte:2022-04-16',
  })
  @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_DRIVING_OFFENSE)
  async getAllForAdmin(
    @Page() page,
    @Limit() limit,
    @Sort() sorts,
    @Filter([
      ['user_id', 'userId'],
      ['car_id', 'carId'],
      'status',
      'type',
      'client',
      ['date', 'createdAt', 'DATE'],
    ])
    filters,
  ) {
    const data = await this.drivingOffenseService.getAll(
      page,
      limit,
      filters,
      sorts,
    );
    return successfulResult([], data);
  }

  /**
   * -------------------------------------------------------
   * GET /driving-offenses/me
   */
  @Get('/me')
  @ApiQuery({ name: 'car_id', required: false })
  @ApiQuery({ name: 'status', required: false, enum: DrivingOffenseStatus })
  @ApiQuery({ name: 'type', required: false, enum: DrivingOffenseType })
  @ApiQuery({
    name: 'date',
    required: false,
    description: 'e.g. gte:2022-04-16[and]lte:2022-04-16',
  })
  @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)
  async getAll(
    @Page() page,
    @Limit() limit,
    @Sort() sorts,
    @Filter([
      ['car_id', 'carId'],
      'status',
      'type',
      ['date', 'createdAt', 'DATE'],
    ])
    filters,
    @User('id') userId,
  ) {
    const data = await this.drivingOffenseService.getAll(
      page,
      limit,
      filters,
      sorts,
      userId,
    );
    return successfulResult([], data);
  }

  /**
   * -------------------------------------------------------
   * GET /driving-offenses/1/admin
   */
  @Get('/:id/admin')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.GET_DRIVING_OFFENSE)
  async getByIdForAdmin(@Param('id') id: number) {
    const data = await this.drivingOffenseService.getById(id);
    return successfulResult([], data);
  }

  /**
   * -------------------------------------------------------
   * GET /driving-offenses/1/me
   */
  @Get('/:id/me')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  async getById(@Param('id') id: number) {
    const data = await this.drivingOffenseService.getById(id);
    return successfulResult([], data);
  }

  /**
   * -------------------------------------------------------
   * GET /driving-offenses/1/images/me
   */
  @Get('/:id/images/me')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  async getDrivingOffenseImages(
    @Param('id') id: number,
    @User() user: UserEntity,
  ) {
    const data = await this.drivingOffenseService.getDrivingOffenseImages(
      id,
      user,
    );
    return successfulResult([], data);
  }

  /**
   * -------------------------------------------------------
   * GET /driving-offenses/image/1/me
   */
  @Get('/image/:billId/me')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard)
  async getDrivingOffenseImage(
    @Param('billId') billId: number,
    @User() user: UserEntity,
  ) {
    const data = await this.drivingOffenseService.getDrivingOffenseImage(
      billId,
      user,
    );
    return successfulResult([], data);
  }
}
