import { Injectable } from "@nestjs/common"
import { RolePermissionRepository } from "../repositories/role-permission.repository"
import { CreateRolePermissionDto } from "../dto/create-role-permission.dto"
import { failureResponse, successResponse } from "src/common/response/response"
import { RolePermission } from "../entities/role-permission.entity"
import { messageKey } from "src/constants/message-keys"
import { FindAllRolePermissionDto } from "../dto/find-all-role-permission.dto"
import { UpdateRolePermissionDto } from "../dto/update-role-permission.dto"
import { Role } from "../../role/entities/role.entity"
import { Modules } from "../../module/entities/module.entity"
import { Permission } from "../../permission/entities/permission.entity"
import { code } from "src/common/response/response.code"
import { messages } from "src/constants/messages"

@Injectable()
export class RolePermissionService {
  constructor(
    private readonly rolePermissionRepository: RolePermissionRepository,
  ) {}

  async checkRolePermissionExist(
    role_id: number,
    module_id: number,
    permission_id: number,
  ): Promise<RolePermission | null> {
    return (await this.rolePermissionRepository.getByParams({
      where: {
        role_id,
        module_id,
        permission_id,
      },
      findOne: true,
    })) as RolePermission | null
  }

  async createRolePermissionBulk(dtos: CreateRolePermissionDto[]) {
    const results = []

    for (const dto of dtos) {
      const existingRecord: any =
        await this.rolePermissionRepository.getByParams({
          where: {
            role_id: dto.role_id,
            module_id: dto.module_id,
          },
          findOne: true,
        })

      if (existingRecord) {
        existingRecord.permission_id = dto.permission_id
        const updated = await this.rolePermissionRepository.save(existingRecord)
        results.push(updated)
      } else {
        const newRecord: Partial<RolePermission> = {
          role_id: dto.role_id,
          module_id: dto.module_id,
          permission_id: dto.permission_id,
        }
        const created = await this.rolePermissionRepository.save(newRecord)

        results.push(created)
      }
    }

    return successResponse(code.CREATED, messages.success.data_add, results)
  }

  async findAllRolePermissions(params: FindAllRolePermissionDto) {
    try {
      const rolePermissions =
        await this.rolePermissionRepository.getFullRolePermissions(params)

      return successResponse(
        code.SUCCESS,
        messages.success.data_retrieve,
        rolePermissions,
      )
    } catch (error) {
      return failureResponse(code.ERROR, messages.error.something_went_wrong)
    }
  }

  async findOneRolePermission(roleId: number, moduleId: number) {
    try {
      // Call the method with both roleId and moduleId
      const rolePermission =
        await this.rolePermissionRepository.findOneRolePermissionByRoleIdAndModuleId(
          roleId,
          moduleId,
        )

      return successResponse(
        code.SUCCESS,
        messages.success.data_retrieve,
        rolePermission,
      )
    } catch (error) {
      return failureResponse(code.ERROR, messages.error.something_went_wrong)
    }
  }

  async updateRolePermission(id: number, updateDto: UpdateRolePermissionDto) {
    const rolePermission = (await this.rolePermissionRepository.getByParams({
      where: { id },
      findOne: true,
    })) as RolePermission

    if (!rolePermission) {
      return failureResponse(404, messageKey.data_not_found)
    }

    const isExist = await this.checkRolePermissionExist(
      updateDto.role_id,
      updateDto.module_id,
      updateDto.permission_id,
    )

    if (isExist && isExist.id !== id) {
      return failureResponse(400, messageKey.already_exist)
    }

    rolePermission.role = { id: updateDto.role_id } as Role
    rolePermission.module = { id: updateDto.module_id } as Modules
    rolePermission.permission = { id: updateDto.permission_id } as Permission

    return await this.rolePermissionRepository.save(rolePermission)
  }

  async remove(id: number) {
    const rolePermission = (await this.rolePermissionRepository.getByParams({
      where: { id },
      findOne: true,
    })) as RolePermission

    if (!rolePermission) {
      return failureResponse(404, messageKey.data_not_found)
    }

    await this.rolePermissionRepository.remove({ id })

    return { success: true, code: 200, message: messageKey.data_removed }
  }
}
