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 {
  ApiArrayEnvelopeOkResponse,
  ApiEnvelopeCreatedResponse,
  ApiEnvelopeOkResponse,
  ApiPaginatedEnvelopeOkResponse,
} from '../../common/swagger/api-success-responses.decorator';
import {
  TemplateDetailResponseDto,
  TemplateQuestionMappingResponseDto,
  TemplateResponseDto,
} from '../../common/swagger/response-models.dto';
import { AttachTemplateQuestionDto } from './dto/attach-template-question.dto';
import { CreateTemplateDto } from './dto/create-template.dto';
import { ReorderTemplateQuestionsDto } from './dto/reorder-template-questions.dto';
import { TemplateQueryDto } from './dto/template-query.dto';
import { UpdateTemplateDto } from './dto/update-template.dto';
import { TemplatesService } from './templates.service';

@ApiTags('Templates')
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Controller('templates')
export class TemplatesController {
  constructor(private readonly templatesService: TemplatesService) {}

  @Get()
  @PermissionsDecorator(AppPermission.TEMPLATES_READ)
  @ApiOperation({ summary: 'List assessment templates' })
  @ApiPaginatedEnvelopeOkResponse(TemplateResponseDto, 'Paginated template list')
  @ApiJwtErrorResponses()
  list(@Query() query: TemplateQueryDto) {
    return this.templatesService.list(query);
  }

  @Post()
  @PermissionsDecorator(AppPermission.TEMPLATES_WRITE)
  @ApiOperation({ summary: 'Create assessment template' })
  @ApiEnvelopeCreatedResponse(TemplateResponseDto, 'Template created successfully')
  @ApiJwtErrorResponses({ conflict: 'Template code already exists' })
  create(@Body() body: CreateTemplateDto, @CurrentUser() user: JwtAuthUser) {
    return this.templatesService.create(body, user);
  }

  @Get(':id')
  @PermissionsDecorator(AppPermission.TEMPLATES_READ)
  @ApiOperation({ summary: 'Get template detail' })
  @ApiParam({ name: 'id', description: 'Template identifier' })
  @ApiEnvelopeOkResponse(TemplateDetailResponseDto, 'Template detail with mapped questions')
  @ApiJwtErrorResponses({ notFound: 'Template was not found' })
  findOne(@Param('id') id: string) {
    return this.templatesService.findOne(id);
  }

  @Patch(':id')
  @PermissionsDecorator(AppPermission.TEMPLATES_WRITE)
  @ApiOperation({ summary: 'Update assessment template' })
  @ApiParam({ name: 'id', description: 'Template identifier' })
  @ApiEnvelopeOkResponse(TemplateResponseDto, 'Template updated successfully')
  @ApiJwtErrorResponses({
    conflict: 'Template code already exists',
    notFound: 'Template was not found',
  })
  update(
    @Param('id') id: string,
    @Body() body: UpdateTemplateDto,
    @CurrentUser() user: JwtAuthUser,
  ) {
    return this.templatesService.update(id, body, user);
  }

  @Delete(':id')
  @PermissionsDecorator(AppPermission.TEMPLATES_WRITE)
  @ApiOperation({ summary: 'Soft delete assessment template' })
  @ApiParam({ name: 'id', description: 'Template identifier' })
  @ApiEnvelopeOkResponse(TemplateResponseDto, 'Template deleted successfully')
  @ApiJwtErrorResponses({ notFound: 'Template was not found' })
  remove(@Param('id') id: string, @CurrentUser() user: JwtAuthUser) {
    return this.templatesService.remove(id, user);
  }

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

  @Post(':id/questions')
  @PermissionsDecorator(AppPermission.TEMPLATES_WRITE)
  @ApiOperation({ summary: 'Attach question to template' })
  @ApiParam({ name: 'id', description: 'Template identifier' })
  @ApiEnvelopeCreatedResponse(
    TemplateQuestionMappingResponseDto,
    'Question attached to template successfully',
  )
  @ApiJwtErrorResponses({
    conflict: 'Question is already attached to the template',
    notFound: 'Template or question was not found',
  })
  attachQuestion(
    @Param('id') id: string,
    @Body() body: AttachTemplateQuestionDto,
    @CurrentUser() user: JwtAuthUser,
  ) {
    return this.templatesService.attachQuestion(id, body, user);
  }

  @Patch(':id/questions/reorder')
  @PermissionsDecorator(AppPermission.TEMPLATES_WRITE)
  @ApiOperation({ summary: 'Reorder template questions' })
  @ApiParam({ name: 'id', description: 'Template identifier' })
  @ApiArrayEnvelopeOkResponse(
    TemplateQuestionMappingResponseDto,
    'Template question order updated successfully',
  )
  @ApiJwtErrorResponses({ notFound: 'Template or one of the question mappings was not found' })
  reorderQuestions(
    @Param('id') id: string,
    @Body() body: ReorderTemplateQuestionsDto,
    @CurrentUser() user: JwtAuthUser,
  ) {
    return this.templatesService.reorderQuestions(id, body, user);
  }

  @Delete(':id/questions/:mappingId')
  @PermissionsDecorator(AppPermission.TEMPLATES_WRITE)
  @ApiOperation({ summary: 'Remove question from template' })
  @ApiParam({ name: 'id', description: 'Template identifier' })
  @ApiParam({ name: 'mappingId', description: 'Template-question mapping identifier' })
  @ApiEnvelopeOkResponse(
    TemplateQuestionMappingResponseDto,
    'Template question removed successfully',
  )
  @ApiJwtErrorResponses({ notFound: 'Template question mapping was not found' })
  removeQuestion(
    @Param('id') id: string,
    @Param('mappingId') mappingId: string,
    @CurrentUser() user: JwtAuthUser,
  ) {
    return this.templatesService.removeQuestion(id, mappingId, user);
  }

  @Patch(':id/questions/:mappingId/restore')
  @PermissionsDecorator(AppPermission.TEMPLATES_WRITE)
  @ApiOperation({ summary: 'Restore removed template question mapping' })
  @ApiParam({ name: 'id', description: 'Template identifier' })
  @ApiParam({ name: 'mappingId', description: 'Template-question mapping identifier' })
  @ApiEnvelopeOkResponse(
    TemplateQuestionMappingResponseDto,
    'Template question restored successfully',
  )
  @ApiJwtErrorResponses({ notFound: 'Template question mapping was not found' })
  restoreQuestion(
    @Param('id') id: string,
    @Param('mappingId') mappingId: string,
    @CurrentUser() user: JwtAuthUser,
  ) {
    return this.templatesService.restoreQuestion(id, mappingId, user);
  }
}
