package com.takensoft.common.oauth.handler;

import com.takensoft.cms.loginPolicy.service.LoginModeService;
import com.takensoft.cms.mber.service.LgnHstryService;
import com.takensoft.cms.mber.service.UnifiedLoginService;
import com.takensoft.cms.mber.vo.LgnHstryVO;
import com.takensoft.cms.mber.vo.MberVO;
import com.takensoft.common.oauth.vo.CustomOAuth2UserVO;
import com.takensoft.common.util.HttpRequestUtil;
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 통합 문제 해결
 *
 * OAuth2 로그인 성공 핸들러 - 통합 로그인 시스템 적용 (문제 해결)
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class OAuth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

    private final UnifiedLoginService unifiedLoginService;
    private final LgnHstryService lgnHstryService;
    private final HttpRequestUtil httpRequestUtil;
    private final LoginUtil loginUtil;
    private final LoginModeService loginModeService;

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

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

        CustomOAuth2UserVO oAuth2User = (CustomOAuth2UserVO) authentication.getPrincipal();

        try {
            // 현재 설정된 로그인 모드 확인
            String currentLoginMode = loginModeService.getLoginMode();

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

            saveLoginHistory(request, mber, oAuth2User.getProvider());

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

            String redirectUrl = String.format("%s/login.page?oauth_success=true&loginMode=%s",
                    frontUrl, currentLoginMode);
            getRedirectStrategy().sendRedirect(request, response, redirectUrl);

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

    /**
     * 로그인 이력 저장
     */
    private void saveLoginHistory(HttpServletRequest request, MberVO mber, String provider) {
        try {
            String userAgent = httpRequestUtil.getUserAgent(request);

            LgnHstryVO loginHistory = new LgnHstryVO();
            loginHistory.setLgnId(mber.getLgnId());
            loginHistory.setLgnType(mber.getAuthorities().stream()
                    .anyMatch(r -> r.getAuthority().equals("ROLE_ADMIN")) ? "0" : "1");
            loginHistory.setCntnIp(httpRequestUtil.getIp(request));
            loginHistory.setCntnOperSys(httpRequestUtil.getOS(userAgent));
            loginHistory.setDeviceNm(httpRequestUtil.getDevice(userAgent));
            loginHistory.setBrwsrNm(httpRequestUtil.getBrowser(userAgent));

            lgnHstryService.LgnHstrySave(loginHistory);
        } catch (Exception e) {
            log.error("로그인 이력 저장 실패: {}", e.getMessage());
        }
    }

    /**
     * 제공자명을 회원타입으로 변환
     */
    private String convertProviderToMbrType(String provider) {
        return switch (provider.toLowerCase()) {
            case "kakao" -> "K";
            case "naver" -> "N";
            case "google" -> "G";
            case "facebook" -> "F";
            default -> "S";
        };
    }

    /**
     * OAuth2 오류 처리
     */
    private void handleOAuth2Error(HttpServletResponse response, Exception e) throws IOException {
        String message = URLEncoder.encode("OAuth 로그인에 실패했습니다.", "UTF-8");
        String errorUrl = String.format("%s/login.page?error=oauth2_failed&message=%s", frontUrl, message);
        getRedirectStrategy().sendRedirect(null, response, errorUrl);
    }
}