package com.eactive.eai.rms.common.login;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import com.eactive.eai.rms.common.context.MonitoringContext;
import com.eactive.eai.rms.common.util.CommonConstants;

//craft
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 공통 상수를 정의하는 클래스입니다.
 */
public class SessionManager {

    /** The Constant contextHolder. */
    private static final ThreadLocal<LoginVo> contextHolder = new ThreadLocal<LoginVo>();
    
    /** craft */ 
    private static final Map<String, String> loggedInUsers = new ConcurrentHashMap<>();
	
    /**
     * Sets the data source type.
     * 
     * @param dataSourceType
     *            the new data source type
     */
    public static void setLoginVo(LoginVo loginVo) {
    	contextHolder.set(loginVo);    	 	
    }

    /**
     * Gets the data source type.
     * 
     * @return the data source type
     */
    public static LoginVo getLoginVo() {
        return (LoginVo) contextHolder.get();
    }

    /**
     * Clear data source type.
     */
    public static void clearLoginVo() {
        contextHolder.remove();
    }
    
	/**
	 * 세션에서 사용자 객체를 얻어오는 메소드.
	 * 
	 * @param session
	 * @return
	 */
	public static LoginVo getLoginVo(HttpServletRequest request)  {
		return (LoginVo) request.getSession().getAttribute(CommonConstants.LOGIN);
	}

	/**
	 * 세션에서 사용자 아이디(행번)를 가져오는 메소드
	 * 
	 * @param request
	 * @return
	 */
	public static String getUserId(HttpServletRequest request) {
		LoginVo login = (LoginVo) request.getSession().getAttribute(CommonConstants.LOGIN);
		
		// 외부에 제공되는 서블릿(ITSM 임계치 관련 등)의 경우 로그인 정보가 없다.
		if( login == null )
		    return "" ;
		
		return login.getUserId();

	}

	/**
	 * 세션에서 사용자 명을 가져오는 메소드
	 * 
	 * @param request
	 * @return
	 */
	public static String getUserName(HttpServletRequest request) {
		LoginVo login = (LoginVo) request.getSession().getAttribute(CommonConstants.LOGIN);
		
		// 외부에 제공되는 서블릿(ITSM 임계치 관련 등)의 경우 로그인 정보가 없다.
		if( login == null )
		    return "" ;
		
		return login.getUserName();
	}

	/**
	 * 세션에서 RoleID를 얻어오는 메소드
	 * 
	 * @param request
	 * @return
	 */
	public static List<String> getRoleId(HttpServletRequest request) {
		LoginVo login = (LoginVo)request.getSession().getAttribute(CommonConstants.LOGIN);
		if (login == null) {
            return null;
        }
		return login.getRoleList();
	}
	/**
	 * 세션에서 RoleID를 얻어오는 메소드
	 * 
	 * @param request
	 * @return
	 */
	public static String getRoleIdString(HttpServletRequest request) {
		LoginVo login = (LoginVo)request.getSession().getAttribute(CommonConstants.LOGIN);

		if (login == null) {
            return null;
        }

		List<String> roleList = login.getRoleList();

		if (roleList == null || roleList.isEmpty()) {
            return null;
        }

		String roles = "";
        for(String role : roleList){
        	roles = roles +","+role;
        }
        return roles;
	}	

	/**
	 * 세션에서 부서명을 가져오는 메소드
	 * 
	 * @param request
	 * @return
	 */
	public static String getDvsnName(HttpServletRequest request) {
		LoginVo login = (LoginVo) request.getSession().getAttribute(CommonConstants.LOGIN);
		
		// 외부에 제공되는 서블릿(ITSM 임계치 관련 등)의 경우 로그인 정보가 없다.
		if( login == null )
		    return "" ;
		
		return login.getDepartment();		
	}
	/**
	 * 
	 * 세션에 저장 되어 있는 서비스 타입의 키 값을 가져 온다.
	 * 
	 * @param request
	 * @return service key {@link ServiceType#getKey()}
	 */
	public static String getServiceTypeKey(HttpServletRequest request) {
		return request.getParameter("serviceType");
	}	
	
	/**
     * 새 로그인 세션을 등록하고 이중 로그인 여부를 확인
     * @param request HTTP 요청
     * @param loginVo 로그인 정보
     * @return true: 새 로그인, false: 이미 다른 세션에서 로그인됨
     */
    public static boolean registerUserSession(HttpServletRequest request, LoginVo loginVo) {
        String userId = loginVo.getUserId();
        String sessionId = request.getSession().getId();
        
        // 이미 로그인된 사용자인지 확인
        String existingSessionId = loggedInUsers.get(userId);
        
        // 이미 동일한 세션이면 그대로 유지
        if (existingSessionId != null && existingSessionId.equals(sessionId)) {
            return true;
        }
        
        // 이미 다른 세션으로 로그인된 경우
        if (existingSessionId != null) {
            return false;
        }
        
        // 새로운 로그인 세션 등록
        loggedInUsers.put(userId, sessionId);
        return true;
    }
    
    /**
     * 세션을 등록하고 이전 세션을 강제로 로그아웃시킴
     * @param request HTTP 요청
     * @param loginVo 로그인 정보
     */
    public static void forceRegisterUserSession(HttpServletRequest request, LoginVo loginVo) {
        String userId = loginVo.getUserId();
        String sessionId = request.getSession().getId();
        
        // 이전 세션 정보와 상관없이 새 세션으로 업데이트
        loggedInUsers.put(userId, sessionId);
    }
    
    /**
     * 사용자의 로그인 세션을 제거
     * @param userId 사용자 ID
     */
    public static void removeUserSession(String userId) {
        if (userId != null) {
            loggedInUsers.remove(userId);
        }
    }
    
    /**
     * 사용자의 로그인 세션을 제거 (이중로그인 버그 수정용)
     * @param sessionId 로그인한 session ID
     */
    public static void removeUserSessionBySessionId(String sessionId) {
    	loggedInUsers.entrySet().removeIf(entry -> sessionId.equals(entry.getValue()));
    }
    
    /**
     * 현재 세션이 유효한 로그인 세션인지 확인
     * @param request HTTP 요청
     * @param isDualLogin 이중 로그인 허용여부
     * @return true: 유효한 세션, false: 유효하지 않은 세션
     */
    public static boolean isValidSession(HttpServletRequest request, boolean isDualLogin) {
        LoginVo loginVo = getLoginVo(request);
        if (loginVo == null) {
            return false;
        }
        
        if (isDualLogin) {
        	return true;
        } else {
	        String userId = loginVo.getUserId();
	        String currentSessionId = request.getSession().getId();
	        String registeredSessionId = loggedInUsers.get(userId);
	        
	        // 등록된 세션이 없거나 현재 세션과 다른 경우
	        return registeredSessionId != null && registeredSessionId.equals(currentSessionId);
        }
    }	
    
    

}