package com.airlock.iam.plugin.configeditor.session;

import com.airlock.iam.admin.domain.model.administrator.permissions.AdminappAction;
import com.airlock.iam.common.api.domain.model.authentication.Authentee;
import com.airlock.iam.core.misc.authorization.AccessController;
import com.airlock.iam.core.misc.authorization.AccessControllerException;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServletRequest;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.Map;
import org.apache.commons.lang3.Strings;

public final class VaadinAccessControl {
   private static final ELogger LOG = ELoggerFactory.getLogger(VaadinAccessControl.class);
   private final HasAccessController parentApp;
   private final Map<String, Collection<AdminappAction>> pathToActions;

   public static VaadinAccessControl vaadinAccessControl(HasAccessController parentApp, Map<String, Collection<AdminappAction>> pathToActions) {
      return new VaadinAccessControl(parentApp, pathToActions);
   }

   public boolean canAccess(VaadinRequest request, Authentee authentee) {
      HttpServletRequest httpServletRequest = ((VaadinServletRequest)request).getHttpServletRequest();
      String requestUri = httpServletRequest.getRequestURI();
      String contextPath = httpServletRequest.getContextPath();
      String path = Strings.CS.removeStart(requestUri, contextPath);
      return this.canAccess(path, authentee);
   }

   private boolean canAccess(String path, Authentee authentee) {
      Collection<AdminappAction> requiredPermissions = this.pathToActions.get(path);
      if (requiredPermissions == null) {
         return false;
      }

      AccessController ac = this.parentApp.accessController();

      for (AdminappAction requiredPermission : requiredPermissions) {
         try {
            if (ac.isActionAllowedFor(requiredPermission.name(), authentee)) {
               return true;
            }
         } catch (AccessControllerException e) {
            throw new IllegalStateException("Error occurred during access control decision.", e);
         }
      }

      LOG.debug("Denying access to " + path + "  because user '" + authentee.userIdentity().id() + "' has none of roles for " + requiredPermissions);
      return false;
   }

   @SuppressFBWarnings(justification = "generated code")
   private VaadinAccessControl(HasAccessController parentApp, Map<String, Collection<AdminappAction>> pathToActions) {
      this.parentApp = parentApp;
      this.pathToActions = pathToActions;
   }
}
