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 {
  RoleDetailResponseDto,
  RolePermissionResponseDto,
  RoleResponseDto,
} from '../../common/swagger/response-models.dto';
import { CreateRoleDto } from './dto/create-role.dto';
import { RoleQueryDto } from './dto/role-query.dto';
import { UpdateRolePermissionsDto } from './dto/update-role-permissions.dto';
import { UpdateRoleDto } from './dto/update-role.dto';
import { RolesService } from './roles.service';

@ApiTags('Roles')
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Controller('roles')
export class RolesController {
  constructor(private readonly rolesService: RolesService) {}

  @Get()
  @PermissionsDecorator(AppPermission.ROLES_READ)
  @ApiOperation({ summary: 'List roles' })
  @ApiPaginatedEnvelopeOkResponse(RoleDetailResponseDto, 'Paginated role list')
  @ApiJwtErrorResponses()
  list(@Query() query: RoleQueryDto) {
    return this.rolesService.list(query);
  }

  @Post()
  @PermissionsDecorator(AppPermission.ROLES_WRITE)
  @ApiOperation({ summary: 'Create role' })
  @ApiEnvelopeCreatedResponse(RoleResponseDto, 'Role created successfully')
  @ApiJwtErrorResponses({ conflict: 'Role name or slug already exists' })
  create(@Body() body: CreateRoleDto, @CurrentUser() user: JwtAuthUser) {
    return this.rolesService.create(body, user);
  }

  @Get(':id')
  @PermissionsDecorator(AppPermission.ROLES_READ)
  @ApiOperation({ summary: 'Get role detail' })
  @ApiParam({ name: 'id', description: 'Role identifier' })
  @ApiEnvelopeOkResponse(RoleDetailResponseDto, 'Role detail')
  @ApiJwtErrorResponses({ notFound: 'Role was not found' })
  findOne(@Param('id') id: string) {
    return this.rolesService.findOne(id);
  }

  @Patch(':id')
  @PermissionsDecorator(AppPermission.ROLES_WRITE)
  @ApiOperation({ summary: 'Update role' })
  @ApiParam({ name: 'id', description: 'Role identifier' })
  @ApiEnvelopeOkResponse(RoleResponseDto, 'Role updated successfully')
  @ApiJwtErrorResponses({
    conflict: 'Role name or slug already exists',
    notFound: 'Role was not found',
  })
  update(
    @Param('id') id: string,
    @Body() body: UpdateRoleDto,
    @CurrentUser() user: JwtAuthUser,
  ) {
    return this.rolesService.update(id, body, user);
  }

  @Delete(':id')
  @PermissionsDecorator(AppPermission.ROLES_WRITE)
  @ApiOperation({ summary: 'Soft delete role' })
  @ApiParam({ name: 'id', description: 'Role identifier' })
  @ApiEnvelopeOkResponse(RoleResponseDto, 'Role deleted successfully')
  @ApiJwtErrorResponses({ notFound: 'Role was not found' })
  remove(@Param('id') id: string, @CurrentUser() user: JwtAuthUser) {
    return this.rolesService.remove(id, user);
  }

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

  @Get(':id/permissions')
  @PermissionsDecorator(AppPermission.ROLES_READ)
  @ApiOperation({ summary: 'Get permissions assigned to a role' })
  @ApiParam({ name: 'id', description: 'Role identifier' })
  @ApiArrayEnvelopeOkResponse(RolePermissionResponseDto, 'Role permission list')
  @ApiJwtErrorResponses({ notFound: 'Role was not found' })
  getPermissions(@Param('id') id: string) {
    return this.rolesService.getPermissions(id);
  }

  @Patch(':id/permissions')
  @PermissionsDecorator(AppPermission.ROLES_WRITE)
  @ApiOperation({ summary: 'Replace role permissions' })
  @ApiParam({ name: 'id', description: 'Role identifier' })
  @ApiArrayEnvelopeOkResponse(RolePermissionResponseDto, 'Role permissions updated successfully')
  @ApiJwtErrorResponses({ notFound: 'Role was not found' })
  updatePermissions(
    @Param('id') id: string,
    @Body() body: UpdateRolePermissionsDto,
    @CurrentUser() user: JwtAuthUser,
  ) {
    return this.rolesService.updatePermissions(id, body, user);
  }
}
