package com.airlock.iam.saml2.infrastructure.plugin.configuration;

import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.airlock.iam.opensso.jaxb.entityconfig.BaseConfigType;
import com.airlock.iam.opensso.jaxb.entityconfig.EntityConfigElement;
import com.airlock.iam.opensso.jaxb.entityconfig.EntityConfigType;
import com.airlock.iam.saml2.domain.model.logging.Saml2LogTypes;
import com.sun.identity.plugin.configuration.ConfigurationException;
import com.sun.identity.saml2.common.SAML2Utils;
import com.sun.identity.saml2.meta.SAML2MetaException;
import com.sun.identity.saml2.meta.SAML2MetaManager;
import com.sun.identity.saml2.meta.SAML2MetaUtils;
import jakarta.xml.bind.JAXBElement;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

public final class FlowCircleOfTrustConfiguration extends InitializableConfiguration {
   private static final ELogger LOG = ELoggerFactory.getLogger(FlowCircleOfTrustConfiguration.class);

   public FlowCircleOfTrustConfiguration() {
      super("LIBCOT");
   }

   @Override
   protected void initializeConfiguration() throws ConfigurationException {
      LOG.debug("Initializing COT Configuration...");

      SAML2MetaManager metaManager;
      try {
         metaManager = SAML2Utils.getSAML2MetaManager();
      } catch (Exception e) {
         LOG.error(Saml2LogTypes.FEDERATION_LIBRARY_MESSAGE, "Error initializing SAML2 Meta Manager: " + e.getMessage(), e);
         throw new ConfigurationException(e);
      }

      Map<String, Set<String>> entitiesByCot = new HashMap<>();

      try {
         for (String entityID : metaManager.getAllEntities("/")) {
            for (String cotName : getCotsByEntityID(entityID, metaManager)) {
               Set<String> entitySet = entitiesByCot.get(cotName);
               if (entitySet == null) {
                  entitySet = new HashSet<>();
               }

               entitySet.add(entityID + "|saml2");
               entitiesByCot.put(cotName, entitySet);
            }
         }
      } catch (SAML2MetaException e) {
         throw new ConfigurationException(e);
      }

      for (Entry<String, Set<String>> entry : entitiesByCot.entrySet()) {
         String cotName = entry.getKey();
         Map<String, Set<String>> cotConfigMap = (Map<String, Set<String>>)this.getConfigMap().get(cotName);
         if (cotConfigMap == null) {
            cotConfigMap = new HashMap<>();
            cotConfigMap.put("sun-fm-trusted-providers", new HashSet<>());
            Set<String> hs = new HashSet<>();
            hs.add("active");
            cotConfigMap.put("sun-fm-cot-status", hs);
            hs = new HashSet<>();
            hs.add("IAM COT");
            cotConfigMap.put("sun-fm-cot-description", hs);
         }

         Set<String> providers = cotConfigMap.get("sun-fm-trusted-providers");
         providers.addAll(entry.getValue());
         this.getConfigMap().put(cotName, cotConfigMap);
      }
   }

   private static Set<String> getCotsByEntityID(String entityID, SAML2MetaManager metaManager) throws SAML2MetaException {
      Set<String> cotList = new HashSet<>();
      EntityConfigElement config = metaManager.getEntityConfig("/", entityID);
      if (config == null) {
         return cotList;
      }

      for (JAXBElement<BaseConfigType> baseConfigType : ((EntityConfigType)config.getValue()).getIDPSSOConfigOrSPSSOConfigOrAuthnAuthorityConfig()) {
         Map attrMap = SAML2MetaUtils.getAttributes((BaseConfigType)baseConfigType.getValue());
         List<String> cots = (List<String>)attrMap.get("cotlist");
         if (cots != null) {
            cotList.addAll(cots);
         }
      }

      return cotList;
   }
}
