package com.kamco.cd.training.postgres.core;

import com.kamco.cd.training.common.enums.error.AuthErrorCode;
import com.kamco.cd.training.common.exception.CustomApiException;
import com.kamco.cd.training.postgres.entity.AuthRefreshTokenEntity;
import com.kamco.cd.training.postgres.repository.members.AuthRefreshTokenRepository;
import java.time.ZonedDateTime;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class TokenCoreService {

  private final AuthRefreshTokenRepository tokenRepository;

  public void save(String subject, String refreshToken, long validityMs) {
    ZonedDateTime expiresAt = ZonedDateTime.now().plusSeconds(validityMs / 1000);

    tokenRepository
        .findBySubject(subject)
        .ifPresentOrElse(
            entity -> entity.rotate(refreshToken, expiresAt),
            () ->
                tokenRepository.save(new AuthRefreshTokenEntity(subject, refreshToken, expiresAt)));
  }

  /**
   * refreshToken을 DB와 비교 검증
   *
   * @param subject 사용자 식별(UUID)
   * @return
   */
  public String getValidTokenOrThrow(String subject) {
    // DB 기준 유효한 RefreshToken 문자열 반환 (없으면 401 예외)
    return tokenRepository
        .findBySubjectAndRevokedDttmIsNullAndExpiresDttmAfter(subject, ZonedDateTime.now())
        .orElseThrow(() -> new CustomApiException(AuthErrorCode.REFRESH_TOKEN_EXPIRED_OR_REVOKED))
        .getToken();
  }

  /**
   * 로그아웃
   *
   * @param subject
   */
  public void revokeBySubject(String subject) {

    AuthRefreshTokenEntity token =
        tokenRepository
            .findBySubjectAndRevokedDttmIsNullAndExpiresDttmAfter(subject, ZonedDateTime.now())
            .orElseThrow(() -> new CustomApiException(AuthErrorCode.REFRESH_TOKEN_MISMATCH));

    // save() 호출 안 해도 됨 (영속 상태 + 트랜잭션)
    token.revoke();
  }
}
