package go.kr.project.carInspectionPenalty.registration.service.impl;

import egovframework.constant.TaskPrcsSttsConstants;
import egovframework.exception.MessageException;
import go.kr.project.api.model.VehicleApiResponseVO;
import go.kr.project.api.model.response.BasicResponse;
import go.kr.project.carInspectionPenalty.registration.mapper.CarFfnlgTrgtMapper;
import go.kr.project.carInspectionPenalty.registration.model.CarFfnlgTrgtVO;
import go.kr.project.carInspectionPenalty.registration.service.ComparisonService;
import go.kr.project.system.user.mapper.UserMapper;
import go.kr.project.system.user.model.SystemUserVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

/**
 * 과태료 대상 비교 서비스 구현체
 *
 * <p>각 비교 로직을 독립적인 메서드로 분리하여 관리합니다.</p>
 * <p>새로운 비교 조건 추가 시: private 메서드를 추가하고 executeComparison()에서 호출</p>
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ComparisonServiceImpl extends EgovAbstractServiceImpl implements ComparisonService {

    private final CarFfnlgTrgtMapper carFfnlgTrgtMapper;
    private final UserMapper userMapper;

    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");

    /**
     * 비교 로직 메인 메서드
     *
     * <p>순차적으로 각 비교 메서드를 실행하고, 하나라도 적용되면 즉시 종료합니다.</p>
     */
    @Override
    public String executeComparison(CarFfnlgTrgtVO existingData, VehicleApiResponseVO apiResponse, String userId) {
        String vhclno = existingData.getVhclno();
        log.info("========== 비교 로직 시작: {} ==========", vhclno);

        BasicResponse.Record basicInfo = apiResponse.getBasicInfo().getRecord().get(0);

        // ========== 1. 상품용 체크 ==========
        String productUseResult = checkProductUse(existingData, basicInfo);
        if (productUseResult != null) {
            log.info("========== 비교 로직 종료 (상품용): {} ==========", vhclno);
            return productUseResult;
        }

        // ========== 2. 이첩 체크 ==========
        String transferResult = checkTransfer(existingData, basicInfo, userId);
        if (transferResult != null) {
            log.info("========== 비교 로직 종료 (이첩): {} ==========", vhclno);
            return transferResult;
        }

        // ========== 3. 향후 추가될 비교 로직들 ==========
        // String investigationClosedResult = checkInvestigationClosed(existingData, basicInfo);
        // if (investigationClosedResult != null) {
        //     return investigationClosedResult;
        // }

        // 모든 비교 로직에 해당하지 않음
        log.info("========== 비교 로직 종료 (정상): {} ==========", vhclno);
        return null;
    }

    // ========================================
    // 비교 로직 메서드들
    // ========================================

    /**
     * 1. 상품용 체크
     *
     * <p>조건: 대표소유자성명(MBER_NM)에 "상품용" 문자열 포함</p>
     * <p>처리: TASK_PRCS_STTS_CD = 02, CAR_BSC_MTTR_INQ_FLNM = 소유자명</p>
     *
     * @return 02 (적용됨) 또는 null (미적용)
     */
    private String checkProductUse(CarFfnlgTrgtVO existingData, BasicResponse.Record basicInfo) {
        String vhclno = existingData.getVhclno();
        String mberNm = basicInfo.getMberNm();  // 대표소유자성명

        // 조건 체크
        if (mberNm == null || !mberNm.contains("상품용")) {
            log.debug("[상품용] 조건 미충족. 차량번호: {}, 소유자명: {}", vhclno, mberNm);
            return null;
        }

        log.info("[상품용] 조건 충족! 차량번호: {}, 소유자명: {}", vhclno, mberNm);

        // DB 업데이트
        existingData.setTaskPrcsSttsCd(TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_02_PRODUCT_USE);  // 상품용
        existingData.setTaskPrcsYmd(LocalDate.now().format(DATE_FORMATTER));
        existingData.setCarBscMttrInqFlnm(mberNm);  // 소유자명 저장
        existingData.setCarBscMttrInqSggCd(null);
        existingData.setCarBscMttrInqSggNm(null);

        int updateCount = carFfnlgTrgtMapper.update(existingData);
        if (updateCount == 0) {
            throw new MessageException(String.format("[상품용] 업데이트 실패: %s", vhclno));
        }

        log.info("[상품용] 처리 완료! 차량번호: {}", vhclno);
        return TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_02_PRODUCT_USE;
    }

    /**
     * 2. 이첩 체크 (OR 로직: 여러 조건 중 하나라도 만족하면 이첩)
     *
     * <p>처리: TASK_PRCS_STTS_CD = 03, CAR_BSC_MTTR_INQ_SGG_CD = 시군구코드, CAR_BSC_MTTR_INQ_SGG_NM = 시군구명</p>
     *
     * @return 03 (적용됨) 또는 null (미적용)
     */
    private String checkTransfer(CarFfnlgTrgtVO existingData, BasicResponse.Record basicInfo, String userId) {
        String vhclno = existingData.getVhclno();

        // ========== 이첩 조건들 (OR 로직: 하나라도 만족하면 이첩) ==========

        // 조건1: 법정동코드 불일치
        if (checkTransferCondition1_LegalDongMismatch(basicInfo, userId, vhclno)) {
            return processTransfer(existingData, basicInfo, vhclno, "법정동코드 불일치");
        }

        // 조건2: 향후 추가될 이첩 조건들 (예시)
        // if (checkTransferCondition2_OtherReason(basicInfo, userId, vhclno)) {
        //     return processTransfer(existingData, basicInfo, vhclno, "다른 사유");
        // }

        // 모든 이첩 조건에 해당하지 않음
        log.debug("[이첩] 모든 조건 미충족. 차량번호: {}", vhclno);
        return null;
    }

    /**
     * 이첩 조건1: 법정동코드 불일치
     * 사용본거지법정동코드 앞 4자리 != 사용자 조직코드 앞 4자리
     */
    private boolean checkTransferCondition1_LegalDongMismatch(BasicResponse.Record basicInfo, String userId, String vhclno) {
        String useStrnghldLegaldongCode = basicInfo.getUseStrnghldLegaldongCode();

        // 법정동코드 유효성 검사
        if (useStrnghldLegaldongCode == null || useStrnghldLegaldongCode.length() < 4) {
            log.debug("[이첩][조건1] 법정동코드 없음. 차량번호: {}", vhclno);
            return false;
        }

        // 사용자 정보 조회
        SystemUserVO userInfo = userMapper.selectUser(userId);
        if (userInfo == null || userInfo.getOrgCd() == null) {
            log.debug("[이첩][조건1] 사용자 정보 없음. 사용자ID: {}", userId);
            return false;
        }

        // 법정동코드 앞 4자리 vs 사용자 조직코드 앞 4자리 비교
        String legalDong4 = useStrnghldLegaldongCode.substring(0, 4);
        String userOrgCd = userInfo.getOrgCd();
        String userOrg4 = userOrgCd.length() >= 4 ? userOrgCd.substring(0, 4) : userOrgCd;

        if (legalDong4.equals(userOrg4)) {
            log.debug("[이첩][조건1] 법정동코드 일치. 차량번호: {}, 법정동: {}, 조직: {}",
                    vhclno, legalDong4, userOrg4);
            return false;
        }

        log.info("[이첩][조건1] 법정동코드 불일치! 차량번호: {}, 법정동: {}, 조직: {}",
                vhclno, legalDong4, userOrg4);
        return true;
    }

    /**
     * 이첩 처리 (공통 로직)
     */
    private String processTransfer(CarFfnlgTrgtVO existingData, BasicResponse.Record basicInfo,
                                     String vhclno, String reason) {
        log.info("[이첩] 조건 충족! 차량번호: {}, 사유: {}", vhclno, reason);

        // 시군구 코드 및 시군구명 조회
        String useStrnghldLegaldongCode = basicInfo.getUseStrnghldLegaldongCode();
        String sggCd = (useStrnghldLegaldongCode != null && useStrnghldLegaldongCode.length() >= 5)
                ? useStrnghldLegaldongCode.substring(0, 5)
                : (useStrnghldLegaldongCode != null ? useStrnghldLegaldongCode : "");

        String sggNm = carFfnlgTrgtMapper.selectSggNmBySggCd(sggCd);
        if (sggNm == null || sggNm.isEmpty()) {
            log.warn("[이첩] 시군구명 조회 실패. 시군구코드: {}", sggCd);
            sggNm = "";
        }

        // DB 업데이트
        existingData.setTaskPrcsSttsCd(TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_03_TRANSFER);  // 이첩
        existingData.setTaskPrcsYmd(LocalDate.now().format(DATE_FORMATTER));
        existingData.setCarBscMttrInqFlnm(null);
        existingData.setCarBscMttrInqSggCd(sggCd);  // 시군구 코드
        existingData.setCarBscMttrInqSggNm(sggNm);  // 시군구명

        int updateCount = carFfnlgTrgtMapper.update(existingData);
        if (updateCount == 0) {
            throw new MessageException(String.format("[이첩] 업데이트 실패: %s", vhclno));
        }

        log.info("[이첩] 처리 완료! 차량번호: {}, 시군구: {}({}), 사유: {}", vhclno, sggNm, sggCd, reason);
        return TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_03_TRANSFER;
    }

    /**
     * 3. 내사종결 체크 (예시 - 향후 추가)
     *
     * <p>조건: 차량이 말소된 경우 등</p>
     * <p>처리: TASK_PRCS_STTS_CD = 04</p>
     *
     * @return 04 (적용됨) 또는 null (미적용)
     */
    @SuppressWarnings("unused")
    private String checkInvestigationClosed(CarFfnlgTrgtVO existingData, BasicResponse.Record basicInfo) {
        String vhclno = existingData.getVhclno();
        String ersrRegistSeCode = basicInfo.getErsrRegistSeCode();  // 말소등록구분코드

        // 조건 체크: 말소된 차량인지
        if (ersrRegistSeCode == null || ersrRegistSeCode.isEmpty()) {
            log.debug("[내사종결] 조건 미충족. 차량번호: {}", vhclno);
            return null;
        }

        log.info("[내사종결] 조건 충족! 차량번호: {}, 말소구분: {}", vhclno, ersrRegistSeCode);

        // DB 업데이트
        existingData.setTaskPrcsSttsCd(TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_04_INVESTIGATION_CLOSED);  // 내사종결
        existingData.setTaskPrcsYmd(LocalDate.now().format(DATE_FORMATTER));
        // 필요한 추가 필드 설정

        int updateCount = carFfnlgTrgtMapper.update(existingData);
        if (updateCount == 0) {
            throw new MessageException(String.format("[내사종결] 업데이트 실패: %s", vhclno));
        }

        log.info("[내사종결] 처리 완료! 차량번호: {}", vhclno);
        return TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_04_INVESTIGATION_CLOSED;
    }

}
