package com.eactive.eai.rms.ext.kjb.sso;

import com.eactive.apim.portal.user.entity.UserInfo;
import com.eactive.eai.common.seed.Seed;
import com.eactive.eai.rms.common.context.MonitoringContext;
import com.eactive.eai.rms.common.datasource.DataSourceType;
import com.eactive.eai.rms.common.datasource.DataSourceTypeManager;
import com.eactive.eai.rms.common.interceptor.InterceptorSkipController;
import com.eactive.eai.rms.common.login.MainController;
import com.eactive.eai.rms.common.util.CommonConstants;
import com.eactive.eai.rms.data.entity.man.user.UserInfoService;
import com.eactive.eai.rms.data.entity.man.user.UserRole;
import com.eactive.eai.rms.data.entity.man.user.UserRoleId;
import com.eactive.eai.rms.data.entity.man.user.UserRoleService;
import com.eactive.eai.rms.data.entity.man.user.UserServiceTypeService;
import com.eactive.eai.rms.onl.apim.masking.MaskingUtils;
//import com.eactive.ext.kjb.common.KjbProperty;
//import com.eactive.ext.kjb.common.KjbPropertyHolder;
//import com.eactive.ext.kjb.sso.KjbSsoModule;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Optional;
import java.util.Properties;

@Slf4j
@Controller
public class SsoController implements InterceptorSkipController {

    private final UserInfoService userInfoService;
    private final UserRoleService userRoleService;
    private final UserServiceTypeService userServiceTypeService;
    private final MonitoringContext monitoringContext;
    private final MainController mainController;

    public SsoController(UserInfoService userInfoService,
                         UserRoleService userRoleService,
                         UserServiceTypeService userServiceTypeService,
                         MonitoringContext monitoringContext,
                         MainController mainController) {
        this.userInfoService = userInfoService;
        this.userRoleService = userRoleService;
        this.userServiceTypeService = userServiceTypeService;
        this.monitoringContext = monitoringContext;
        this.mainController = mainController;
    }

//    private KjbSsoModule getSsoModule() {
//        return KjbSsoModule.getInstance();
//    }
//
//    private KjbProperty getProperty() {
//        return KjbPropertyHolder.get();
//    }

//    @RequestMapping(value = "/sso/login.do")
//    public String login(HttpServletRequest req, HttpServletResponse res,
//                        @RequestParam(name = "UURL", required = false) String uurl) throws Exception {
//        HttpSession session = req.getSession();
//        String ssoId = getSsoModule().getSsoId(req);
//
//        log.debug("ssoId : {}", ssoId);
//        log.debug("uurl : {}", uurl);
//
//        // 디버깅용 쿠키 목록 출력
//        if (log.isDebugEnabled()) {
//            Cookie[] cookies = req.getCookies();
//            if (cookies == null || cookies.length == 0) {
//                log.debug("No cookies");
//            } else {
//                for (Cookie c : cookies) {
//                    log.debug("Cookie[{}] : Domain={}, Path={}",
//                            c.getName(), c.getDomain(), c.getPath());
//                }
//            }
//        }
//
//        if (StringUtils.isEmpty(uurl)) {
//            uurl = getSsoModule().getAscpUrl();
//            log.debug("UURL is empty, set to ASCP URL");
//            log.debug("uurl : {}", uurl);
//        }
//
//        if (ssoId == null) {
//            getSsoModule().goLoginPage(res, uurl);
//            return null;
//        } else {
//            // EAM 세션 검증
//            String retCode = getSsoModule().getEamSessionCheck(req, res);
//            log.debug("retCode : {}", retCode);
//
//            log.debug("Property - sso.ignore_validation = {}", getProperty().isSsoIgnoreValidation());
//            if (!getProperty().isSsoIgnoreValidation() && !"0".equalsIgnoreCase(retCode)) {
//                // SSO 검증 실패 시 에러 메시지 설정 및 로그인 페이지로 이동
//                log.warn("SSO 검증 실패 - retCode: {}, ssoId: {}", retCode, ssoId);
//                session.setAttribute("resultMsg", "SSO 로그인을 실패 하였습니다. (오류코드: " + retCode + ") 다른 로그인 방식을 시도 하세요");
//                return "redirect:/loginForm.do";
//            }
//
//            if (StringUtils.isEmpty(ssoId)) {
//                session.setAttribute("resultMsg", "SSO 인증 정보를 획득하지 못했습니다.");
//                return "redirect:/loginForm.do";
//            }
//
//            if (getProperty().isSsoSyncInfo()) {
//                // 기본 정보
//                Properties info = getSsoModule().getUserInfos(ssoId);
//                // 확장 정보
//                Properties extendedInfo = getSsoModule().getUserExFields(ssoId);
//
//                // 필수 필드 검증
//                try {
//                    validateRequiredFields(info, extendedInfo);
//                } catch (IllegalStateException e) {
//                    log.warn("SSO 필수 필드 검증 실패: {}", e.getMessage());
//                    session.setAttribute("resultMsg", e.getMessage());
//                    return "redirect:/loginForm.do";
//                }
//
//                // 사용자 정보 로깅 (개인정보 마스킹 처리)
//                String userId = info.getProperty("USERID");
//                String name = info.getProperty("NAME");
//                String email = info.getProperty("EMAIL");
//                String cellPhoneNo = extendedInfo != null ? extendedInfo.getProperty("CELLPHONENO") : null;
//
//                log.info("SSO 로그인 시도 - userId: {}", userId);
//                log.debug("SSO 사용자 정보 - userId: {}, name: {}, phone: {}, email: {}",
//                        userId,
//                        MaskingUtils.maskName(name),
//                        MaskingUtils.maskPhoneNumber(cellPhoneNo),
//                        MaskingUtils.maskEmailId(email));
//
//                // 사용자 생성 또는 업데이트
//                UserInfo userInfo = findOrCreateUser(info, extendedInfo);
//
//                // 로그인 세션 설정 (MainController 위임)
//                log.info("SSO 로그인 성공 - userId: {}", userId);
//                return mainController.setupSsoLoginSession(req, userInfo);
//            } else {
//                // 동기화 비활성화 모드: 기존 사용자는 업데이트 없이, 신규 사용자는 최소 정보로 생성
//                log.info("SSO 동기화 비활성화 모드로 로그인 처리 - ssoId: {}", ssoId);
//
//                UserInfo userInfo = findOrCreateUserWithoutSync(ssoId);
//
//                log.info("SSO 로그인 성공 (동기화 비활성화 모드) - userId: {}", ssoId);
//                return mainController.setupSsoLoginSession(req, userInfo);
//            }
//        }
//    }

