package com.its.op.security;

import com.its.op.dao.repository.its.oper.TbUserCnncHsRepository;
import com.its.op.entity.its.oper.TbUserCnncHs;
import com.its.utils.CookieUtils;
import com.its.utils.ItsUtils;
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.util.ArrayList;
import java.util.List;

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

    private final TbUserCnncHsRepository cnncHsRepo;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {

        // IP, 세션 ID
        WebAuthenticationDetails details = (WebAuthenticationDetails)authentication.getDetails();

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

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

        UserInfrVo userInfr = (UserInfrVo)authentication.getPrincipal();
        String remoteIp = ItsUtils.getHttpServletRemoteIP(request);
        log.info("UserLogin: {}, {}", userInfr.getUserId(), remoteIp);
        TbUserCnncHs cnncHs = TbUserCnncHs.builder()
                .userId(userInfr.getUserId())
                .loginHms(ItsUtils.getSysTime())
                .logoutHms("")
                .build();
        this.cnncHsRepo.insertData(cnncHs.getLoginHms(), cnncHs.getUserId(), cnncHs.getLogoutHms());

        //log.info("cnncHs: {}, {}", cnncHs.getUserId(), cnncHs.getLoginHms());

        request.getSession().setAttribute(WebMvcConfig.USER_UUID, WebMvcConfig.encUserId(cnncHs.getUserId()));
        request.getSession().setAttribute(WebMvcConfig.USER_TIME, cnncHs.getLoginHms());

        CookieUtils.setCookie(response, WebMvcConfig.USER_UUID, WebMvcConfig.encUserId(cnncHs.getUserId()), 60*60);
        CookieUtils.setCookie(response, WebMvcConfig.USER_TIME, cnncHs.getLoginHms(), 60*60);

        String defaultSuccessUrl = "/application/op/00.main/main.html";
        String uri = defaultSuccessUrl;
        // Security 가 요청을 가로챈 경우 사용자가 원래 요청했던 URI 정보를 저장한 객체
//        RequestCache requestCache = new HttpSessionRequestCache();
//        SavedRequest savedRequest = requestCache.getRequest(request, response);
//
//        // 있을 경우 URI 등 정보를 가져와서 사용
//        if (savedRequest != null) {
//            uri = savedRequest.getRedirectUrl();
//            // 세션에 저장된 객체를 다 사용한 뒤에는 지워줘서 메모리 누수 방지
//            requestCache.removeRequest(request, response);
//            log.info("Saved Uri: {}", uri);
//        }

        // 세션 Attribute 확인
//        Enumeration<String> list = request.getSession().getAttributeNames();
//        while (list.hasMoreElements()) {
//            log.info("Attribute: {}", list.nextElement());
//            //Attribute: TIME
//            //Attribute: UUID
//            //Attribute: SPRING_SECURITY_CONTEXT
//        }
        clearAuthenticationAttributes(request);
        response.sendRedirect(uri);
    }

    /**
     * 로그인 성공시 로그인 실패 시 작성한 에러 세션 지우기
     * @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);
    }
}
