package incheon.com.security.vo;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import org.springframework.security.core.GrantedAuthority;

import javax.validation.constraints.Email;
import java.io.Serializable;
import java.util.Date;
import java.util.List;

/**
 * @Class Name : LoginVO.java
 * @Description : Login VO class
 * @Modification Information
 * @
 * @  수정일         수정자                   수정내용
 * @ -------    --------    ---------------------------
 * @ 2009.03.03    박지욱          최초 생성
 *
 *  @author 공통서비스 개발팀 박지욱
 *  @since 2009.03.03
 *  @version 1.0
 *  @see
 *  
 */
@Schema(description = "사용자 정보 VO")
@Getter
@Setter
public class LoginVO implements Serializable{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -8274004534207618049L;
	
	// === 기본 사용자 정보 ===
	@Schema(description = "사용자 고유 아이디 (PK)")
	private String userUnqId;

	@Schema(description = "사용자 아이디")
	private String userId;

	@Schema(description = "사용자 상태 코드")
	private String userStcd;

	@Schema(description = "사용자명")
	private String userNm;

	// === 조직 정보 ===
	@Schema(description = "부서 코드")
	private String deptCd;

	@Schema(description = "부서명")
	private String deptNm;

	@Schema(description = "부서 전체명")
	private String deptWholNm;

	@Schema(description = "직급 코드")
	private String jbgdCd;

	@Schema(description = "직급명")
	private String jbgdNm;

	@Schema(description = "직위 코드")
	private String jbpsCd;

	@Schema(description = "직위명")
	private String jbpsNm;

	// === 기관 정보 ===
	@Schema(description = "대표기관코드")
	private String rprsInstCd;

	@Schema(description = "대표기관명")
	private String rprsInstNm;

	@Schema(description = "도로관리기관코드")
	private String roadMngInstCd;

	@Schema(description = "도로관리기관명")
	private String roadMngInstNm;

	// === 연락처 정보 ===
	@Email(regexp = "[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,3}")
	@Schema(description = "이메일 주소")
	private String emlAddr;

	@Schema(description = "사무실 전화번호")
	private String ofcTelno;

	@Schema(description = "휴대전화번호")
	private String mblTelno;

	// === 외부 시스템 연동 정보 ===
	@Schema(description = "전자결재로그인아이디")
	private String elaprLgnId;

	@Schema(description = "세외수입아이디")
	private String nxrpId;

	@Schema(description = "새올아이디")
	private String saeoId;

	@Schema(description = "새올부서코드")
	private String saeoDeptCd;

	@Schema(description = "새올민원부서코드")
	private String saeoCvlcptDeptCd;

	@Schema(description = "시군구민원접수담당자아이디")
	private String sggCvlcptRcptPicId;

	// === 시스템 정보 ===
	@Schema(description = "최초 등록자 ID")
	private String frstRegId;
	
	@Schema(description = "최초 등록일시")
	private Date frstRegDt;
	
	@Schema(description = "최종 수정자 ID")
	private String lastMdfcnId;
	
	@Schema(description = "최종 수정일시")
	private Date lastMdfcnDt;
	
	// === 시스템 전용 필드들 ===
	@Schema(description = "권한 역할 (시스템 내부용)")
	private String groupId;
	
	@Schema(description = "사용자 IP정보 (세션용)")
	private String ip;

	@Schema(description = "권한 목록")
	private List<GrantedAuthority> authorities;

	@Schema(description = "로그인 시간")
	private Date loginTime;

	// === 권한 정보 (시스템별) ===

	/** 사용자 권한 목록 (시스템별) */
	@Schema(description = "사용자 권한 목록 (시스템별)")
	private List<UserAuthrtVO> userAuthrts;

	/** 사용자 역할 목록 (정규) */
	@Schema(description = "사용자 정규 역할 목록")
	private List<UserRoleVO> userRoles;

	/** 사용자 역할 목록 (임시) */
	@Schema(description = "사용자 임시 역할 목록")
	private List<UserRoleVO> tempUserRoles;

	/** 현재 작업중인 시스템 코드 (동적) */
	@Schema(description = "현재 작업중인 시스템 코드 (URL 경로 기반)")
	private String currentSysCd;

	/** 접근 가능한 시스템 코드 목록 (정적 캐싱) */
	@Schema(description = "사용자가 접근 가능한 시스템 코드 목록")
	private List<String> activeSysCds;

	/** 통합관리자 여부 (ROLTYP001 역할유형 보유) */
	@Schema(description = "통합관리자 여부")
	private boolean superAdmin;

	/** 업무관리자 권한이 있는 시스템 코드 목록 (ROLTYP002) */
	@Schema(description = "업무관리자 권한이 있는 시스템 코드 목록")
	private List<String> adminSysCds;

	public List<GrantedAuthority> getAuthorities() {
		return authorities;
	}

	public void setAuthorities(List<GrantedAuthority> authorities) {
		this.authorities = authorities;
	}

	/**
	 * 특정 시스템의 특정 권한을 가지고 있는지 확인
	 *
	 * @param sysCd 시스템 코드
	 * @param authrtCd 권한 코드
	 * @return 권한 보유 여부
	 */
	public boolean hasAuthrt(String sysCd, String authrtCd) {
		if (userAuthrts == null) return false;

		return userAuthrts.stream()
			.anyMatch(authrt ->
				authrt.getSysCd().equals(sysCd) &&
				authrt.getAuthrtCd().equals(authrtCd));
	}

	/**
	 * 특정 시스템의 권한 목록 조회
	 *
	 * @param sysCd 시스템 코드
	 * @return 해당 시스템의 권한 목록
	 */
	public List<UserAuthrtVO> getAuthrtsBySysCd(String sysCd) {
		if (userAuthrts == null) return java.util.Collections.emptyList();

		return userAuthrts.stream()
			.filter(authrt -> authrt.getSysCd().equals(sysCd))
			.collect(java.util.stream.Collectors.toList());
	}

	/**
	 * 사용자가 접근 가능한 시스템 코드 목록 조회 (캐싱)
	 * - 필드가 이미 설정된 경우 캐시된 값 반환
	 * - 설정되지 않은 경우 권한 정보에서 계산
	 *
	 * @return 접근 가능한 시스템 코드 목록
	 */
	public List<String> getActiveSysCds() {
		// 캐시된 값이 있으면 반환
		if (activeSysCds != null) {
			return activeSysCds;
		}

		// 캐시가 없으면 권한 정보에서 계산
		if (userAuthrts == null) return java.util.Collections.emptyList();

		return userAuthrts.stream()
			.map(UserAuthrtVO::getSysCd)
			.distinct()
			.sorted()
			.collect(java.util.stream.Collectors.toList());
	}

	@Override
	public String toString() {
		return "LoginVO{" + "userUnqId=" + userUnqId + ", userId=" + userId + ", userNm=" + userNm + ", deptNm=" + deptNm + '}';
	}

}
