package com.madeu.interceptor;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import com.madeu.dao.web.webauthmenurelation.WebAuthMenuRelationSqlMapDAO;
import com.madeu.dao.web.webmember.WebMemberSqlMapDAO;
import com.madeu.filter.CachedBodyRequestWrapper;
import org.springframework.web.servlet.ModelAndView;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class WebLoginInterceptor implements HandlerInterceptor {

    @Autowired
    private WebMemberSqlMapDAO webMemberSqlMapDAO;

    @Autowired
    private WebAuthMenuRelationSqlMapDAO webAuthMenuRelationSqlMapDAO;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        HttpSession session = request.getSession(false);

        if (session == null) {
            return handleSessionExpired(request, response);
        }

        String loginMemberId = (String) session.getAttribute("loginMemberId");
        String loginId = (String) session.getAttribute("loginId");
        String loginName = (String) session.getAttribute("loginName");

        log.debug("======================== USER CHECKLOGIN START =========================");
        log.debug(" loginMemberId      : " + loginMemberId);
        log.debug(" loginId            : " + loginId);
        log.debug(" loginName          : " + loginName);
        log.debug("======================== USER CHECKLOGIN END ===========================");

        if (loginMemberId == null || loginMemberId.isEmpty()) {
            return handleSessionExpired(request, response);
        }

        // 권한 체크 시작
        String menuClass = request.getParameter("menuClass");

        // Body (JSON) 에서 menuClass 파싱 시도
        if (menuClass == null || menuClass.isEmpty()) {
            if (request instanceof CachedBodyRequestWrapper) {
                CachedBodyRequestWrapper wrapper = (CachedBodyRequestWrapper) request;
                String body = new String(wrapper.getCachedBody(),
                        request.getCharacterEncoding() != null ? request.getCharacterEncoding() : "UTF-8");
                if (!body.isEmpty()) {
                    try {
                        ObjectMapper mapper = new ObjectMapper();
                        JsonNode root = mapper.readTree(body);
                        if (root.has("menuClass")) {
                            menuClass = root.get("menuClass").asText();
                        }
                    } catch (Exception e) {
                        log.error("Fail to parse JSON body for menuClass", e);
                    }
                }
            }
        }

        if (menuClass != null && !menuClass.isEmpty()) {
            try {
                HashMap<String, Object> checkMap = new HashMap<>();
                checkMap.put("loginMemberId", loginMemberId);
                List<Map<String, Object>> userListMap = webMemberSqlMapDAO.checkMember(checkMap);
                if (userListMap.size() == 1) {
                    String muAuthId = String.valueOf(userListMap.get(0).get("muAuthId"));

                    HashMap<String, Object> authCheckMap = new HashMap<>();
                    authCheckMap.put("menuClass", menuClass);
                    authCheckMap.put("muAuthId", muAuthId);
                    List<Map<String, Object>> authList = webAuthMenuRelationSqlMapDAO
                            .selectAuthMenuRelation(authCheckMap);

                    if (authList.size() == 1) {
                        request.setAttribute("selectUseYn", String.valueOf(authList.get(0).get("selectUseYn")));
                        request.setAttribute("insertUseYn", String.valueOf(authList.get(0).get("insertUseYn")));
                        request.setAttribute("updateUseYn", String.valueOf(authList.get(0).get("updateUseYn")));
                        request.setAttribute("deleteUseYn", String.valueOf(authList.get(0).get("deleteUseYn")));
                        request.setAttribute("downloadUseYn", String.valueOf(authList.get(0).get("downloadUseYn")));
                        log.debug("Menu Auth Set for menuClass: " + menuClass);
                    } else {
                        log.warn("No auth found for menuClass: " + menuClass + ", muAuthId: " + muAuthId);
                    }
                }
            } catch (Exception e) {
                log.error("Menu Auth Check Error", e);
            }
        }

        return true;
    }

    /**
     * 세션 만료 시 AJAX / 페이지 요청을 구분하여 처리
     */
    private boolean handleSessionExpired(HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        if (isAjaxRequest(request)) {
            // AJAX 요청 → 401 + JSON 응답
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(
                    "{\"msgCode\":\"SESSION_EXPIRED\","
                            + "\"msgDesc\":\"세션이 만료되었습니다. 다시 로그인해주세요.\","
                            + "\"success\":false}");
        } else {
            // 일반 페이지 요청 → 로그인 페이지로 리다이렉트
            response.sendRedirect("/web/login/logout");
        }
        return false;
    }

    /**
     * AJAX 요청 여부 판별
     */
    private boolean isAjaxRequest(HttpServletRequest request) {
        String xRequestedWith = request.getHeader("X-Requested-With");
        String contentType = request.getContentType();
        String accept = request.getHeader("Accept");

        return "XMLHttpRequest".equals(xRequestedWith)
                || (contentType != null && contentType.contains("application/json"))
                || (accept != null && accept.contains("application/json"));
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        if (modelAndView != null) {
            String selectUseYn = (String) request.getAttribute("selectUseYn");
            if (selectUseYn != null) {
                modelAndView.addObject("selectUseYn", selectUseYn);
                modelAndView.addObject("insertUseYn", request.getAttribute("insertUseYn"));
                modelAndView.addObject("updateUseYn", request.getAttribute("updateUseYn"));
                modelAndView.addObject("deleteUseYn", request.getAttribute("deleteUseYn"));
                modelAndView.addObject("downloadUseYn", request.getAttribute("downloadUseYn"));
            }
        }
    }
}
