package go.kr.project.carInspectionPenalty.registrationOm.service.impl.om_checker;

import egovframework.constant.TaskPrcsSttsConstants;
import egovframework.exception.MessageException;
import egovframework.util.DateUtil;
import go.kr.project.api.model.request.NewBasicRequest;
import go.kr.project.api.model.request.NewLedgerRequest;
import go.kr.project.api.model.response.NewBasicResponse;
import go.kr.project.api.model.response.NewLedgerResponse;
import go.kr.project.api.service.ExternalVehicleApiService;
import go.kr.project.api.service.VmisCarBassMatterInqireLogService;
import go.kr.project.api.service.VmisCarLedgerFrmbkLogService;
import go.kr.project.carInspectionPenalty.registrationOm.mapper.CarFfnlgTrgtIncmpMapper;
import go.kr.project.carInspectionPenalty.registrationOm.model.CarFfnlgTrgtIncmpVO;
import go.kr.project.carInspectionPenalty.registrationOm.service.impl.ComparisonOmRemarkBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.util.List;

/**
 * 미필 - 명의이전 소유자 확인 검증
 *
 * <p>부과일자 소유자가 상품용이 아닌 경우, 검사종료일 이후 명의이전 이력을 확인하여 처리</p>
 *
 * API 호출 순서:
 * 1) 자동차기본정보(차량번호, 부과일자=검사유효기간 종료일+146일) → 차대번호, 소유자명
 * 2) 자동차기본정보(차대번호, 부과일자=오늘) → 차량번호, 성명, 주민번호, 법정동코드
 * 3) 자동차등록원부(갑)(차량번호, 성명, 주민번호, 법정동코드) → 갑부 상세 List
 * 4) 자동차기본정보(차대번호, 부과일자=명의이전일자-1) → 소유자명
 *
 * 비교조건:
 * - 1단계: 소유자명에 "상품용" 미포함
 * - 2단계: 갑부 상세에서 다음 조건을 만족하는 명의이전(코드 11) 레코드 찾기
 *   • CHG_YMD > 검사유효기간 종료일 + 31일
 *   • 명의이전 중 마지막 일자
 *   • CHG_TASK_SE_CD == "11" (명의이전)
 * - 3단계: 4번 API 소유자명 확인
 *   • "상품용" 미포함 → 비고: 명의이전(날짜)
 *   • "상품용" 포함 → 비고: 명의이전(날짜) 이전소유자 상품용
 */
@Slf4j
@Component
public class OwnerTransferOmChecker extends AbstractComparisonOmChecker {

    public OwnerTransferOmChecker(CarFfnlgTrgtIncmpMapper carFfnlgTrgtIncmpMapper,
                                  ExternalVehicleApiService apiService,
                                  VmisCarBassMatterInqireLogService bassMatterLogService,
                                  VmisCarLedgerFrmbkLogService ledgerLogService) {
        super(carFfnlgTrgtIncmpMapper, apiService, bassMatterLogService, ledgerLogService);
    }