    /**
     * 필수 필드 검증
     */
    private void validateRequiredFields(Properties info, Properties extendedInfo) throws IllegalStateException {
        validateField(info, "USERID", "사용자ID");
        validateField(info, "NAME", "사용자명");
        validateField(extendedInfo, "CELLPHONENO", "휴대폰번호");
    }

    private void validateField(Properties props, String key, String fieldName) {
        String value = props != null ? props.getProperty(key) : null;
        if (StringUtils.isEmpty(value)) {
            throw new IllegalStateException(fieldName + " - SSO 서버로 부터 전달 받지 못했습니다.");
        }
    }

    /**
     * 사용자 조회 또는 생성
     */
    private UserInfo findOrCreateUser(Properties info, Properties extendedInfo) throws Exception {
        String userId = info.getProperty("USERID");

        // 대소문자 구분 없이 검색
        Optional<UserInfo> existingUser = userInfoService.findByUserIdIgnoreCase(userId);

        if (existingUser.isPresent()) {
            return updateUserIfNeeded(existingUser.get(), info, extendedInfo);
        } else {
            return createNewUser(info, extendedInfo);
        }
    }

    /**
     * 사용자 조회 또는 생성 (동기화 비활성화 모드)
     * - 기존 사용자: 정보 업데이트 없이 그대로 반환
     * - 신규 사용자: userId를 username으로 사용하여 최소 정보로 생성
     */
    private UserInfo findOrCreateUserWithoutSync(String ssoId) throws Exception {
        // 대소문자 구분 없이 검색
        Optional<UserInfo> existingUser = userInfoService.findByUserIdIgnoreCase(ssoId);

        if (existingUser.isPresent()) {
            log.debug("동기화 비활성화 모드 - 기존 사용자 발견, 정보 업데이트 없이 로그인 처리: {}", ssoId);
            return existingUser.get();
        } else {
            return createNewUserWithMinimalInfo(ssoId);
        }
    }

    /**
     * 최소 정보로 신규 사용자 생성 (동기화 비활성화 모드)
     * - username을 userId와 동일하게 설정
     */
    private UserInfo createNewUserWithMinimalInfo(String userId) throws Exception {
        UserInfo userInfo = new UserInfo();
        userInfo.setUserid(userId);
        userInfo.setUsername(userId);  // username = userId
        userInfo.setPassword(Seed.encrypt("!" + userId));
        userInfo.setRoleidnfiname(CommonConstants.DEPT_DEVELOPER);

        userInfoService.save(userInfo);

        // 기본 역할 할당
        String roleId = monitoringContext.getStringProperty(
                MonitoringContext.USER_DEFAULT_RULE, "newbie");
        UserRole userRole = new UserRole();
        userRole.setId(new UserRoleId(userId, roleId));
        userRoleService.save(userRole);

        // 서비스 타입 할당
        DataSourceTypeManager.getDynamicDataSourceTypes().stream()
                .map(DataSourceType::getName)
                .forEach(type -> userServiceTypeService.insertUserServiceType(userId, type));

        log.info("동기화 비활성화 모드 - 신규 사용자 생성 완료 (최소 정보): {}", userId);
        return userInfo;
    }

