import { Controller, Get, Post, Put, Delete, Param, Query, Body, HttpCode, HttpStatus, Logger, UseGuards } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiQuery, ApiBody, ApiBearerAuth } from '@nestjs/swagger';
import { PermissionService } from './permission.service';
import { PaginatedPermissionResponseDto, PermissionResponseDto } from './dto/permission-response.dto';
import { CreatePermissionDto } from './dto/create-permission.dto';
import { UpdatePermissionDto } from './dto/update-permission.dto';
import { JwtAuthGuard } from 'common/guards/jwt-auth.guard';
import { RolesGuard } from 'common/guards/roles.guard';
import { Roles } from 'common/decorators/role.decorator';
import { UserRole } from 'common/enum/UserRole.enum';
import { CreateSubPermissionDto } from './dto/create-sub-permisison.dto';
import { SubPermissionEntity } from './entities/sub-permission.entity';
import { UpdateSubPermissionDto } from './dto/update-sub-permission.dto';

@ApiTags('Permissions')
@ApiBearerAuth()
@Controller({ path: 'permissions', version: '1' })
@UseGuards(JwtAuthGuard, RolesGuard)
export class PermissionController {
  private readonly logger = new Logger(PermissionController.name);
  constructor(private readonly permissionService: PermissionService) {}

