package com.bb.config;

import java.io.IOException;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

import com.bb.common.model.OutLoginVO;
import com.bb.model.Site;
import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository; 
import org.springframework.security.web.context.SecurityContextRepository;
import org.springframework.stereotype.Component;

/**
 * Description: 스프링시큐리티 인증 성공 핸들러 (Spring Security 6 대응)
 * 작성된 코드에서 JSON 출력 로직을 제거하고 명시적 세션 저장을 추가했습니다.
 */
@Slf4j
@Component
public class AuthSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

    // [1번 방식 핵심] SecurityContextConfig에서 등록한 빈을 주입받아 사용합니다.
    // 이를 통해 SecurityConfig와의 순환 참조 문제를 해결합니다.
    @Autowired
    private SecurityContextRepository securityContextRepository;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) throws ServletException, IOException {
        
        // 1. [핵심] SecurityContext 생성 및 명시적 저장
        // Spring Security 6부터는 이 과정이 있어야 리다이렉트 후 @Secured가 권한을 올바르게 인식합니다.
        SecurityContext context = SecurityContextHolder.createEmptyContext();
        context.setAuthentication(authentication);
        SecurityContextHolder.setContext(context);
        
        // [수정] 빈으로 주입받은 repository를 통해 세션에 SecurityContext를 영구 저장 (Persistence)
        securityContextRepository.saveContext(context, request, response);	
		request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, context);

        // 2. 로그인 사용자 정보 추출 (UserDetails 대신 사용 중인 Site 객체)
        Site login = (Site) authentication.getDetails();
        final String LOG_PREFIX = "#-AS::" + (login != null ? login.getSiteId() : "Unknown") + ":::";
        
        String authorities = authentication.getAuthorities()
                .stream()
                .map(GrantedAuthority::getAuthority)
                .reduce((a, b) -> a + ", " + b)
                .orElse("없음");

        log.info(LOG_PREFIX + "로그인 성공 - 권한: " + authorities);
        
        // 3. 커스텀 세션 정보 저장
        HttpSession session = request.getSession(true);
        session.setAttribute("user", login);

        // 4. 권한에 따른 리다이렉트 경로 결정
        String targetUrl;
        if (authorities.contains("ROLE_ADMIN")) {
            // 관리자 세션 추가 정보 설정 (필요 시)
            OutLoginVO outLoginVO = new OutLoginVO();
            outLoginVO.setDomain(login != null ? login.getDomain() : "");
            outLoginVO.setId(login != null ? login.getSiteId() : "");

            targetUrl = "/index";
        } else {
            targetUrl = "/guest/simpleReport";
        }

        log.info(LOG_PREFIX + "Redirecting to: " + targetUrl);
        
        // 5. 리다이렉트 실행 (Clear prior attributes and redirect)
        clearAuthenticationAttributes(request);
        getRedirectStrategy().sendRedirect(request, response, targetUrl);
        
    }
}