    /**
     * 신규 사용자 생성
     */
    private UserInfo createNewUser(Properties info, Properties extendedInfo) throws Exception {
        String userId = info.getProperty("USERID");
        String name = info.getProperty("NAME");
        String email = info.getProperty("EMAIL");
        String cellPhoneNo = extendedInfo != null ? extendedInfo.getProperty("CELLPHONENO") : null;
        String positionName = extendedInfo != null ? extendedInfo.getProperty("LEGACYPOSITIONNAME") : null;
        String deptName = extendedInfo != null ? extendedInfo.getProperty("LEGACYDEPTNAME") : null;

        UserInfo userInfo = new UserInfo();
        userInfo.setUserid(userId);
        userInfo.setUsername(name);
        userInfo.setPassword(Seed.encrypt("!" + userId));
        userInfo.setCphnno(cleanPhoneNumber(cellPhoneNo));
        userInfo.setRoleidnfiname(CommonConstants.DEPT_DEVELOPER);

        // 부가 필드 설정 (값이 있을 경우만)
        if (StringUtils.isNotEmpty(email)) {
            userInfo.setEmad(email);
        }
        if (StringUtils.isNotEmpty(positionName)) {
            userInfo.setJobtlname(positionName);
        }
        if (StringUtils.isNotEmpty(deptName)) {
            userInfo.setDvsnname(deptName);
        }

        userInfoService.save(userInfo);

        // 기본 역할 할당
        String roleId = monitoringContext.getStringProperty(
                MonitoringContext.USER_DEFAULT_RULE, "newbie");
        UserRole userRole = new UserRole();
        userRole.setId(new UserRoleId(userId, roleId));
        userRoleService.save(userRole);

        // 서비스 타입 할당
        DataSourceTypeManager.getDynamicDataSourceTypes().stream()
                .map(DataSourceType::getName)
                .forEach(type -> userServiceTypeService.insertUserServiceType(userId, type));

        log.info("SSO 신규 사용자 생성 완료 - userId: {}", userId);
        return userInfo;
    }

    /**
     * 기존 사용자 정보 업데이트 (변경된 필드만)
     */
    private UserInfo updateUserIfNeeded(UserInfo userInfo, Properties info, Properties extendedInfo) {
        boolean updated = false;
        String userId = userInfo.getUserid();

        String name = info.getProperty("NAME");
        String email = info.getProperty("EMAIL");
        String cellPhoneNo = extendedInfo != null ? extendedInfo.getProperty("CELLPHONENO") : null;
        String positionName = extendedInfo != null ? extendedInfo.getProperty("LEGACYPOSITIONNAME") : null;
        String deptName = extendedInfo != null ? extendedInfo.getProperty("LEGACYDEPTNAME") : null;

        // 사용자명 업데이트
        if (StringUtils.isNotEmpty(name) && !name.equals(userInfo.getUsername())) {
            userInfo.setUsername(name);
            updated = true;
        }

        // 휴대폰번호 업데이트
        String cleanedPhone = cleanPhoneNumber(cellPhoneNo);
        if (StringUtils.isNotEmpty(cleanedPhone) && !cleanedPhone.equals(userInfo.getCphnno())) {
            userInfo.setCphnno(cleanedPhone);
            updated = true;
        }

        // 이메일 업데이트
        if (StringUtils.isNotEmpty(email) && !email.equals(userInfo.getEmad())) {
            userInfo.setEmad(email);
            updated = true;
        }

        // 직위명 업데이트
        if (StringUtils.isNotEmpty(positionName) && !positionName.equals(userInfo.getJobtlname())) {
            userInfo.setJobtlname(positionName);
            updated = true;
        }

        // 부서명 업데이트
        if (StringUtils.isNotEmpty(deptName) && !deptName.equals(userInfo.getDvsnname())) {
            userInfo.setDvsnname(deptName);
            updated = true;
        }

        if (updated) {
            userInfoService.save(userInfo);
            log.info("SSO 사용자 정보 업데이트 완료 - userId: {}", userId);
        }

        return userInfo;
    }

    /**
     * 휴대폰번호에서 숫자만 추출
     */
    private String cleanPhoneNumber(String phone) {
        if (StringUtils.isEmpty(phone)) {
            return null;
        }
        return phone.replaceAll("[^0-9]", "");
    }
}