  @Post()
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN)
  // @Permissions('CREATE_PERMISSION')
  @ApiOperation({ summary: 'Create a new permission' })
  @ApiResponse({
    status: HttpStatus.CREATED,
    description: 'Permission created successfully',
    type: PermissionResponseDto,
  })
  @ApiResponse({
    status: HttpStatus.CONFLICT,
    description: 'Permission with the same name already exists',
  })
  @ApiResponse({
    status: HttpStatus.BAD_REQUEST,
    description: 'Invalid input data',
  })
  @ApiBody({ type: CreatePermissionDto })
  async createPermission(@Body() createPermissionDto: CreatePermissionDto): Promise<PermissionResponseDto> {
    return this.permissionService.createPermission(createPermissionDto);
  }

  @Put(':id')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN)
  @ApiOperation({ summary: 'Update a permission' })
  @ApiResponse({
    status: HttpStatus.OK,
    description: 'Permission updated successfully',
    type: PermissionResponseDto,
  })
  @ApiResponse({
    status: HttpStatus.NOT_FOUND,
    description: 'Permission not found',
  })
  @ApiResponse({
    status: HttpStatus.CONFLICT,
    description: 'Permission with the same name already exists',
  })
  @ApiResponse({
    status: HttpStatus.BAD_REQUEST,
    description: 'Cannot modify system permission properties',
  })
  @ApiParam({ name: 'id', description: 'Permission ID', type: Number })
  @ApiBody({ type: UpdatePermissionDto })
  async updatePermission(@Param('id') id: string, @Body() updatePermissionDto: UpdatePermissionDto): Promise<PermissionResponseDto> {
    return this.permissionService.updatePermission(id, updatePermissionDto);
  }

  @Delete(':id')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN)
  @HttpCode(HttpStatus.NO_CONTENT)
  @ApiOperation({ summary: 'Delete a permission' })
  @ApiResponse({
    status: HttpStatus.NO_CONTENT,
    description: 'Permission deleted successfully',
  })
  @ApiResponse({
    status: HttpStatus.NOT_FOUND,
    description: 'Permission not found',
  })
  @ApiResponse({
    status: HttpStatus.BAD_REQUEST,
    description: 'Cannot delete system permission or permission in use',
  })
  @ApiParam({ name: 'id', description: 'Permission ID', type: Number })
  async deletePermission(@Param('id') id: string): Promise<void> {
    await this.permissionService.deletePermission(id);
  }

  @Get('fetch-all')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN, UserRole.CLIENT)
  @ApiOperation({ summary: 'Get all permissions with pagination' })
  @ApiResponse({
    status: HttpStatus.OK,
    description: 'List of permissions',
    type: PaginatedPermissionResponseDto,
  })
  async findAllClientPermissions(): Promise<PermissionResponseDto[]> {
    return this.permissionService.findAllClientPermissions();
  }

  @Get(':id')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN, UserRole.CLIENT, UserRole.USER)
  @ApiOperation({ summary: 'Get a permission by ID' })
  @ApiResponse({
    status: HttpStatus.OK,
    description: 'Permission details',
    type: PermissionResponseDto,
  })
  @ApiResponse({
    status: HttpStatus.NOT_FOUND,
    description: 'Permission not found',
  })
  @ApiParam({ name: 'id', description: 'Permission ID', type: Number })
  async findPermissionById(@Param('id') id: string): Promise<PermissionResponseDto> {
    return this.permissionService.findPermissionById(id);
  }

  @Get('name/:name')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN, UserRole.CLIENT, UserRole.USER)
  @ApiOperation({ summary: 'Get a permission by name' })
  @ApiResponse({
    status: HttpStatus.OK,
    description: 'Permission details',
    type: PermissionResponseDto,
  })
  @ApiResponse({
    status: HttpStatus.NOT_FOUND,
    description: 'Permission not found',
  })
  @ApiParam({ name: 'name', description: 'Permission name', type: String })
  async findPermissionByName(@Param('name') name: string): Promise<PermissionResponseDto> {
    return this.permissionService.findPermissionByName(name);
  }

  @Get('role/:roleId')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN, UserRole.CLIENT)
  @ApiOperation({ summary: 'Get permissions by role ID with pagination' })
  @ApiResponse({
    status: HttpStatus.OK,
    description: 'List of role permissions',
    type: PaginatedPermissionResponseDto,
  })
  @ApiResponse({
    status: HttpStatus.NOT_FOUND,
    description: 'Role not found',
  })
  @ApiParam({ name: 'roleId', description: 'Role ID', type: Number })
  @ApiQuery({
    name: 'page',
    required: false,
    description: 'Page number (default: 1)',
    type: Number,
  })
  @ApiQuery({
    name: 'limit',
    required: false,
    description: 'Items per page (default: 10)',
    type: Number,
  })
  async getPermissionsByRoleId(
    @Param('roleId') roleId: string,
    @Query('page') page = 1,
    @Query('limit') limit = 10,
  ): Promise<PaginatedPermissionResponseDto> {
    return this.permissionService.getPermissionsByRoleId(roleId, page, limit);
  }

  @Get('role/name/:roleName')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN, UserRole.CLIENT)
  @ApiOperation({ summary: 'Get permissions by role name with pagination' })
  @ApiResponse({
    status: HttpStatus.OK,
    description: 'List of role permissions',
    type: PaginatedPermissionResponseDto,
  })
  @ApiResponse({
    status: HttpStatus.NOT_FOUND,
    description: 'Role not found',
  })
  @ApiParam({ name: 'roleName', description: 'Role name', type: String })
  @ApiQuery({
    name: 'page',
    required: false,
    description: 'Page number (default: 1)',
    type: Number,
  })
  @ApiQuery({
    name: 'limit',
    required: false,
    description: 'Items per page (default: 10)',
    type: Number,
  })
  async getPermissionsByRoleName(
    @Param('roleName') roleName: string,
    @Query('page') page = 1,
    @Query('limit') limit = 10,
  ): Promise<PaginatedPermissionResponseDto> {
    return this.permissionService.getPermissionsByRoleName(roleName, page, limit);
  }

  @Delete('role/:roleId/permissions')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN, UserRole.CLIENT)
  @HttpCode(HttpStatus.NO_CONTENT)
  @ApiOperation({ summary: 'Remove permissions from a role' })
  @ApiResponse({
    status: HttpStatus.NO_CONTENT,
    description: 'Permissions removed from role successfully',
  })
  @ApiResponse({
    status: HttpStatus.NOT_FOUND,
    description: 'Role or permissions not found',
  })
  @ApiParam({ name: 'roleId', description: 'Role ID', type: Number })
  @ApiBody({
    description: 'Array of permission IDs to remove',
    type: [Number],
  })
  async removePermissionsFromRole(@Param('roleId') roleId: string, @Body() permissionIds: string[]): Promise<void> {
    await this.permissionService.removePermissionsFromRole(roleId, permissionIds);
  }

  // Create sub-permission
  @Post('sub-permissions')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN)
  @ApiOperation({ summary: 'Create a new sub-permission' })
  @ApiResponse({
    status: HttpStatus.CREATED,
    description: 'Sub-permission created successfully',
    type: PermissionResponseDto,
  })
  @ApiResponse({
    status: HttpStatus.CONFLICT,
    description: 'Sub-permission with the same name already exists',
  })
  @ApiResponse({
    status: HttpStatus.BAD_REQUEST,
    description: 'Invalid input data',
  })
  @ApiBody({ type: CreateSubPermissionDto })
  async createSubPermission(@Body() createSubPermissionDto: CreateSubPermissionDto): Promise<PermissionResponseDto> {
    return this.permissionService.createSubPermission(createSubPermissionDto);
  }

  @Put('sub-permissions/:id')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN)
  @ApiOperation({ summary: 'Update a sub-permission' })
  @ApiResponse({
    status: HttpStatus.OK,
    description: 'Sub-permission updated successfully',
    type: SubPermissionEntity,
  })
  @ApiResponse({
    status: HttpStatus.NOT_FOUND,
    description: 'Sub-permission not found',
  })
  @ApiResponse({
    status: HttpStatus.CONFLICT,
    description: 'Sub-permission with the same name already exists',
  })
  @ApiResponse({
    status: HttpStatus.BAD_REQUEST,
    description: 'Cannot modify system sub-permission properties',
  })
  @ApiParam({ name: 'id', description: 'Sub-permission ID', type: String })
  @ApiBody({ type: UpdateSubPermissionDto })
  async updateSubPermission(@Param('id') id: string, @Body() updateSubPermissionDto: UpdateSubPermissionDto): Promise<PermissionResponseDto> {
    return this.permissionService.updateSubPermission(id, updateSubPermissionDto);
  }
  @Delete('sub-permissions/:id')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN)
  @HttpCode(HttpStatus.NO_CONTENT)
  @ApiOperation({ summary: 'Delete a sub-permission' })
  @ApiResponse({
    status: HttpStatus.NO_CONTENT,
    description: 'Sub-permission deleted successfully',
  })
  @ApiResponse({
    status: HttpStatus.NOT_FOUND,
    description: 'Sub-permission not found',
  })
  @ApiResponse({
    status: HttpStatus.BAD_REQUEST,
    description: 'Cannot delete system sub-permission or sub-permission in use',
  })
  @ApiParam({ name: 'id', description: 'Sub-permission ID', type: String })
  async deleteSubPermission(@Param('id') id: string): Promise<void> {
    await this.permissionService.deleteSubPermission(id);
  }

  @Get('sub-permissions/:id')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN, UserRole.CLIENT, UserRole.USER)
  @ApiOperation({ summary: 'Get a sub-permission by ID' })
  @ApiResponse({
    status: HttpStatus.OK,
    description: 'Sub-permission details',
    type: PermissionResponseDto,
  })
  @ApiResponse({
    status: HttpStatus.NOT_FOUND,
    description: 'Sub-permission not found',
  })
  @ApiParam({ name: 'id', description: 'Sub-permission ID', type: String })
  async findSubPermissionById(@Param('id') id: string): Promise<PermissionResponseDto> {
    return this.permissionService.findSubPermissionById(id);
  }

  @Get('sub-permissions/name/:name')
  @Roles(UserRole.SUPER_ADMIN, UserRole.ADMIN, UserRole.CLIENT, UserRole.USER)
  @ApiOperation({ summary: 'Get a sub-permission by name' })
  @ApiResponse({
    status: HttpStatus.OK,
    description: 'Sub-permission details',
    type: PermissionResponseDto,
  })
  @ApiResponse({
    status: HttpStatus.NOT_FOUND,
    description: 'Sub-permission not found',
  })
  @ApiParam({ name: 'name', description: 'Sub-permission name', type: String })
  async findSubPermissionByName(@Param('name') name: string): Promise<PermissionResponseDto> {
    return this.permissionService.findSubPermissionByName(name);
  }
}
