package com.airlock.iam.admin.application.service.token.fido;

import com.airlock.iam.admin.api.domain.model.administrator.CurrentAdministrator;
import com.airlock.iam.base.api.domain.model.user.UserId;
import com.airlock.iam.factor.domain.model.fido.FidoUserCredential;
import com.airlock.iam.fido.api.domain.model.FidoCredentialId;
import com.airlock.iam.log.api.helpdesk.HelpdeskLogger;
import com.airlock.iam.log.api.signing.SigningLogger;
import jakarta.inject.Inject;
import lombok.NonNull;

public final class FidoAdminLoggerImpl implements FidoAdminLogger {
   @NonNull
   private final SigningLogger signingLogger;
   @NonNull
   private final HelpdeskLogger helpdeskLogger;
   @NonNull
   private final CurrentAdministrator administrator;

   @Inject
   FidoAdminLoggerImpl(@NonNull SigningLogger signingLogger, @NonNull HelpdeskLogger helpdeskLogger, @NonNull CurrentAdministrator administrator) {
      if (signingLogger == null) {
         throw new NullPointerException("signingLogger is marked non-null but is null");
      }

      if (helpdeskLogger == null) {
         throw new NullPointerException("helpdeskLogger is marked non-null but is null");
      }

      if (administrator == null) {
         throw new NullPointerException("administrator is marked non-null but is null");
      }

      this.signingLogger = signingLogger;
      this.helpdeskLogger = helpdeskLogger;
      this.administrator = administrator;
   }

   @Override
   public void logCredentialDeleted(FidoCredentialId credentialId, UserId userId) {
      this.log(
         String.format("Administrator '%s' deleted %s from user '%s'", this.administrator.getName(), this.describeFidoCredential(credentialId), userId), userId
      );
   }

   @Override
   public void logCredentialLocked(FidoUserCredential credential, UserId userId) {
      this.log(
         String.format("Administrator '%s' locked %s of user '%s'", this.administrator.getName(), this.describeFidoCredential(credential), userId), userId
      );
   }

   @Override
   public void logCredentialUnlocked(FidoUserCredential credential, UserId userId) {
      this.log(
         String.format("Administrator '%s' unlocked %s of user '%s'", this.administrator.getName(), this.describeFidoCredential(credential), userId), userId
      );
   }

   private void log(String message, UserId affectedUserId) {
      this.signingLogger.log(message);
      this.helpdeskLogger.log(affectedUserId, message);
   }

   private String describeFidoCredential(FidoCredentialId credentialId) {
      return String.format("FIDO credential(ID='%s')", credentialId);
   }

   private String describeFidoCredential(FidoUserCredential credential) {
      return String.format(
         "FIDO credential(ID='%s', public-key credential ID='%s', relying party ID='%s')",
         credential.getId(),
         credential.getPublicKeyCredentialId(),
         credential.getRelyingPartyId()
      );
   }
}
