package com.airlock.iam.flow.shared.infrastructure.resource;

import com.airlock.iam.common.domain.model.user.PrincipalInfo;
import com.airlock.iam.common.domain.model.user.UserIdentityLogs;
import com.airlock.iam.flow.api.domain.model.flow.FlowResult;
import com.airlock.iam.flow.api.domain.model.step.StepError;
import com.airlock.iam.flow.api.infrastructure.mapper.FlowResultMapper;
import com.airlock.iam.flow.infrastructure.mapper.FlowResultToCollectionDocumentMapper;
import com.airlock.iam.flow.shared.domain.model.termsofservice.TermsOfServiceCheck;
import com.airlock.iam.flow.shared.domain.model.termsofservice.TermsOfServiceEntries;
import com.airlock.iam.flow.shared.domain.model.termsofservice.TermsOfServiceStep;
import com.airlock.iam.log.api.helpdesk.HelpdeskLogger;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import jakarta.ws.rs.core.Response;
import java.util.Optional;
import ma.glasnost.orika.MapperFacade;

public class TermsOfServiceResourceImpl {
   private final HelpdeskLogger helpdeskLogger;
   private final Provider<PrincipalInfo> principalInfo;
   private final FlowResultMapper mapper;
   private final MapperFacade mapperFacade;
   private final Provider<TermsOfServiceCheck> termsOfServiceCheck;

   @Inject
   public TermsOfServiceResourceImpl(
      HelpdeskLogger helpdeskLogger,
      Provider<PrincipalInfo> principalInfo,
      FlowResultMapper mapper,
      MapperFacade mapperFacade,
      Provider<TermsOfServiceCheck> termsOfServiceCheck
   ) {
      this.helpdeskLogger = helpdeskLogger;
      this.principalInfo = principalInfo;
      this.mapper = mapper;
      this.mapperFacade = mapperFacade;
      this.termsOfServiceCheck = termsOfServiceCheck;
   }

   public Response retrieveOpenTermsOfService(Class<?> resultDataClass) {
      FlowResult result = ((TermsOfServiceCheck)this.termsOfServiceCheck.get()).retrieve();
      return FlowResultToCollectionDocumentMapper.flowResultDataToCollectionDocumentMapper(this.mapper, this.mapperFacade)
         .map(result, TermsOfServiceEntries.class, resultDataClass, tos -> tos.getTag().getName());
   }

   public Response denyToS() {
      String userIdForLogging = UserIdentityLogs.orElseNotAvailable(((PrincipalInfo)this.principalInfo.get()).getKnownIdentity());
      FlowResult result = ((TermsOfServiceCheck)this.termsOfServiceCheck.get()).deny();
      Optional<StepError> stepError = result.error();
      if (stepError.isPresent() && stepError.get() == TermsOfServiceStep.TermsOfServiceError.TERMS_OF_SERVICES_DENIED) {
         this.helpdeskLogger.log(userIdForLogging, "Denied terms of services.");
         return Response.noContent().build();
      } else {
         return this.mapper.toResponse(result);
      }
   }

   public Response acceptRetrieved() {
      String userIdForLogging = UserIdentityLogs.orElseNotAvailable(((PrincipalInfo)this.principalInfo.get()).getKnownIdentity());
      FlowResult result = ((TermsOfServiceCheck)this.termsOfServiceCheck.get()).acceptRetrieved();
      if (!result.isFailed()) {
         this.helpdeskLogger.log(userIdForLogging, "Terms of services accepted.");
      }

      return this.mapper.toResponse(result);
   }
}
