package com.eactive.eai.rms.ext.djb.smsauth;

import com.eactive.apim.portal.user.entity.UserInfo;
import com.eactive.eai.rms.common.interceptor.InterceptorSkipController;
import com.eactive.eai.rms.common.login.LoginVo;
import com.eactive.eai.rms.common.login.MainController;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@Slf4j
@Controller
@RequestMapping("/sms-auth")
public class SmsAuthController implements InterceptorSkipController {

    private final MainController mainController;
    private final SmsAuthService smsAuthService;

    public SmsAuthController(MainController mainController, SmsAuthService smsAuthService) {
        this.mainController = mainController;
        this.smsAuthService = smsAuthService;
    }

    private SmsAuthService getSmsAuthService() {
        return smsAuthService;
    }

    /**
     * SMS 인증번호 발송
     */
    @RequestMapping(value = "/send.json", method = RequestMethod.POST)
    @ResponseBody
    public SmsAuthDto sendAuthCode(HttpServletRequest request) {
        HttpSession session = request.getSession();
        UserInfo userInfo = getSmsAuthService().getUserInfoFromSession(session);

        if (userInfo == null) {
            log.warn("SMS 인증 세션 정보 없음 - send 요청");
            return SmsAuthDto.builder()
                    .sent(false)
                    .errorMessage("인증 세션이 만료되었습니다. 다시 로그인해주세요.")
                    .build();
        }

        if (!getSmsAuthService().hasValidPhoneNumber(userInfo)) {
            log.warn("유효한 휴대폰번호 없음 - userId: {}", userInfo.getUserid());
            return SmsAuthDto.builder()
                    .sent(false)
                    .errorMessage("휴대폰번호가 등록되어 있지 않습니다. 관리자에게 문의하세요.")
                    .build();
        }

        // 인증번호 생성 및 발송
        String authCode = getSmsAuthService().generateAuthCode();
        boolean sent = getSmsAuthService().sendAuthCode(userInfo, authCode);

        if (sent) {
            // 세션에 인증번호 저장 (기존 UserInfo, LoginVo 유지)
            LoginVo loginVo = getSmsAuthService().getLoginVoFromSession(session);
            getSmsAuthService().setupAuthSession(session, userInfo, loginVo, authCode);

            return SmsAuthDto.builder()
                    .sent(true)
                    .maskedPhone(getSmsAuthService().maskPhoneNumber(userInfo.getCphnno()))
                    .expiresAt(getSmsAuthService().getExpiresAt(session))
                    .resendableAt(getSmsAuthService().getResendableAt(session))
                    .build();
        } else {
            return SmsAuthDto.builder()
                    .sent(false)
                    .errorMessage("인증번호 발송에 실패했습니다. 잠시 후 다시 시도해주세요.")
                    .build();
        }
    }

    /**
     * SMS 인증번호 재발송
     */
    @RequestMapping(value = "/resend.json", method = RequestMethod.POST)
    @ResponseBody
    public SmsAuthDto resendAuthCode(HttpServletRequest request) {
        HttpSession session = request.getSession();
        UserInfo userInfo = getSmsAuthService().getUserInfoFromSession(session);

        if (userInfo == null) {
            log.warn("SMS 인증 세션 정보 없음 - resend 요청");
            return SmsAuthDto.builder()
                    .sent(false)
                    .errorMessage("인증 세션이 만료되었습니다. 다시 로그인해주세요.")
                    .build();
        }

        if (!getSmsAuthService().canResend(session)) {
            long waitTime = getSmsAuthService().getResendWaitTime(session);
            log.debug("재발송 대기 중 - 남은 시간: {}ms", waitTime);
            return SmsAuthDto.builder()
                    .sent(false)
                    .errorMessage(String.format("%.0f초 후에 재발송이 가능합니다.", Math.ceil(waitTime / 1000.0)))
                    .resendableAt(getSmsAuthService().getResendableAt(session))
                    .build();
        }

        // 새 인증번호 생성 및 발송
        String authCode = getSmsAuthService().generateAuthCode();
        boolean sent = getSmsAuthService().sendAuthCode(userInfo, authCode);

        if (sent) {
            LoginVo loginVo = getSmsAuthService().getLoginVoFromSession(session);
            getSmsAuthService().setupAuthSession(session, userInfo, loginVo, authCode);

            return SmsAuthDto.builder()
                    .sent(true)
                    .maskedPhone(getSmsAuthService().maskPhoneNumber(userInfo.getCphnno()))
                    .expiresAt(getSmsAuthService().getExpiresAt(session))
                    .resendableAt(getSmsAuthService().getResendableAt(session))
                    .build();
        } else {
            return SmsAuthDto.builder()
                    .sent(false)
                    .errorMessage("인증번호 발송에 실패했습니다. 잠시 후 다시 시도해주세요.")
                    .build();
        }
    }

