package com.takensoft.common.oauth.handler;

import com.takensoft.cms.loginPolicy.service.LoginModeService;
import com.takensoft.cms.loginPolicy.service.LoginPolicyService;
import com.takensoft.cms.mber.service.LgnHstryService;
import com.takensoft.cms.mber.service.UnifiedLoginService;
import com.takensoft.cms.mber.service.Impl.UnifiedLoginServiceImpl;
import com.takensoft.cms.mber.vo.MberVO;
import com.takensoft.common.util.LoginUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.URLEncoder;

/**
 * @author takensoft
 * @since 2025.05.22
 * @modification
 *     since    |    author    | description
 *  2025.05.22  |  takensoft   | 최초 등록
 *  2025.05.28  |  takensoft   | 통합 로그인 적용
 *  2025.05.29  |  takensoft   | OAuth2 통합 문제 해결
 *  2025.06.02  |  takensoft   | 세션 모드 중복로그인 처리 개선
 *  2025.06.09  |  takensoft   | OIDC 타입 캐스팅 문제 해결
 *  2025.06.18  |  takensoft   | OAuth 사용자 정보 추출 및 로그인 이력 저장 로직 통합
 *
 * OAuth2 로그인 성공 핸들러 - 최종 중복 제거 완료
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class OAuth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

    private final UnifiedLoginService unifiedLoginService;
    private final LgnHstryService lgnHstryService;
    private final LoginUtil loginUtil;
    private final LoginModeService loginModeService;
    private final LoginPolicyService loginPolicyService;

    @Value("${front.url}")
    private String frontUrl;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
        try {
            // 통합된 사용자 정보 추출 로직 사용
            UnifiedLoginServiceImpl.OAuth2UserInfo userInfo = extractUserInfo(authentication);

            if (userInfo == null) {
                handleOAuth2Error(response, new Exception("사용자 정보 추출 실패"));
                return;
            }

            // 현재 설정된 로그인 모드 확인
            String currentLoginMode = loginModeService.getLoginMode();
            boolean allowMultipleLogin = loginPolicyService.getPolicy();

            // 통합 로그인 서비스를 통한 OAuth2 사용자 처리
            MberVO mber = unifiedLoginService.processOAuth2User(
                    userInfo.getEmail(),
                    unifiedLoginService.convertProviderToMbrType(userInfo.getProvider()),
                    userInfo.getId(),
                    userInfo.getName(),
                    request
            );

            // 통합된 OAuth2 로그인 이력 저장 로직 사용
            lgnHstryService.saveOAuth2LoginHistory(mber, request, userInfo.getProvider());

            request.setAttribute("loginType", "OAUTH2");

            // LoginUtil을 통한 통합 로그인 처리
            loginUtil.successLogin(mber, request, response);

            String redirectUrl = String.format("%s/login.page?oauth_success=true&loginMode=%s&policyMode=%s",
                    frontUrl,
                    currentLoginMode,
                    allowMultipleLogin ? "Y" : "N");

            getRedirectStrategy().sendRedirect(request, response, redirectUrl);

        } catch (Exception e) {
            handleOAuth2Error(response, e);
        }
    }

    /**
     * OAuth2 사용자 정보 추출 - UnifiedLoginService의 통합 로직 사용
     */
    private UnifiedLoginServiceImpl.OAuth2UserInfo extractUserInfo(Authentication authentication) {
        try {
            // UnifiedLoginService의 통합된 사용자 정보 추출 메서드 사용
            if (unifiedLoginService instanceof UnifiedLoginServiceImpl) {
                UnifiedLoginServiceImpl unifiedLoginServiceImpl = (UnifiedLoginServiceImpl) unifiedLoginService;
                return unifiedLoginServiceImpl.extractUserInfoFromAuthentication(authentication);
            } else {
                return null;
            }
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * OAuth2 오류 처리
     */
    private void handleOAuth2Error(HttpServletResponse response, Exception e) throws IOException {

        String message = URLEncoder.encode("OAuth 로그인에 실패했습니다.", "UTF-8");
        String errorUrl = String.format("%s/?error=oauth2_failed&message=%s", frontUrl, message);
        getRedirectStrategy().sendRedirect(null, response, errorUrl);
    }
}