import {
  Body,
  Controller,
  Get,
  Post,
  Param,
  Put,
  UseGuards,
  Delete,
  Query,
} 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 { AnnouncementService } from './announcement.service';
import { CreateAnnouncementDto } from './dto/create-announcement.dto';
import { UpdateAnnouncementDto } from './dto/update-announcement.dto';
import {
  AnnouncementEntity,
  AnnouncementSections,
} from './entities/announcement.entity';
import { AnnouncementSortDto } from './dto/announcement-sort.dto';
import { sort } from '../../utils/sort';
import { ErrorService } from '../../error/error.service';

@ApiTags('Announcement')
@Controller('announcements')
export class AnnouncementController {
  constructor(
    private announcementService: AnnouncementService,
    private error: ErrorService,
  ) {}

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

  /**
   * -------------------------------------------------------
   */
  @Get('admin')
  @ApiQuery({ name: 'end_date', required: false })
  @ApiQuery({ name: 'start_date', required: false })
  @ApiQuery({ name: 'section', required: false })
  @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_ANNOUNCEMENT)
  async getAllForAdmin(
    @Page() page,
    @Limit() limit,
    @Sort() sorts,
    @Filter([
      ['start_date', 'startDate', 'DATE'],
      ['end_date', 'endDate', 'DATE'],
      'section',
    ])
    filters,
  ) {
    const data = await this.announcementService.getAllForAdmin(
      page,
      limit,
      filters,
      sorts,
    );
    return successfulResult([], data);
  }

  /**
   * -------------------------------------------------------
   */
  @Get()
  @ApiQuery({ name: 'section', required: false, enum: AnnouncementSections })
  async getAll(@Query('section') section: AnnouncementSections) {
    const data = await this.announcementService.getAll(section);
    return successfulResult([], data);
  }

  /**
   * -------------------------------------------------------
   */
  @Put('sort/admin')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.UPDATE_ANNOUNCEMENT)
  async sort(@Body() dto: AnnouncementSortDto) {
    const result = await sort(AnnouncementEntity.name, dto.id, dto.action);

    if (!result) {
      return this.error.unprocessableEntity(['داده جایگزینی یافت نشد']);
    }

    return successfulResult(['داده مورد نظر با موفقیت مرتب شد']);
  }

  /**
   * -------------------------------------------------------
   */
  @Put('admin')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.UPDATE_ANNOUNCEMENT)
  async updateById(@Body() dto: UpdateAnnouncementDto) {
    await this.announcementService.updateById(dto);
    return successfulResult(['اطلاعیه با موفقیت آپدیت شد']);
  }

  /**
   * -------------------------------------------------------
   */
  @Post('admin')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.ADD_ANNOUNCEMENT)
  async create(@Body() dto: CreateAnnouncementDto) {
    await this.announcementService.create(dto);
    return successfulResult(['اطلاعیه جدید با موفقیت ایجاد شد']);
  }

  /**
   * -------------------------------------------------------
   */
  @Delete(':id/admin')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.DELETE_ANNOUNCEMENT)
  async delete(@Param('id') id: number) {
    await this.announcementService.delete(id);
    return successfulResult(['اطلاعیه موردنظر با موفقیت حذف شد']);
  }
}