    /**
     * SMS 인증번호 검증 및 로그인 완료
     */
    @RequestMapping(value = "/verify.json", method = RequestMethod.POST)
    @ResponseBody
    public SmsAuthDto verifyAuthCode(HttpServletRequest request,
                                     @RequestParam("authCode") String authCode) {
        HttpSession session = request.getSession();
        UserInfo userInfo = getSmsAuthService().getUserInfoFromSession(session);
        LoginVo loginVo = getSmsAuthService().getLoginVoFromSession(session);

        if (userInfo == null || loginVo == null) {
            log.warn("SMS 인증 세션 정보 없음 - verify 요청");
            return SmsAuthDto.builder()
                    .success(false)
                    .errorMessage("인증 세션이 만료되었습니다. 다시 로그인해주세요.")
                    .build();
        }

        if (getSmsAuthService().isExpired(session)) {
            log.warn("SMS 인증번호 만료됨 - userId: {}", userInfo.getUserid());
            getSmsAuthService().clearAuthSession(session);
            return SmsAuthDto.builder()
                    .success(false)
                    .errorMessage("인증번호가 만료되었습니다. 다시 시도해주세요.")
                    .build();
        }

        if (!getSmsAuthService().validateAuthCode(session, authCode)) {
            log.warn("SMS 인증번호 불일치 - userId: {}", userInfo.getUserid());
            return SmsAuthDto.builder()
                    .success(false)
                    .errorMessage("인증번호가 일치하지 않습니다.")
                    .build();
        }

        // 인증 성공 - 로그인 완료 처리
        try {
            getSmsAuthService().clearAuthSession(session);

            // MainController의 loadUserInfoAndSetupSession 호출
            String result = mainController.loadUserInfoAndSetupSession(request, session, loginVo, userInfo);

            // result가 "redirect:/main.do" 형태이면 redirectUrl 추출
            String contextPath = request.getContextPath();
            String redirectUrl = contextPath + "/main.do";
            if (result != null && result.startsWith("redirect:")) {
                String path = result.substring("redirect:".length());
                // 이미 contextPath가 포함되어 있지 않으면 추가
                if (!path.startsWith(contextPath)) {
                    redirectUrl = contextPath + path;
                } else {
                    redirectUrl = path;
                }
            }

            // serviceType 파라미터 추가
            String serviceType = request.getParameter("serviceType");
            if (serviceType == null) {
                serviceType = (String) session.getAttribute("serviceType");
            }
            if (serviceType != null && !redirectUrl.contains("serviceType")) {
                redirectUrl += (redirectUrl.contains("?") ? "&" : "?") + "serviceType=" + serviceType;
            }

            log.info("SMS 인증 성공 - 로그인 완료 - userId: {}", userInfo.getUserid());
            return SmsAuthDto.builder()
                    .success(true)
                    .redirectUrl(redirectUrl)
                    .build();

        } catch (Exception e) {
            log.error("SMS 인증 후 로그인 처리 실패", e);
            return SmsAuthDto.builder()
                    .success(false)
                    .errorMessage("로그인 처리 중 오류가 발생했습니다.")
                    .build();
        }
    }

    /**
     * SMS 인증 상태 조회
     */
    @RequestMapping(value = "/status.json", method = RequestMethod.GET)
    @ResponseBody
    public SmsAuthDto getStatus(HttpServletRequest request) {
        HttpSession session = request.getSession();
        UserInfo userInfo = getSmsAuthService().getUserInfoFromSession(session);

        if (userInfo == null) {
            return SmsAuthDto.builder()
                    .enabled(false)
                    .errorMessage("인증 세션이 없습니다.")
                    .build();
        }

        return SmsAuthDto.builder()
                .enabled(getSmsAuthService().isEnabled())
                .maskedPhone(getSmsAuthService().maskPhoneNumber(userInfo.getCphnno()))
                .expiresAt(getSmsAuthService().getExpiresAt(session))
                .resendableAt(getSmsAuthService().getResendableAt(session))
                .build();
    }
}
