package com.airlock.iam.admin.infrastructure.service.settings.provider;

import com.airlock.iam.admin.application.configuration.administrators.AdministratorsManagement;
import com.airlock.iam.admin.application.service.SettingsProvider;
import com.airlock.iam.admin.application.service.settings.AdminDetailSettings;
import com.airlock.iam.admin.application.service.settings.Settings;
import com.airlock.iam.admin.application.service.settings.UserProfileItemSettings;
import com.airlock.iam.admin.application.system.AdminappPage;
import com.airlock.iam.admin.domain.model.administrator.ExtendedCurrentAdministrator;
import com.airlock.iam.admin.infrastructure.service.ProfileItems;
import com.airlock.iam.base.api.infrastructure.plugin.PluginConfigToLogic;
import com.airlock.iam.common.api.domain.model.role.Role;
import com.airlock.iam.common.application.configuration.userprofile.UserProfileItemConfig;
import com.airlock.iam.common.domain.model.role.RoleCombination;
import com.airlock.iam.common.domain.model.role.RolesUtil;
import com.airlock.iam.common.domain.model.user.profileitems.UserProfileItemDetails;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;

public class AdminDetailSettingsProvider implements SettingsProvider {
   private final Optional<AdministratorsManagement> adminConfig;
   private final PluginConfigToLogic toLogic;
   private final ExtendedCurrentAdministrator currentAdministrator;

   @Override
   public AdminappPage page() {
      return AdminappPage.ADMIN_DETAIL;
   }

   @Override
   public Optional<Settings> getSettings() {
      return this.adminConfig.map(this::createAdminDetailSettings);
   }

   private AdminDetailSettings createAdminDetailSettings(AdministratorsManagement config) {
      List<UserProfileItemDetails> profileItems = ProfileItems.asProfileItemDetails(
         config.getRowsOnAdminDetailPage(), UserProfileItemConfig::isModifiable, this.toLogic
      );
      return AdminDetailSettings.builder()
         .adminProfileItems(UserProfileItemSettings.createGeneric(profileItems))
         .availableRoles(this.getAssignableRoleCombinations(config))
         .lockReasons(config.getLockReasons())
         .superAdminRole(config.getSuperAdminRole())
         .enforceRoleCombinations(config.isEnforceRoleCombinations())
         .build();
   }

   private List<String> getAssignableRoleCombinations(AdministratorsManagement config) {
      Set<Role> peparRoles = peparRolesFromConfig(config);
      return config.getAssignableRoleCombinations().stream().filter(this.rolesAdminHasPrivilegeFor(peparRoles)).toList();
   }

   private Predicate<String> rolesAdminHasPrivilegeFor(Set<Role> peparRoles) {
      return assignableRole -> RoleCombination.roleCombination(assignableRole).containsAtLeastOne(peparRoles)
         ? this.currentAdministrator.hasPrivilegeEscalation()
         : true;
   }

   private static Set<Role> peparRolesFromConfig(AdministratorsManagement config) {
      return RolesUtil.rolesFrom(config.getPeparRoles());
   }

   @SuppressFBWarnings(justification = "generated code")
   public AdminDetailSettingsProvider(
      Optional<AdministratorsManagement> adminConfig, PluginConfigToLogic toLogic, ExtendedCurrentAdministrator currentAdministrator
   ) {
      this.adminConfig = adminConfig;
      this.toLogic = toLogic;
      this.currentAdministrator = currentAdministrator;
   }
}
