package com.spring.infra.security.domain;

import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import com.spring.domain.user.entity.AgentUser;
import com.spring.domain.user.entity.AgentUserRole;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

/**
 * 사용자 정보를 나타내는 클래스입니다.
 * 
 * <p>이 클래스는 Spring Security의 UserDetails 인터페이스를 구현하여,
 * 인증된 사용자의 정보를 제공하는 역할을 합니다.</p>
 * 
 * <p>사용자 정보는 AgentUser 객체를 통해 관리되며, 사용자 권한 및 상태 정보를 포함합니다.</p>
 * 
 * @author mindol
 * @version 1.0
 */
@Getter
@RequiredArgsConstructor
public class UserPrincipal implements UserDetails {

    /**
     * 인증된 사용자 정보를 담고 있는 AgentUser 객체입니다.
     */
    private final transient AgentUser agentUser;

    /**
     * AgentUser 객체를 기반으로 UserPrincipal 객체를 생성합니다.
     * 
     * @param agentUser 인증된 사용자 정보가 담긴 AgentUser 객체
     * @return 생성된 UserPrincipal 객체
     */
    public static UserPrincipal valueOf(AgentUser agentUser) {
        return new UserPrincipal(agentUser);
    }

    /**
     * 사용자 ID와 사용자 이름을 기반으로 UserPrincipal 객체를 생성합니다.
     * 
     * @param userId 사용자 ID
     * @param userName 사용자 이름
     * @return 생성된 UserPrincipal 객체
     */
    public static UserPrincipal of(String userId, String userName) {
        return new UserPrincipal(AgentUser.builder().userId(userId).name(userName).build());
    }

    /**
     * 사용자의 권한을 반환합니다.
     * 
     * <p>사용자의 역할에 따라 GrantedAuthority 객체의 컬렉션을 반환합니다.</p>
     * 
     * @return 사용자의 권한 목록
     */
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return Arrays.stream(AgentUserRole.values())
            .filter(role -> Arrays.asList(agentUser.getUserRole()).contains(role)) 
            .map(AgentUserRole::getRole)
            .map(SimpleGrantedAuthority::new)
            .collect(Collectors.toList());
    }

    /**
     * 계정이 만료되지 않았는지 여부를 반환합니다.
     * 
     * @return 계정이 만료되지 않았으면 true, 그렇지 않으면 false
     */
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    /**
     * 계정이 잠겨 있지 않았는지 여부를 반환합니다.
     * 
     * @return 계정이 잠겨 있지 않으면 true, 그렇지 않으면 false
     */
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    /**
     * 자격 증명이 만료되지 않았는지 여부를 반환합니다.
     * 
     * @return 자격 증명이 만료되지 않았으면 true, 그렇지 않으면 false
     */
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    /**
     * 계정이 활성화되었는지 여부를 반환합니다.
     * 
     * @return 계정이 활성화되었으면 true, 그렇지 않으면 false
     */
    @Override
    public boolean isEnabled() {
        return true;
    }

    /**
     * 사용자의 비밀번호를 반환합니다.
     * 
     * @return 사용자의 비밀번호
     */
    @Override
    public String getPassword() {
        return agentUser.getPassword();
    }

    /**
     * 사용자의 사용자 ID를 반환합니다.
     * 
     * @return 사용자의 사용자 ID
     */
    @Override
    public String getUsername() {
        return agentUser.getUserId();
    }

    /**
     * 사용자의 고유 키를 반환합니다.
     * 
     * @return 사용자의 고유 키
     */
    public String getKey() {
        return agentUser.getId().toString();
    }

    /**
     * 사용자의 이름을 반환합니다.
     * 
     * @return 사용자의 이름
     */
    public String getMemberName() {
        return agentUser.getName();
    }

}
