import { logError } from "@/lib/logger";
import { createConsoleUserRolesToken } from "@/lib/session";
import { TConsoleUserRolesServices } from "../console-user-roles/console-user-roles.services";
import { TConsoleUserServices } from "../console-users/console-users.services";
import { TConsoleRolePrivilegesRepository } from "./console-role-privileges.repository";

type TConsoleRolePrivilegesServicesDeps = {
  ConsoleRolePrivilegesRepository: TConsoleRolePrivilegesRepository;
  ConsoleUserRolesServices: TConsoleUserRolesServices;
  ConsoleUserServices: TConsoleUserServices;
};

export const ConsoleRolePrivilegesServices = ({
  ConsoleRolePrivilegesRepository,
  ConsoleUserRolesServices,
  ConsoleUserServices,
}: TConsoleRolePrivilegesServicesDeps) => {
  const FindRolePrivilegesByRoleId = async (roleId: string | string[]) => {
    try {
      const records =
        await ConsoleRolePrivilegesRepository.FindEntriesByRoleId(roleId);
      return records;
    } catch (err) {
      logError(err);
      throw new Error(
        (err as Error).message ?? "Failed finding role privileges by roleId",
      );
    }
  };

  const CreateRolePrivilegesToken = async (userId: string) => {
    try {
      const userRoles =
        await ConsoleUserRolesServices.FindUserRolesByUserId(userId);
      const user = await ConsoleUserServices.GetUserById(userId);
      if (userRoles.length === 0) {
        if (user.is_super_admin) {
          const { roleToken } = await createConsoleUserRolesToken(
            [],
            user.is_super_admin,
          );
          return { roleToken };
        } else return;
      }
      const roleIds = userRoles.map((role) => role.console_role_id);
      const rolePrivileges =
        await ConsoleRolePrivilegesRepository.FindEntriesByRoleId(roleIds);

      // Merge privileges by feature_slug from multiple roles
      const mergedPrivileges: Record<string, any> = {};
      rolePrivileges.forEach((rp: any) => {
          if (!mergedPrivileges[rp.feature_slug]) {
              mergedPrivileges[rp.feature_slug] = {
                  feature_slug: rp.feature_slug,
                  create: rp.create,
                  read: rp.read,
                  update: rp.update,
                  delete: rp.delete
              };
          } else {
              const m = mergedPrivileges[rp.feature_slug];
              m.create = m.create || rp.create;
              m.read = m.read || rp.read;
              m.update = m.update || rp.update;
              m.delete = m.delete || rp.delete;
          }
      });

      const finalScopes = Object.values(mergedPrivileges).filter(
        (rp: any) => rp.create || rp.read || rp.update || rp.delete,
      );

      const { roleToken } = await createConsoleUserRolesToken(
        finalScopes,
        user.is_super_admin,
      );
      return { roleToken };
    } catch (err) {
      logError(err);
      throw new Error(
        (err as Error).message ?? "Failed creating role privileges token",
      );
    }
  };

  return {
    FindRolePrivilegesByRoleId,
    CreateRolePrivilegesToken,
  };
};

export type TConsoleRolePrivilegesServices = ReturnType<
  typeof ConsoleRolePrivilegesServices
>;
