import { Body, Controller, Delete, Get, Param, Patch, Post, Query, UseGuards } from '@nestjs/common';
import {
  ApiBearerAuth,
  ApiOperation,
  ApiParam,
  ApiTags,
} from '@nestjs/swagger';
import { AppPermission } from '@aechr/shared';
import { CurrentUser } from '../../common/decorators/current-user.decorator';
import { Permissions as PermissionsDecorator } from '../../common/decorators/permissions.decorator';
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
import type { JwtAuthUser } from '../../common/interfaces/jwt-auth-user.interface';
import { ApiJwtErrorResponses } from '../../common/swagger/api-error-responses.decorator';
import {
  ApiEnvelopeCreatedResponse,
  ApiEnvelopeOkResponse,
  ApiPaginatedEnvelopeOkResponse,
} from '../../common/swagger/api-success-responses.decorator';
import {
  CampaignDetailResponseDto,
  CampaignResponseDto,
} from '../../common/swagger/response-models.dto';
import { CampaignsService } from './campaigns.service';
import { CampaignQueryDto } from './dto/campaign-query.dto';
import { CreateCampaignDto } from './dto/create-campaign.dto';
import { GenerateMonthlyCampaignDto } from './dto/generate-monthly-campaign.dto';
import { UpdateCampaignDto } from './dto/update-campaign.dto';

@ApiTags('Campaigns')
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Controller('campaigns')
export class CampaignsController {
  constructor(private readonly campaignsService: CampaignsService) {}

  @Get()
  @PermissionsDecorator(AppPermission.CAMPAIGNS_READ)
  @ApiOperation({ summary: 'List campaigns' })
  @ApiPaginatedEnvelopeOkResponse(CampaignResponseDto, 'Paginated campaign list')
  @ApiJwtErrorResponses()
  list(@Query() query: CampaignQueryDto) {
    return this.campaignsService.list(query);
  }

  @Post()
  @PermissionsDecorator(AppPermission.CAMPAIGNS_WRITE)
  @ApiOperation({ summary: 'Create campaign' })
  @ApiEnvelopeCreatedResponse(CampaignResponseDto, 'Campaign created successfully')
  @ApiJwtErrorResponses({
    conflict: 'Campaign already exists for the requested assessment period',
    notFound: 'Referenced template was not found',
  })
  create(@Body() body: CreateCampaignDto, @CurrentUser() user: JwtAuthUser) {
    return this.campaignsService.create(body, user);
  }

  @Get(':id')
  @PermissionsDecorator(AppPermission.CAMPAIGNS_READ)
  @ApiOperation({ summary: 'Get campaign detail' })
  @ApiParam({ name: 'id', description: 'Campaign identifier' })
  @ApiEnvelopeOkResponse(CampaignDetailResponseDto, 'Campaign detail')
  @ApiJwtErrorResponses({ notFound: 'Campaign was not found' })
  findOne(@Param('id') id: string) {
    return this.campaignsService.findOne(id);
  }

  @Patch(':id')
  @PermissionsDecorator(AppPermission.CAMPAIGNS_WRITE)
  @ApiOperation({ summary: 'Update campaign' })
  @ApiParam({ name: 'id', description: 'Campaign identifier' })
  @ApiEnvelopeOkResponse(CampaignResponseDto, 'Campaign updated successfully')
  @ApiJwtErrorResponses({
    conflict: 'Campaign update conflicts with an existing assessment period',
    notFound: 'Campaign or referenced template was not found',
  })
  update(@Param('id') id: string, @Body() body: UpdateCampaignDto, @CurrentUser() user: JwtAuthUser) {
    return this.campaignsService.update(id, body, user);
  }

  @Delete(':id')
  @PermissionsDecorator(AppPermission.CAMPAIGNS_WRITE)
  @ApiOperation({ summary: 'Soft delete campaign' })
  @ApiParam({ name: 'id', description: 'Campaign identifier' })
  @ApiEnvelopeOkResponse(CampaignResponseDto, 'Campaign deleted successfully')
  @ApiJwtErrorResponses({ notFound: 'Campaign was not found' })
  remove(@Param('id') id: string, @CurrentUser() user: JwtAuthUser) {
    return this.campaignsService.remove(id, user);
  }

  @Patch(':id/restore')
  @PermissionsDecorator(AppPermission.CAMPAIGNS_WRITE)
  @ApiOperation({ summary: 'Restore soft-deleted campaign' })
  @ApiParam({ name: 'id', description: 'Campaign identifier' })
  @ApiEnvelopeOkResponse(CampaignResponseDto, 'Campaign restored successfully')
  @ApiJwtErrorResponses({ notFound: 'Campaign was not found' })
  restore(@Param('id') id: string, @CurrentUser() user: JwtAuthUser) {
    return this.campaignsService.restore(id, user);
  }

  @Post('generate-monthly')
  @PermissionsDecorator(AppPermission.CAMPAIGNS_WRITE)
  @ApiOperation({ summary: 'Generate the monthly campaign for a period' })
  @ApiEnvelopeCreatedResponse(CampaignResponseDto, 'Monthly campaign generated successfully')
  @ApiJwtErrorResponses({
    conflict: 'A monthly campaign already exists for the requested period',
    notFound: 'No active monthly template was found for generation',
  })
  generateMonthly(@Body() body: GenerateMonthlyCampaignDto, @CurrentUser() user: JwtAuthUser) {
    return this.campaignsService.generateMonthly(body, user);
  }
}
