package com.kamco.cd.kamcoback.common.utils;

import com.kamco.cd.kamcoback.auth.CustomUserDetails;
import com.kamco.cd.kamcoback.auth.JwtTokenProvider;
import com.kamco.cd.kamcoback.postgres.entity.MemberEntity;
import java.util.Optional;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class UserUtil {

  private final JwtTokenProvider jwtTokenProvider;

  /**
   * 현재 SecurityContext의 Authentication 에서 사용자 ID(Long) 가져오기 - 로그인 된 상태(AccessToken 인증 이후)에서만 사용 가능
   * - 인증 정보 없으면 null 리턴
   */
  public Long getCurrentUserId() {
    return Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication())
        .filter(auth -> auth.getPrincipal() instanceof CustomUserDetails)
        .map(auth -> ((CustomUserDetails) auth.getPrincipal()).getMember().getId())
        .orElse(null);
  }

  /** 현재 SecurityContext의 Authentication 에서 사용자 UUID 가져오기 - 인증 정보 없으면 null 리턴 */
  public UUID getCurrentUserUuid() {
    return Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication())
        .filter(auth -> auth.getPrincipal() instanceof CustomUserDetails)
        .map(auth -> ((CustomUserDetails) auth.getPrincipal()).getMember().getUuid())
        .orElse(null);
  }

  /** 현재 로그인한 사용자의 MemberEntity 통째로 가져오기 (Optional) */
  public Optional<MemberEntity> getCurrentMember() {
    return Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication())
        .filter(auth -> auth.getPrincipal() instanceof CustomUserDetails)
        .map(auth -> ((CustomUserDetails) auth.getPrincipal()).getMember());
  }

  /** 현재 로그인한 사용자의 MemberEntity 가져오기 (없으면 예외) */
  public MemberEntity getCurrentMemberOrThrow() {
    return getCurrentMember().orElseThrow(() -> new IllegalStateException("인증된 사용자를 찾을 수 없습니다."));
    // 필요하면 여기서 CustomApiException 으로 바꿔도 됨
  }

  /** AccessToken / RefreshToken 에서 sub(subject, uuid) 추출 - 토큰 문자열만 있을 때 uuid 가져올 때 사용 */
  public String getSubjectFromToken(String token) {
    return jwtTokenProvider.getSubject(token);
  }
}
