import {
  Body,
  Controller,
  Delete,
  Get,
  HttpCode,
  HttpStatus,
  Param,
  Post,
  Put,
  UploadedFile,
  UseGuards,
  UseInterceptors,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { ApiBearerAuth, ApiConsumes, ApiQuery, ApiTags } from '@nestjs/swagger';
import { ErrorService } from 'src/error/error.service';
import { successfulResult } from 'src/utils';
import { Filter } from 'src/utils/decorators/filter.decorator';
import { Limit } from 'src/utils/decorators/limit.decorator';
import { Page } from 'src/utils/decorators/page.decorator';
import { Sort } from 'src/utils/decorators/sort.decorator';
import { User } from 'src/utils/decorators/user.decorator';
import { multerOptions } from 'src/utils/multer.options';
import { sort } from 'src/utils/sort';
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 { CreateNewsDto } from './dto/create-news.dto';
import { NewsSortDto } from './dto/news-sort.dto';
import { UpdateNewsDto } from './dto/update-news.dto';
import { UpdateStatusCommentDto } from './dto/update-status-comment.dto';
import { NewsEntity } from './entities/news.entity';
import { NewsService } from './news.service';

@ApiTags('News')
@Controller('news')
export class NewsController {
  constructor(private newsService: NewsService, private error: ErrorService) {}

  /**
   * -------------------------------------------------------
   * GET /news/comments/admin
   */
  @Get('/comments/admin')
  @ApiQuery({ name: 'news_id', required: false })
  @ApiQuery({ name: 'status', required: false })
  @ApiQuery({ name: 'date', 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_NEWS_COMMENT)
  async getCommentslist(
    @Page() page,
    @Limit() limit,
    @Sort() sorts,
    @Filter(['status', ['news_id', 'newsId'], ['date', 'createdAt', 'DATE']])
    filters,
  ) {
    const data = await this.newsService.getCommentslist(
      page,
      limit,
      filters,
      sorts,
    );
    return successfulResult([], data);
  }

  /**
   * -------------------------------------------------------
   * GET /news/comments/1/admin
   */
  @Get('/comments/:id/admin')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.GET_NEWS_COMMENT)
  async getCommentById(@Param('id') id: number) {
    const data = await this.newsService.getCommentById(id);
    return successfulResult([], data);
  }

  /**
   * -------------------------------------------------------
   * GET /news/admin
   */
  @Get('admin')
  @ApiQuery({ name: 'title', required: false })
  @ApiQuery({ name: 'date', required: false })
  @ApiQuery({ name: 'deleted', required: false, description: 'e.g. 1' })
  @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_NEWS)
  async list(
    @Page() page,
    @Limit() limit,
    @Sort() sorts,
    @Filter(['title', ['date', 'createdAt', 'DATE'], 'deleted'])
    filters,
  ) {
    const data = await this.newsService.getAll(page, limit, filters, sorts);
    return successfulResult([], data);
  }

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

  /**
   * -------------------------------------------------------
   * POST /news/admin
   */
  @Post('admin')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.ADD_NEWS)
  @HttpCode(HttpStatus.CREATED)
  @ApiConsumes('multipart/form-data')
  @UseInterceptors(FileInterceptor('image', multerOptions('news')))
  async addNews(
    @Body() dto: CreateNewsDto,
    @User('id') userId,
    @UploadedFile() image,
  ) {
    const data = await this.newsService.addNews(dto, userId, image);
    return successfulResult(['مقاله جدید، باموفقیت اضافه شد'], data);
  }

  /**
   * -------------------------------------------------------
   * PUT /news/sort/admin
   */
  @Put('sort/admin')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.SORT_NEWS)
  async sort(@Body() dto: NewsSortDto) {
    const result = await sort(NewsEntity.name, dto.id, dto.action);

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

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

  /**
   * -------------------------------------------------------
   * PUT /news/1/admin
   */
  @Put(':id/admin')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.UPDATE_NEWS)
  @ApiConsumes('multipart/form-data')
  @UseInterceptors(FileInterceptor('image', multerOptions('news')))
  async updateNews(
    @Param('id') id: number,
    @Body() dto: UpdateNewsDto,
    @UploadedFile() image,
  ) {
    await this.newsService.updateNews(id, dto, image);
    return successfulResult(['مقاله موردنظر، با موفقیت آپدیت شد']);
  }

  /**
   * -------------------------------------------------------
   * PUT /news/comments/1/admin
   */
  @Put('comments/:id/admin')
  @ApiBearerAuth()
  @UseGuards(JwtAuthGuard, PermissionsGuard)
  @Permissions(PermissionsType.NEWS_COMMENT_STATUS)
  async updateStatusComment(
    @Param('id') id: number,
    @Body() dto: UpdateStatusCommentDto,
  ) {
    await this.newsService.updateStatusComment(id, dto);
    return successfulResult(['کامنت موردنظر، با موفقیت تعیین وضعیت شد']);
  }

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