package com.airlock.iam.techclientreg.domain.model.step;

import com.airlock.iam.base.api.domain.model.plugin.LogicForConfig;
import com.airlock.iam.base.misc.log.LogUtil;
import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.airlock.iam.elog.api.LogTypes;
import com.airlock.iam.flow.api.domain.model.step.FlowStep;
import com.airlock.iam.flow.api.domain.model.step.StepResult;
import com.airlock.iam.oauth2.api.domain.model.OAuth2ClientId;
import com.airlock.iam.oauth2.domain.model.client.OAuth2Client;
import com.airlock.iam.oauth2.domain.model.client.OAuth2ClientLoader;
import com.airlock.iam.techclient.auth.application.service.oauth2.OAuth2TechClientService;
import com.airlock.iam.techclient.auth.domain.model.oauth2.LoginOAuth2TechClientImpl;
import com.airlock.iam.techclient.auth.domain.model.oauth2.OAuth2TechClient;
import com.airlock.iam.techclientreg.api.domain.model.oauth2.OAuth2ClientRegistrationError;
import com.airlock.iam.techclientreg.application.configuration.step.OAuth2ClientPersistingStepConfig;
import com.airlock.iam.techclientreg.domain.model.flow.RegisteringTechClientFlowAttribute;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.Optional;

@LogicForConfig(OAuth2ClientPersistingStepConfig.class)
public class OAuth2ClientPersistingStep implements FlowStep {
   private static final ELogger LOG = ELoggerFactory.getLogger(OAuth2ClientPersistingStep.class);
   private final Provider<OAuth2ClientLoader> clientLoader;
   private final Provider<RegisteringTechClientFlowAttribute> flowAttribute;
   private final Provider<OAuth2TechClientService> clientService;

   @Inject
   public OAuth2ClientPersistingStep(
      Provider<OAuth2ClientLoader> clientLoader, Provider<RegisteringTechClientFlowAttribute> flowAttribute, Provider<OAuth2TechClientService> clientService
   ) {
      this.clientLoader = clientLoader;
      this.flowAttribute = flowAttribute;
      this.clientService = clientService;
   }

   @Override
   public StepResult initialize() {
      OAuth2TechClient techClient = (LoginOAuth2TechClientImpl)((RegisteringTechClientFlowAttribute)this.flowAttribute.get()).client();
      OAuth2ClientId oauth2ClientId = techClient.getMetadata().getClientId();
      Optional<OAuth2Client> existingClient = ((OAuth2ClientLoader)this.clientLoader.get()).tryLoadClient(oauth2ClientId);
      if (existingClient.isPresent()) {
         LOG.warn(LogTypes.ILLEGAL_ARGUMENT, "Requested Client ID already exists: " + LogUtil.logSafeQuote(oauth2ClientId.id()));
         return this.stepResultFactory()
            .fail(OAuth2ClientRegistrationStep.RegistrationStepError.OAUTH2_CLIENT_REGISTRATION_FAILED)
            .resultData(OAuth2ClientRegistrationError.invalidClientMetadata("Client Id not unique"))
            .build();
      } else {
         LOG.info(
            "Persisting OAuth 2.0 client with technical client identifier "
               + LogUtil.logSafeQuote(techClient.getId())
               + " and OAuth 2.0 Client ID "
               + LogUtil.logSafeQuote(oauth2ClientId.id())
               + "."
         );
         ((OAuth2TechClientService)this.clientService.get()).insert(techClient);
         return this.stepResultFactory().success().build();
      }
   }

   @Override
   public String getDescription() {
      return "OAuth 2.0 Client Persisting Step";
   }
}
