package com.its.web.security;

import com.its.web.dto.admin.PrincipalDetail;
import com.its.web.dto.admin.TbWwwMemberDto;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.WebAttributes;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.stereotype.Service;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
@AllArgsConstructor
@Service
public class WebLoginSuccessHandler implements AuthenticationSuccessHandler {

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        SimpleDateFormat sdfDate = new SimpleDateFormat("yyyyMMddHHmmss");
        Date dtNow = new Date();
        String currSysTime = sdfDate.format(dtNow);
        // IP, 세션 ID
        WebAuthenticationDetails details = (WebAuthenticationDetails)authentication.getDetails();

        // 인증 ID
        String userId = authentication.getName();
        log.info("login Remote-IP/Session-ID/User-ID: {}/{}/{}", details.getRemoteAddress(), details.getSessionId(), userId);

        // 권한 리스트
        List<GrantedAuthority> authList = new ArrayList<>(authentication.getAuthorities());
        for (GrantedAuthority auth : authList) {
            log.info("login Roll: {}", auth.getAuthority());
        }

        PrincipalDetail principal = (PrincipalDetail)authentication.getPrincipal();
        TbWwwMemberDto userInfr = principal.getUser();

        String remoteIp = this.getHttpServletRemoteIP(request);
        log.info("Login History: {}, {}", currSysTime, remoteIp);

        HttpSession session = request.getSession(false); // 세션을 생성 하지 않음
        if (session != null) {
            log.info("Session[{}}] [{}], Login Authentication: User: {}, {}, Login History: {}, {}",
                    session.getId(), currSysTime, userInfr.getEmail(), userInfr.getMemberNm(), remoteIp, currSysTime);
        } else {
            session = request.getSession(true); // 새로운 세션을 생성
            session.setMaxInactiveInterval(60);
            log.info("Session[{}] [{}], Login Authentication, Session Create: User: {}, {}, {}, Login History: {}, {}",
                    session.getId(), currSysTime, userInfr.getEmail(), userInfr.getMemberNm(), currSysTime, session.getMaxInactiveInterval(), remoteIp, currSysTime);
        }
        session.setAttribute("UUID", userInfr.getEmail());
        session.setAttribute("TIME", currSysTime);
        session.setAttribute("NAME", userInfr.getMemberNm());

        clearAuthenticationAttributes(request);
        response.sendRedirect("/phits/main");
    }

    /**
     * 로그인 성공시 로그인 실패 시 작성한 에러 세션 지우기
     * @param request
     */
    protected void clearAuthenticationAttributes(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        //log.error("clearAuthenticationAttributes: {}", session);
        if (session == null) {
            log.warn("session already cleared.");
            return;
        }

        session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
    }

    public static String getHttpServletRemoteIP(HttpServletRequest request) {
        if (request == null) {
            return "";
        }

        String ipAddress = request.getHeader("X-FORWARDED-FOR");
        // proxy 환경일 경우
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        // 웹로직 서버일 경우
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        // 기타
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr() ;
        }
        //-Djava.net.preferIPv4Stack=true
        if (ipAddress.equals("0:0:0:0:0:0:0:1"))   //==> ipv6 <== default
        {
            ipAddress = "127.0.0.1";   //==> localhost
        }
        return ipAddress;
    }
}
