import { Body, Controller, 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 {
  ApiArrayEnvelopeOkResponse,
  ApiEnvelopeOkResponse,
  ApiPaginatedEnvelopeOkResponse,
} from '../../common/swagger/api-success-responses.decorator';
import {
  AssignmentDetailResponseDto,
  AssignmentResponseDto,
} from '../../common/swagger/response-models.dto';
import { AssignmentsService } from './assignments.service';
import { AssignmentQueryDto } from './dto/assignment-query.dto';
import { BulkAssignmentsDto } from './dto/bulk-assignments.dto';
import { ReopenAssignmentDto } from './dto/reopen-assignment.dto';

@ApiTags('Assignments')
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Controller('assignments')
export class AssignmentsController {
  constructor(private readonly assignmentsService: AssignmentsService) {}

  @Get()
  @PermissionsDecorator(AppPermission.ASSIGNMENTS_READ)
  @ApiOperation({ summary: 'List assignments' })
  @ApiPaginatedEnvelopeOkResponse(AssignmentResponseDto, 'Paginated assignment list')
  @ApiJwtErrorResponses()
  list(@Query() query: AssignmentQueryDto) {
    return this.assignmentsService.list(query);
  }

  @Get('me')
  @ApiOperation({ summary: 'List current user assignments' })
  @ApiArrayEnvelopeOkResponse(
    AssignmentResponseDto,
    'Assignments visible to the authenticated employee',
  )
  @ApiJwtErrorResponses({ forbidden: 'Authenticated user is not allowed to access assignment data' })
  mine(@CurrentUser() user: JwtAuthUser) {
    return this.assignmentsService.mine(user);
  }

  @Get(':id')
  @PermissionsDecorator(AppPermission.ASSIGNMENTS_READ)
  @ApiOperation({ summary: 'Get assignment detail' })
  @ApiParam({ name: 'id', description: 'Assignment identifier' })
  @ApiEnvelopeOkResponse(AssignmentDetailResponseDto, 'Assignment detail')
  @ApiJwtErrorResponses({ notFound: 'Assignment was not found' })
  findOne(@Param('id') id: string) {
    return this.assignmentsService.findOne(id);
  }

  @Post('bulk')
  @PermissionsDecorator(AppPermission.ASSIGNMENTS_WRITE)
  @ApiOperation({ summary: 'Create assignments in bulk' })
  @ApiArrayEnvelopeOkResponse(
    AssignmentResponseDto,
    'Assignments created for the provided campaign and employees',
  )
  @ApiJwtErrorResponses({
    conflict: 'One or more assignments already exist for the same campaign and employee',
    notFound: 'Campaign or employee was not found',
  })
  bulkAssign(@Body() body: BulkAssignmentsDto, @CurrentUser() user: JwtAuthUser) {
    return this.assignmentsService.bulkAssign(body, user);
  }

  @Patch(':id/enable')
  @PermissionsDecorator(AppPermission.ASSIGNMENTS_WRITE)
  @ApiOperation({ summary: 'Enable assignment' })
  @ApiParam({ name: 'id', description: 'Assignment identifier' })
  @ApiEnvelopeOkResponse(AssignmentResponseDto, 'Assignment enabled successfully')
  @ApiJwtErrorResponses({ notFound: 'Assignment was not found' })
  enable(@Param('id') id: string, @CurrentUser() user: JwtAuthUser) {
    return this.assignmentsService.enable(id, user);
  }

  @Patch(':id/disable')
  @PermissionsDecorator(AppPermission.ASSIGNMENTS_WRITE)
  @ApiOperation({ summary: 'Disable assignment' })
  @ApiParam({ name: 'id', description: 'Assignment identifier' })
  @ApiEnvelopeOkResponse(AssignmentResponseDto, 'Assignment disabled successfully')
  @ApiJwtErrorResponses({ notFound: 'Assignment was not found' })
  disable(@Param('id') id: string, @CurrentUser() user: JwtAuthUser) {
    return this.assignmentsService.disable(id, user);
  }

  @Patch(':id/reopen')
  @PermissionsDecorator(AppPermission.ASSIGNMENTS_WRITE)
  @ApiOperation({ summary: 'Reopen assignment' })
  @ApiParam({ name: 'id', description: 'Assignment identifier' })
  @ApiEnvelopeOkResponse(AssignmentResponseDto, 'Assignment reopened successfully')
  @ApiJwtErrorResponses({ notFound: 'Assignment was not found' })
  reopen(@Param('id') id: string, @Body() body: ReopenAssignmentDto, @CurrentUser() user: JwtAuthUser) {
    return this.assignmentsService.reopen(id, body, user);
  }
}
