package com.airlock.iam.oauth2.application.service.token;

import com.airlock.iam.base.misc.result.Result;
import com.airlock.iam.common.api.domain.model.user.PersistentUser;
import com.airlock.iam.core.misc.util.ticket.Ticket;
import com.airlock.iam.core.misc.util.ticket.TicketEncodingException;
import com.airlock.iam.oauth2.domain.model.credential.OAuth2AccessInfo;
import com.airlock.iam.oauth2.domain.model.parser.RawOAuth2TokenParser;
import com.airlock.iam.oauth2.domain.model.token.OAuth2AccessToken;
import com.airlock.iam.oauth2.domain.model.validation.OAuth2ValidationResult;
import com.airlock.iam.oauth2.domain.service.credential.OAuth2AccessTokenValidationService;

public final class OAuth2AccessTokenDecoderService {
   private final OAuth2AccessTokenValidationService validationService;
   private final RawOAuth2TokenParser tokenParser;
   private final boolean addScopesAsRoles;

   public OAuth2AccessTokenDecoderService(OAuth2AccessTokenValidationService validationService, RawOAuth2TokenParser tokenParser, boolean addScopesAsRoles) {
      this.validationService = validationService;
      this.tokenParser = tokenParser;
      this.addScopesAsRoles = addScopesAsRoles;
   }

   public Ticket decode(String ticketString) throws TicketEncodingException {
      OAuth2AccessInfo oAuth2AccessInfo = this.decodeToAccessInfo(ticketString).orElseThrow(r -> new TicketEncodingException("Error validating token"));
      PersistentUser user = oAuth2AccessInfo.getValidUser();
      OAuth2AccessToken token = oAuth2AccessInfo.getAccessToken();
      return OAuth2TicketBuilderFactory.buildTicket(user, token, this.addScopesAsRoles);
   }

   private Result<OAuth2AccessInfo, OAuth2ValidationResult> decodeToAccessInfo(String ticketString) throws TicketEncodingException {
      return this.tokenParser
         .parseRawOAuth2Token(ticketString)
         .map(this.validationService::validateAccessToken)
         .orElseThrow(() -> new TicketEncodingException("Error parsing token"));
   }
}
