import {
  Body,
  Controller,
  Get,
  Param,
  Post,
  Query,
  UploadedFiles,
  UseGuards,
  UseInterceptors,
} from '@nestjs/common';
import {
  ApiBody,
  ApiConsumes,
  ApiExtraModels,
  ApiOkResponse,
  ApiOperation,
  ApiTags,
  getSchemaPath,
} from '@nestjs/swagger';
import { AdminJwtAuthGuard } from '../auth/admin/jwt.guard';
import {
  CreateAdvertisementDto,
  DeleteAdvertisementDto,
  GetAdminAdvertisementListDto,
  GetAdvertisementDto,
  GetAdvertisementListResponseDto,
  GetAdvertisementStaticsResponseDto,
  GetAdvertisementStatisDto,
  UpdateAdvertisementDto,
} from './advertisement.dto';
import { FileFieldsInterceptor } from '@nestjs/platform-express';
import { fileOriginNameFilter } from '@api/helpers/file-helper';
import { AdvertisementService } from './advertisement.service';
import { plainToInstance } from 'class-transformer';
import { RolesGuard } from '../auth/admin/roles.guard';
import { Roles } from '../auth/admin/roles.decorator';

@ApiTags('[관리자] 광고')
@UseGuards(AdminJwtAuthGuard, RolesGuard)
@Roles('admin')
@Controller('admin/advertisement')
export class AdminAdvertisementController {
  constructor(private advertisementService: AdvertisementService) {}

  @ApiOperation({
    summary: '광고목록/검색',
  })
  @Get()
  @ApiOkResponse({ type: GetAdvertisementListResponseDto })
  async getAdvertisementList(@Query() query: GetAdminAdvertisementListDto) {
    const data = await this.advertisementService.getAdminList(query);
    return plainToInstance(GetAdvertisementListResponseDto, data, {
      excludeExtraneousValues: true,
    });
  }

  @ApiOperation({
    summary: '광고 상세조회',
  })
  @Get(':adsId')
  @ApiOkResponse({ type: GetAdvertisementDto })
  async getAdvertisement(@Param('adsId') adsId: number) {
    const data = await this.advertisementService.getDetail(adsId);
    return plainToInstance(GetAdvertisementDto, data, {
      excludeExtraneousValues: true,
    });
  }

  @Get('statis/:adsId')
  @ApiOperation({
    summary: '광고 상세(통계 탭)',
  })
  @ApiOkResponse({ type: GetAdvertisementStaticsResponseDto })
  async getStatis(
    @Param('adsId') adsId: number,
    @Query() query: GetAdvertisementStatisDto,
  ) {
    const data = await this.advertisementService.getAdvertisementStatis(
      adsId,
      query.dateType,
      query.year,
      query.month,
    );

    return plainToInstance(GetAdvertisementStaticsResponseDto, data, {
      excludeExtraneousValues: true,
    });
  }

  @Post()
  @ApiOperation({
    summary: '광고 신규등록',
  })
  @ApiConsumes('multipart/form-data')
  @ApiExtraModels(CreateAdvertisementDto)
  @ApiBody({
    description: '광고 등록 정보',
    schema: {
      type: 'object',
      properties: {
        adsImg: { type: 'string', format: 'binary', nullable: false },
        advertisementData: {
          allOf: [{ $ref: getSchemaPath(CreateAdvertisementDto) }],
        },
      },
    },
  })
  @UseInterceptors(
    FileFieldsInterceptor([{ name: 'adsImg', maxCount: 1 }], {
      fileFilter: fileOriginNameFilter,
    }),
  )
  async createAdvertisement(
    @UploadedFiles() files: Express.Multer.File[],
    @Body('advertisementData') advertisementData: string,
  ) {
    await this.advertisementService.createAdvertisement(
      advertisementData,
      files,
    );
    return;
  }

  @Post('edit/:adsId')
  @ApiOperation({
    summary: '광고 수정',
  })
  @ApiConsumes('multipart/form-data')
  @ApiExtraModels(UpdateAdvertisementDto)
  @ApiBody({
    description: '광고 수정 정보',
    schema: {
      type: 'object',
      properties: {
        adsImg: { type: 'string', format: 'binary', nullable: false },
        advertisementData: {
          allOf: [{ $ref: getSchemaPath(UpdateAdvertisementDto) }],
        },
      },
    },
  })
  @UseInterceptors(
    FileFieldsInterceptor([{ name: 'adsImg', maxCount: 1 }], {
      fileFilter: fileOriginNameFilter,
    }),
  )
  async updateAdvertisement(
    @UploadedFiles() files: Express.Multer.File[],
    @Param('adsId') adsId: number,
    @Body('advertisementData') advertisementData: string,
  ) {
    await this.advertisementService.updateAdvertisement(
      adsId,
      advertisementData,
      files,
    );
    return;
  }

  @Post('delete')
  @ApiOperation({
    summary: '광고 삭제',
  })
  async deleteAdvertisement(@Body() body: DeleteAdvertisementDto) {
    await this.advertisementService.deleteAdvertisement(body);
  }
}
