import {
  Body,
  Controller,
  Delete,
  Get,
  HttpCode,
  HttpStatus,
  Param,
  Post,
  Put,
  UseGuards,
} from '@nestjs/common';
import { ApiBearerAuth, ApiQuery, ApiTags } from '@nestjs/swagger';
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 { PermissionsType } from '../role/entities/permission.entity';
import { AddressService } from './address.service';
import { CreateAddressDto } from './dto/create-address.dto';
import { UpdateAddressDto } from './dto/update-address.dto';

@ApiTags('Address')
@Controller('addresses')
export class AddressController {
  constructor(private addressService: AddressService) {}

  /**
   * -------------------------------------------------------
   * GET /addresses/1
   */
  @Get(':id/admin')
  // @ApiOperation({
  //   description:
  //     '<p dir="rtl">حذف یک اتاق، از یک سفارش، توسط نقش هایی با سطح دسترسی DELETE_ROOM_ORDER_HOTEL <br> (مثلا ادمین یا مدیر آژانس)</p>',
  // })
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.GET_ADDRESS)
  async info(@Param('id') id: number) {
    const data = await this.addressService.getById(id);
    return successfulResult([], data);
  }

  /**
   * -------------------------------------------------------
   * GET /addresses
   * GET /addresses?user_id=djd4-hfhf-ssd3-sd
   */
  @Get('admin')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.GET_ADDRESS)
  @ApiQuery({ name: 'user_id', required: false })
  @ApiQuery({ name: 'city_id', required: false })
  @ApiQuery({ name: 'deleted', required: false })
  @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' })
  async list(
    @Page() page,
    @Limit() limit,
    @Sort() sorts,
    @Filter([
      ['date', 'createdAt', 'DATE'],
      ['user_id', 'userId'],
      ['city_id', 'cityId'],
      'deleted',
    ])
    filters,
  ) {
    const data = await this.addressService.getAll(page, limit, filters, sorts);
    return successfulResult([], data);
  }

  /**
   * -------------------------------------------------------
   * PUT /addresses
   */
  @Put(':id/admin')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.UPDATE_ADDRESS)
  async updateAddress(@Param('id') id: number, @Body() dto: UpdateAddressDto) {
    await this.addressService.updateByAdmin(id, dto);
    return successfulResult(['آدرس مورد نظر با موفقیت آپدیت شد']);
  }

  /**
   * -------------------------------------------------------
   * POST /addresses
   */
  @Post('admin')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.ADD_ADDRESS)
  @HttpCode(HttpStatus.CREATED)
  async addAddress(@Body() dto: CreateAddressDto) {
    const data = await this.addressService.addByAdmin(dto);
    return successfulResult(
      ['آدرس جدید برای کاربر موردنظر باموفقیت اضافه شد'],
      data,
    );
  }

  /**
   * -------------------------------------------------------
   * DELETE /addresses/1/admin
   */
  @Delete(':id/admin')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.DELETE_ADDRESS)
  async deleteAddress(@Param('id') id: number) {
    await this.addressService.deleteAddress(id);
    return successfulResult(['آدرس موردنظر، با موفقیت حذف شد']);
  }

  /**
   * -------------------------------------------------------
   */
  @Get('cities')
  async getAllCities() {
    const data = await this.addressService.getAllCities();
    return successfulResult([], data);
  }

  /**
   * -------------------------------------------------------
   */
  @Get('states')
  async getAllStates() {
    const data = await this.addressService.getAllStates();
    return successfulResult([], data);
  }

  /**
   * -------------------------------------------------------
   */
  @Get(':id/calculate-shipping')
  async calculateShipping(@Param('id') id: number) {
    const data = await this.addressService.calculateShipping(id);
    return successfulResult([], data);
  }
}
