package com.airlock.iam.authentication.domain.service.rememberme;

import com.airlock.iam.authentication.domain.model.rememberme.RememberMeTokenResult;
import com.airlock.iam.base.api.domain.model.user.UserId;
import com.airlock.iam.base.misc.time.TimeProvider;
import com.airlock.iam.flow.shared.domain.model.rememberme.RememberMeRequestMetadata;
import com.airlock.iam.flow.shared.domain.model.rememberme.RememberMeSecret;
import com.airlock.iam.flow.shared.domain.model.rememberme.RememberMeToken;
import com.airlock.iam.flow.shared.domain.model.rememberme.RememberMeTokenId;
import com.airlock.iam.flow.shared.domain.model.rememberme.RememberMeTokenRepository;
import jakarta.inject.Inject;
import jakarta.inject.Provider;

public final class RememberMeTokenGenerationServiceImpl implements RememberMeTokenGenerationService {
   private final Provider<RememberMeTokenRepository> repository;
   private final Provider<RememberMeRequestMetadata> requestMetadata;
   private final TimeProvider time;

   @Inject
   RememberMeTokenGenerationServiceImpl(Provider<RememberMeTokenRepository> repository, Provider<RememberMeRequestMetadata> requestMetadata, TimeProvider time) {
      this.repository = repository;
      this.requestMetadata = requestMetadata;
      this.time = time;
   }

   @Override
   public RememberMeTokenResult createToken(UserId iamUserId) {
      RememberMeSecret secret = RememberMeSecret.randomRememberMeSecret();
      RememberMeToken token = RememberMeToken.builder()
         .id(RememberMeTokenId.newRememberMeTokenId())
         .iamUserId(iamUserId)
         .secretHash(secret.hash())
         .firstUsedAt(this.time.getCurrentInstant())
         .firstRequest((RememberMeRequestMetadata)this.requestMetadata.get())
         .time(this.time)
         .build();
      ((RememberMeTokenRepository)this.repository.get()).insert(token);
      return new RememberMeTokenResult(token, secret);
   }

   @Override
   public RememberMeTokenResult renewToken(RememberMeToken token) {
      RememberMeSecret newSecret = token.renewSecret((RememberMeRequestMetadata)this.requestMetadata.get());
      ((RememberMeTokenRepository)this.repository.get()).update(token);
      return new RememberMeTokenResult(token, newSecret);
   }
}
