import { Injectable } from "@nestjs/common"
import { InjectRepository } from "@nestjs/typeorm"
import { TeamMember } from "src/modules/team-member/entities/team_member.entity"
import { Repository } from "typeorm"
import { BaseAbstractRepository } from "../../../common/repository/base.repository"
import { FindAllRolesDto } from "../dto/find-all-roles.dto"
import { Role } from "../entities/role.entity"

@Injectable()
export class RoleRepository extends BaseAbstractRepository<Role> {
  constructor(
    @InjectRepository(Role) private readonly roleRepository: Repository<Role>,
    @InjectRepository(TeamMember)
    private readonly teamMemberRepository: Repository<TeamMember>,
  ) {
    super(roleRepository)
  }
  async findAllWithFilters(params: FindAllRolesDto) {
    const validSortColumns = ["id", "name", "created_at", "updated_at"]
    const sortColumn = validSortColumns.includes(params.sortBy)
      ? params.sortBy
      : "created_at"
    const sortOrder: "ASC" | "DESC" = params.sortOrder || "DESC"

    const query = this.roleRepository
      .createQueryBuilder("role")
      .leftJoinAndSelect("role.departments", "departments")
      .leftJoinAndSelect("role.business_verticals", "business_verticals")
      .leftJoinAndSelect("role.parent_role", "parent_role")
      .leftJoinAndSelect("role.team_member", "team_member")

    if (params.search) {
      query.andWhere("role.name ILIKE :search", {
        search: `%${params.search}%`,
      })
    }

    if (params.department_id) {
      const deptIds = params.department_id.split(",").map((id) => +id)
      query.andWhere("departments.id IN (:...deptIds)", { deptIds })
    }

    if (params.business_vertical_id) {
      const bvIds = params.business_vertical_id.split(",").map((id) => +id)
      query.andWhere("business_verticals.id IN (:...bvIds)", { bvIds })
    }

    query
      .orderBy(`role.${sortColumn}`, sortOrder)
      .skip(Number(params.skip))
      .take(Number(params.limit))

    const [data, count] = await query.getManyAndCount()

    const rolesWithMemberCount = data.map((role) => ({
      ...role,
      member_count: role.team_member ? role.team_member.length : 0,
    }))

    return {
      count,
      data: rolesWithMemberCount,
    }
  }
  async findRolesWithDepartmentAndBv(
    roleId: number,
    departmentIds: number[],
    businessVerticalIds: number[],
  ): Promise<boolean> {
    const departmentCount = await this.teamMemberRepository
      .createQueryBuilder("team_member")
      .leftJoin("team_member.department", "department")
      .where("team_member.role_id = :roleId", { roleId })
      .andWhere("department.id IN (:...deptIds)", { deptIds: departmentIds })
      .andWhere("team_member.form_status = 'submitted'")
      .getCount()

    const bvCount = await this.teamMemberRepository
      .createQueryBuilder("team_member")
      .leftJoin("team_member.business_vertical", "bv")
      .where("team_member.role_id = :roleId", { roleId })
      .andWhere("bv.id IN (:...bvIds)", { bvIds: businessVerticalIds })
      .andWhere("team_member.form_status = 'submitted'")
      .getCount()

    return departmentCount > 0 || bvCount > 0
  }
}
