package com.airlock.iam.authentication.infrastructure.rememberme;

import com.airlock.iam.authentication.domain.model.rememberme.RememberMeJspSecret;
import com.airlock.iam.authentication.domain.model.rememberme.RememberMeRequest;
import com.airlock.iam.common.application.configuration.rememberme.JspRememberMeConfig;
import com.airlock.iam.common.application.configuration.rememberme.RememberMeConfig;
import com.airlock.iam.core.misc.util.ServletUtils;
import com.airlock.iam.flow.shared.domain.model.rememberme.RememberMeSecret;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Optional;
import java.util.regex.Pattern;

public final class RememberMeRequestImpl implements RememberMeRequest {
   private static final Pattern REMEMBER_ME_SECRET_COOKIE_PATTERN = Pattern.compile("^[a-zA-Z0-9_-]{200}$");
   private final Provider<HttpServletRequest> request;
   private final RememberMeConfig config;
   private final Optional<JspRememberMeConfig> jspConfig;

   @Inject
   public RememberMeRequestImpl(Provider<HttpServletRequest> request, RememberMeConfig config, Optional<JspRememberMeConfig> jspConfig) {
      this.request = request;
      this.config = config;
      this.jspConfig = jspConfig;
   }

   @Override
   public Optional<RememberMeSecret> findRememberMeSecret() {
      return Optional.ofNullable(ServletUtils.getCookie((HttpServletRequest)this.request.get(), this.config.getCookieName()))
         .<String>map(Cookie::getValue)
         .flatMap(RememberMeSecret::parseRememberMeSecret);
   }

   @Override
   public Optional<RememberMeJspSecret> findRememberMeJspSecret() {
      return this.jspConfig
         .flatMap(
            jspRememberMeConfig -> Optional.ofNullable(ServletUtils.getCookie((HttpServletRequest)this.request.get(), jspRememberMeConfig.getCookieName()))
               .filter(c -> this.isRememberMeJspCookie(c.getValue()))
               .<String>map(Cookie::getValue)
               .map(RememberMeJspSecret::fromString)
         );
   }

   private boolean isRememberMeJspCookie(String value) {
      return !REMEMBER_ME_SECRET_COOKIE_PATTERN.matcher(value).matches();
   }
}