    @Override
    public String check(CarFfnlgTrgtIncmpVO existingData, String userOrgCd) {
        String vhclno = existingData.getVhclno();
        String levyCrtrYmd = existingData.getLevyCrtrYmd().replace("-", "");  // 미필: 검사유효기간 종료일 + 146일
        String inspVldPrd = existingData.getInspVldPrd();    // 검사유효기간

        // 검사유효기간에서 시작일과 종료일 추출
        String inspVldPrdStart = null;
        String inspVldPrdEnd = null;
        if (inspVldPrd != null && inspVldPrd.contains("~")) {
            String[] dates = inspVldPrd.split("~");
            inspVldPrdStart = dates[0].trim().replace("-", "");

            // 종료일 + 31일 계산
            if (dates.length > 1) {
                String endDateStr = dates[1].trim().replace("-", "");
                LocalDate endDate = DateUtil.parseDate(endDateStr);
                if (endDate != null) {
                    inspVldPrdEnd = DateUtil.formatLocalDate(endDate.plusDays(31), "yyyyMMdd");
                }
            }
        }

        if (inspVldPrdEnd == null) {
            log.debug("[명의이전-미필] 검사유효기간 종료일 없음 - 차량번호: {}", vhclno);
            return null;
        }

        try {

            log.info("[명의이전-미필] Step 0: 자동차기본정보 조회 - 차량번호: {}, 현재일", vhclno);
            NewBasicRequest step0Request = createBasicRequest(vhclno, null, LocalDate.now().format(DATE_FORMATTER));
            NewBasicResponse step0Response = apiService.getBasicInfo(step0Request);
            bassMatterLogService.updateCarFfnlgTrgtIdByTxIdNewTx(step0Response, existingData.getCarFfnlgTrgtIncmpId());

            if (step0Response == null || step0Response.getRecord() == null || step0Response.getRecord().isEmpty()) {
                log.warn("[명의이전-미필] Step 0 응답 없음 - 차량번호: {}", vhclno);
                return null;
            }

            NewBasicResponse.Record step0Record = step0Response.getRecord().get(0);
            String step0vin = step0Record.getVin();  // 차대번호

            // ========== Step 1: 자동차기본정보 조회 (차량번호, 부과일자=검사유효기간 종료일+146일) ==========
            log.info("[명의이전-미필] Step 1: 자동차기본정보 조회 - 차대번호: {}, 부과일자: {}", step0vin, levyCrtrYmd);

            NewBasicRequest step1Request = createBasicRequest(null, step0vin, levyCrtrYmd);
            NewBasicResponse step1Response = apiService.getBasicInfo(step1Request);
            bassMatterLogService.updateCarFfnlgTrgtIdByTxIdNewTx(step1Response, existingData.getCarFfnlgTrgtIncmpId());

            if (step1Response == null || step1Response.getRecord() == null || step1Response.getRecord().isEmpty()) {
                log.warn("[명의이전-미필] Step 1 응답 없음 - 차량번호: {}", vhclno);
                return null;
            }

            NewBasicResponse.Record step1Record = step1Response.getRecord().get(0);
            String vin = step1Record.getVin();  // 차대번호
            String step1OwnerName = step1Record.getRprsOwnrNm();  // 부과일자 기준 소유자명

            log.info("[명의이전-미필] Step 1 결과 - 차대번호: {}, 소유자명: {}", vin, step1OwnerName);

            // 조건 1: 소유자명에 "상품용" 미포함 확인 (포함되면 다른 Checker에서 처리)
            if (step1OwnerName != null && step1OwnerName.contains("상품용")) {
                log.debug("[명의이전-미필] 소유자명에 '상품용' 포함 - 차량번호: {}, 소유자명: {}", vhclno, step1OwnerName);
                return null;
            }

            log.info("[명의이전-미필] 소유자명에 '상품용' 미포함 확인! - 차량번호: {}, 소유자명: {}", vhclno, step1OwnerName);

            // ========== Step 2: 자동차기본정보 조회 (차대번호, 부과일자=오늘일자) ==========
            String today = LocalDate.now().format(DATE_FORMATTER);
            log.info("[명의이전-미필] Step 2: 자동차기본정보 조회 - 차대번호: {}, 오늘일자: {}", vin, today);

            NewBasicRequest step2Request = createBasicRequest(null, vin, today);
            NewBasicResponse step2Response = apiService.getBasicInfo(step2Request);
            bassMatterLogService.updateCarFfnlgTrgtIdByTxIdNewTx(step2Response, existingData.getCarFfnlgTrgtIncmpId());

            if (step2Response == null || step2Response.getRecord() == null || step2Response.getRecord().isEmpty()) {
                log.warn("[명의이전-미필] Step 2 응답 없음 - 차대번호: {}", vin);
                return null;
            }

            NewBasicResponse.Record step2Record = step2Response.getRecord().get(0);
            String currentVhclno = step2Record.getVhrno();
            String currentOwnerName = step2Record.getRprsOwnrNm();
            String currentIdecno = step2Record.getRprsvOwnrIdecno();
            String currentLegalDongCode = step2Record.getUsgsrhldStdgCd();

            log.info("[명의이전-미필] Step 2 결과 - 차량번호: {}, 성명: {}, 주민번호: {}, 법정동코드: {}",
                    currentVhclno, currentOwnerName, currentIdecno, currentLegalDongCode);

            // ========== Step 3: 자동차등록원부(갑) 조회 ==========
            log.info("[명의이전-미필] Step 3: 자동차등록원부(갑) 조회 - 차량번호: {}, 성명: {}, 주민번호: {}, 법정동코드: {}",
                    currentVhclno, currentOwnerName, currentIdecno, currentLegalDongCode);

            NewLedgerRequest step3Request = createLedgerRequest(currentVhclno, currentOwnerName, currentIdecno, currentLegalDongCode);
            NewLedgerResponse step3Response = apiService.getLedgerInfo(step3Request);
            ledgerLogService.updateCarFfnlgTrgtIdByTxIdNewTx(step3Response, existingData.getCarFfnlgTrgtIncmpId());

            if (step3Response == null) {
                log.warn("[명의이전-미필] Step 3 응답 없음 - 차량번호: {}", currentVhclno);
                return null;
            }

            List<NewLedgerResponse.Record> ledgerRecords = step3Response.getRecord();
            if (ledgerRecords == null || ledgerRecords.isEmpty()) {
                log.debug("[명의이전-미필] 갑부 상세 내역 없음 - 차량번호: {}", vhclno);
                return null;
            }

            // ========== 갑부 상세에서 조건에 맞는 레코드 찾기 ==========
            log.info("[명의이전-미필] 갑부 상세 레코드 검색 시작 - 검사유효기간 종료일: {}", inspVldPrdEnd);

            NewLedgerResponse.Record targetRecord = null;
            LocalDate latestChgDate = null;
            LocalDate inspVldPrdEndDate = DateUtil.parseDate(inspVldPrdEnd);

            for (NewLedgerResponse.Record record : ledgerRecords) {
                String chgYmd = record.getChgYmd();
                String chgTaskSeCd = record.getChgTaskSeCd();

                // 조건: CHG_TASK_SE_CD == "11" (명의이전)
                if (!"11".equals(chgTaskSeCd) || chgYmd == null) {
                    continue;
                }

                LocalDate chgDate = DateUtil.parseDate(chgYmd);
                if (chgDate == null) {
                    continue;
                }

                // 조건: CHG_YMD > 검사유효기간 종료일
                if (!chgDate.isAfter(inspVldPrdEndDate)) {
                    log.debug("[명의이전-미필] CHG_YMD <= 검사유효기간 종료일 - 변경일자: {}, 검사유효기간 종료일: {}", chgYmd, inspVldPrdEnd);
                    continue;
                }

                // 가장 마지막 일자 찾기
                if (latestChgDate == null || chgDate.isAfter(latestChgDate)) {
                    latestChgDate = chgDate;
                    targetRecord = record;
                    log.debug("[명의이전-미필] 조건 충족 레코드 발견 - 변경일자: {}, 변경업무: {}", chgYmd, chgTaskSeCd);
                }
            }

            if (targetRecord == null) {
                log.debug("[명의이전-미필] 조건에 맞는 명의이전 레코드 없음 - 차량번호: {}", vhclno);
                return null;
            }

            String targetChgYmd = targetRecord.getChgYmd();
            log.info("[명의이전-미필] 조건 충족 레코드 선택! 변경일자: {}, 변경업무: {}", targetChgYmd, targetRecord.getChgTaskSeNm());

            // ========== Step 4: 자동차기본정보 조회 (차대번호, 부과일자=명의이전일자-1) ==========
            LocalDate targetDate = DateUtil.parseDate(targetChgYmd);
            LocalDate step4Date = targetDate.minusDays(1);
            String step4Ymd = step4Date.format(DATE_FORMATTER);

            log.info("[명의이전-미필] Step 4: 자동차기본정보 조회 - 차대번호: {}, 부과일자: {} (명의이전일자-1)", vin, step4Ymd);

            NewBasicRequest step4Request = createBasicRequest(null, vin, step4Ymd);
            NewBasicResponse step4Response = apiService.getBasicInfo(step4Request);
            bassMatterLogService.updateCarFfnlgTrgtIdByTxIdNewTx(step4Response, existingData.getCarFfnlgTrgtIncmpId());

            if (step4Response == null || step4Response.getRecord() == null || step4Response.getRecord().isEmpty()) {
                log.warn("[명의이전-미필] Step 4 응답 없음 - 차대번호: {}, 부과일자: {}", vin, step4Ymd);
                return null;
            }

            NewBasicResponse.Record step4Record = step4Response.getRecord().get(0);
            String step4OwnerName = step4Record.getRprsOwnrNm();  // 명의이전일자-1 시점의 소유자명

            log.info("[명의이전-미필] Step 4 결과 - 소유자명: {}", step4OwnerName);

            // ========== 시군구명 조회 ==========
            String usgsrhldStdgCd = step1Record.getUsgsrhldStdgCd();
            String sggCd = (usgsrhldStdgCd != null && usgsrhldStdgCd.length() >= 5) ? usgsrhldStdgCd.substring(0, 5) : usgsrhldStdgCd;
            String sggNm = carFfnlgTrgtIncmpMapper.selectSggNmBySggCd(sggCd);
            String ownerNm = step1Record.getRprsOwnrNm();

            // ========== 소유자명 상품용 포함 여부에 따라 처리 분기 ==========
            String taskPrcsSttsCd;
            String rmrk;
            String rmrkDtl;

            if (step4OwnerName != null && step4OwnerName.contains("상품용")) {
                // 상품용 포함
                log.info("[명의이전-미필] 명의이전 전 소유자가 상품용");
                taskPrcsSttsCd = TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_01_RCPT; // 접수

                rmrk = ComparisonOmRemarkBuilder.buildProductCloseLevyRemark(targetRecord);
                rmrkDtl = ComparisonOmRemarkBuilder.buildProductCloseLevyRemarkDetail(
                        vhclno, inspVldPrdEnd, levyCrtrYmd, step1OwnerName, targetChgYmd, step4OwnerName);
            } else {
                // 상품용 미포함
                log.info("[명의이전-미필] 명의이전 전 소유자가 상품용 아님");
                taskPrcsSttsCd = TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_01_RCPT; // 접수

                rmrk = ComparisonOmRemarkBuilder.buildOwnerChangeRemark(targetRecord, sggNm, ownerNm, vhclno);
                rmrkDtl = ComparisonOmRemarkBuilder.buildOwnerChangeRemarkDetail(
                        vhclno, inspVldPrdEnd, levyCrtrYmd, step1OwnerName, targetChgYmd, step4OwnerName);
            }

            log.info("[명의이전-미필] 모든 조건 충족! 차량번호: {}, 처리상태: {}", vhclno, taskPrcsSttsCd);

            // ========== DB 업데이트 ==========
            existingData.setCarBassMatterInqireId(step1Response.getGeneratedId());
            existingData.setCarLedgerFrmbkId(step3Response.getGeneratedId());
            existingData.setTaskPrcsSttsCd(taskPrcsSttsCd);
            existingData.setTaskPrcsYmd(LocalDate.now().format(DATE_FORMATTER_DASH));
            existingData.setCarBscMttrInqFlnm(step4OwnerName);
            existingData.setCarRegFrmbkChgTaskSeCd(targetRecord.getChgTaskSeCd());
            existingData.setCarRegFrmbkChgTaskSeNm(targetRecord.getChgTaskSeNm());
            existingData.setCarRegFrmbkChgYmd(targetRecord.getChgYmd());
            existingData.setCarRegFrmbkDtl(ComparisonOmRemarkBuilder.buildLedgerRecordDetail(targetRecord));
            existingData.setRmrk(rmrk);
            existingData.setRmrkDtl(rmrkDtl);

            int updateCount = carFfnlgTrgtIncmpMapper.update(existingData);
            if (updateCount == 0) {
                throw new MessageException(String.format("[명의이전-미필] 업데이트 실패: %s", vhclno));
            }

            log.info("[명의이전-미필] 처리 완료! 차량번호: {}, 처리상태: {}", vhclno, taskPrcsSttsCd);
            return taskPrcsSttsCd;

        } catch (Exception e) {
            log.error("[명의이전-미필] 검증 중 오류 발생 - 차량번호: {}", vhclno, e);
            throw new MessageException(String.format("[명의이전-미필] 검증 중 오류 발생 - 차량번호: %s", vhclno), e);
        }
    }
}
