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

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.techclient.api.domain.model.oauth2.OAuth2TechnicalClientMetadataBuilder;
import com.airlock.iam.techclientreg.api.domain.model.oauth2.OAuth2ClientRegistrationError;
import com.airlock.iam.techclientreg.api.domain.model.oauth2.OAuth2ClientRegistrationRequest;
import com.airlock.iam.techclientreg.api.domain.service.oauth2.OAuth2ClientMetadataProcessor;
import com.airlock.iam.techclientreg.application.configuration.registration.SoftwareIdAndVersionProcessorConfig;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import java.util.Optional;

@LogicForConfig(SoftwareIdAndVersionProcessorConfig.class)
public class SoftwareIdAndVersionProcessor implements OAuth2ClientMetadataProcessor {
   private static final ELogger LOG = ELoggerFactory.getLogger(SoftwareIdAndVersionProcessor.class);
   private final Provider<SoftwareIdAndVersionProcessorConfig> config;
   private final ClientMetadataAttributeValidator validator;

   @Inject
   public SoftwareIdAndVersionProcessor(Provider<SoftwareIdAndVersionProcessorConfig> config, ClientMetadataAttributeValidator validator) {
      this.config = config;
      this.validator = validator;
   }

   @Override
   public Optional<OAuth2ClientRegistrationError> updateClient(OAuth2ClientRegistrationRequest request, OAuth2TechnicalClientMetadataBuilder clientBuilder) {
      Optional<String> id = this.extractValidSoftwareId(request);
      Optional<String> version = this.extractValidSoftwareVersion(request);
      if ((id.isEmpty() || version.isEmpty()) && ((SoftwareIdAndVersionProcessorConfig)this.config.get()).isMandatory()) {
         return Optional.of(OAuth2ClientRegistrationError.invalidClientMetadata("software_id and/or software_version missing or invalid"));
      }

      if (id.isEmpty() && version.isPresent()) {
         return Optional.of(OAuth2ClientRegistrationError.invalidClientMetadata("software_id missing or invalid"));
      }

      if (id.isPresent()) {
         LOG.debug("Using software_id value received from the client: " + LogUtil.logSafeString(id.get()));
         clientBuilder.softwareId(id);
      }

      if (version.isPresent()) {
         LOG.debug("Using software_version value received from the client: " + LogUtil.logSafeString(version.get()));
         clientBuilder.softwareVersion(version);
      }

      return Optional.empty();
   }

   private Optional<String> extractValidSoftwareId(OAuth2ClientRegistrationRequest request) {
      return request.getMetadata()
         .softwareId()
         .filter(v -> this.validator.isValidMetadataAttribute("software_id", v, 50, ((SoftwareIdAndVersionProcessorConfig)this.config.get()).getAllowedIds()));
   }

   private Optional<String> extractValidSoftwareVersion(OAuth2ClientRegistrationRequest request) {
      return request.getMetadata()
         .softwareVersion()
         .filter(
            v -> this.validator
               .isValidMetadataAttribute("software_version", v, 50, ((SoftwareIdAndVersionProcessorConfig)this.config.get()).getAllowedVersions())
         );
   }
}
