package go.kr.project.api.internal.service.impl;

import go.kr.project.api.config.ApiConstant;
import go.kr.project.api.internal.service.VmisCarBassMatterInqireService;
import go.kr.project.api.internal.service.VmisCarLedgerFrmbkService;
import go.kr.project.api.model.Envelope;
import go.kr.project.api.model.VehicleApiResponseVO;
import go.kr.project.api.model.request.BasicRequest;
import go.kr.project.api.model.request.LedgerRequest;
import go.kr.project.api.model.response.BasicResponse;
import go.kr.project.api.model.response.LedgerResponse;
import go.kr.project.api.service.VehicleInfoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;

/**
 * 내부 VMIS 모듈을 직접 호출하는 차량 정보 조회 서비스 구현체
 *
 * <p>이 구현체는 외부 REST API 호출 없이 내부 VMIS 모듈을 직접 사용하여
 * 정부 시스템과 통신합니다. 네트워크 오버헤드가 없어 성능이 향상됩니다.</p>
 *
 * <h3>활성화 조건:</h3>
 * <pre>
 * # application.yml
 * vmis:
 *   integration:
 *     mode: internal
 * </pre>
 *
 * <h3>처리 흐름:</h3>
 * <ol>
 *   <li>차량번호를 받아 BasicRequest, LedgerRequest 생성</li>
 *   <li>VmisCarBassMatterInqireService.basic() 호출 (기본정보)</li>
 *   <li>VmisCarLedgerFrmbkService.ledger() 호출 (등록원부)</li>
 *   <li>BasicResponse, LedgerResponse를 직접 VehicleApiResponseVO에 설정</li>
 *   <li>VehicleApiResponseVO로 결과 반환</li>
 * </ol>
 *
 * @see VehicleInfoService
 * @see VmisCarBassMatterInqireService
 * @see VmisCarLedgerFrmbkService
 */
@Slf4j
@Service
@RequiredArgsConstructor
@ConditionalOnProperty(name = "vmis.integration.mode", havingValue = "internal")
public class InternalVehicleInfoServiceImpl extends EgovAbstractServiceImpl implements VehicleInfoService {

    private final VmisCarBassMatterInqireService carBassMatterInqireService;
    private final VmisCarLedgerFrmbkService carLedgerFrmbkService;
    private final go.kr.project.carInspectionPenalty.history.service.VehicleApiHistoryService vehicleApiHistoryService;


    @Override
    public VehicleApiResponseVO getVehicleInfo(BasicRequest basicRequest) {
        String vehicleNumber = basicRequest.getVhrno();
        log.info("[Internal Mode] 차량 정보 조회 시작 - 차량번호: {}, 부과기준일: {}, 조회구분: {}",
                vehicleNumber, basicRequest.getLevyStdde(), basicRequest.getInqireSeCode());

        VehicleApiResponseVO response = new VehicleApiResponseVO();
        response.setVhrno(vehicleNumber);

        try {
            // 1. 차량 기본정보 조회
            // 중요 로직: BasicRequest 전체를 사용하여 조회 (RequestEnricher가 나머지 채움)
            BasicResponse basicInfo = getBasicInfo(basicRequest);
            response.setBasicInfo(basicInfo);

            // 2. 자동차 등록원부 조회
            // 중요 로직: 통합 조회 시에는 차량번호와 기본정보를 바탕으로 LedgerRequest 생성 (RequestEnricher가 나머지 채움)
            LedgerRequest ledgerRequest = new LedgerRequest();
            ledgerRequest.setVhrno(vehicleNumber);
            ledgerRequest.setOnesInformationOpen("1"); //개인정보공개 {1:소유자공개, 2:비공개, 3:비공개(주민등록번호), 4:비공개(사용본거지)}

            // basicInfo에서 민원인 정보 가져오기
            if (basicInfo != null && basicInfo.getRecord() != null && !basicInfo.getRecord().isEmpty()) {
                BasicResponse.Record record = basicInfo.getRecord().get(0);
                ledgerRequest.setCpttrNm(record.getMberNm());           // 민원인성명
                ledgerRequest.setCpttrIhidnum(record.getMberSeNo());    // 민원인주민번호
            }

            // 고정값 설정
            ledgerRequest.setCpttrLegaldongCode(null);  // 민원인법정동코드

            LedgerResponse ledgerInfo = getLedgerInfo(ledgerRequest);
            response.setLedgerInfo(ledgerInfo);

            // 3. 결과 검증
            if (basicInfo != null && ApiConstant.CNTC_RESULT_CODE_SUCCESS.equals(basicInfo.getCntcResultCode())) {
                response.setSuccess(true);
                response.setMessage("조회 성공");
                log.info("[Internal Mode] 차량번호 {} 조회 성공", vehicleNumber);

                // 4. API 호출 성공 시 히스토리 ID 조회 및 설정
                try {
                    String carBassMatterInqireId = vehicleApiHistoryService.selectLatestCarBassMatterInqireIdByVhclno(vehicleNumber);
                    String carLedgerFrmbkId = vehicleApiHistoryService.selectLatestCarLedgerFrmbkIdByVhclno(vehicleNumber);
                    response.setCarBassMatterInqireId(carBassMatterInqireId);
                    response.setCarLedgerFrmbkId(carLedgerFrmbkId);
                    log.debug("[Internal Mode] 히스토리 ID 설정 완료 - 차량번호: {}, 기본정보ID: {}, 원부ID: {}",
                            vehicleNumber, carBassMatterInqireId, carLedgerFrmbkId);
                } catch (Exception e) {
                    log.warn("[Internal Mode] 히스토리 ID 조회 실패 - 차량번호: {}", vehicleNumber, e);
                    // ID 조회 실패는 치명적이지 않으므로 계속 진행
                }
            } else {
                response.setSuccess(false);
                response.setMessage(basicInfo != null ? basicInfo.getCntcResultDtls() : "조회 실패");
                log.warn("[Internal Mode] 차량번호 {} 조회 실패 - {}", vehicleNumber, response.getMessage());
            }

        } catch (Exception e) {
            response.setSuccess(false);
            response.setMessage("내부 API 호출 오류: " + e.getMessage());
            log.error("[Internal Mode] 차량번호 {} 내부 API 호출 중 오류 발생", vehicleNumber, e);
        }

        return response;
    }


    /**
     * 차량 기본정보 조회 (내부 모듈 직접 호출)
     * 중요 로직: 기본정보 조회는 BasicRequest 전체를 받아서 내부 서비스에 전달
     *
     * @param request 기본정보 조회 요청 (차량번호, 부과기준일, 조회구분 등 포함)
     * @return 차량 기본정보 응답
     */
    @Override
    public BasicResponse getBasicInfo(BasicRequest request) {
        log.debug("[Internal Mode] 차량 기본정보 조회 - 차량번호: {}", request.getVhrno());

        // Envelope로 감싸기 (요청 객체는 이미 모든 필수 파라미터를 포함)
        Envelope<BasicRequest> requestEnvelope = new Envelope<BasicRequest>();
        requestEnvelope.setData(Collections.singletonList(request));

        try {
            // 내부 서비스 호출
            ResponseEntity<Envelope<BasicResponse>> responseEntity =
                    carBassMatterInqireService.basic(requestEnvelope);

            if (responseEntity.getBody() != null &&
                    responseEntity.getBody().getData() != null &&
                    !responseEntity.getBody().getData().isEmpty()) {

                return responseEntity.getBody().getData().get(0);
            }

            log.warn("[Internal Mode] 차량 기본정보 조회 응답이 비어있음 - 차량번호: {}", request.getVhrno());
            return null;

        } catch (Exception e) {
            log.error("[Internal Mode] 차량 기본정보 조회 실패 - 차량번호: {}", request.getVhrno(), e);
            throw new RuntimeException("차량 기본정보 조회 실패: " + e.getMessage(), e);
        }
    }

    /**
     * 자동차 등록원부(갑) 조회 (내부 모듈 직접 호출)
     * 중요 로직: 등록원부 조회는 LedgerRequest 전체를 받아서 내부 서비스에 전달
     *
     * @param request 등록원부 조회 요청 (차량번호, 소유자정보, 조회구분 등 포함)
     * @return 등록원부 정보 응답
     */
    @Override
    public LedgerResponse getLedgerInfo(LedgerRequest request) {
        log.debug("[Internal Mode] 자동차 등록원부 조회 - 차량번호: {}", request.getVhrno());

        // Envelope로 감싸기 (요청 객체는 이미 모든 필수 파라미터를 포함)
        Envelope<LedgerRequest> requestEnvelope = new Envelope<LedgerRequest>();
        requestEnvelope.setData(Collections.singletonList(request));

        try {
            // 내부 서비스 호출
            ResponseEntity<Envelope<LedgerResponse>> responseEntity =
                    carLedgerFrmbkService.ledger(requestEnvelope);

            if (responseEntity.getBody() != null &&
                    responseEntity.getBody().getData() != null &&
                    !responseEntity.getBody().getData().isEmpty()) {

                return responseEntity.getBody().getData().get(0);
            }

            log.warn("[Internal Mode] 자동차 등록원부 조회 응답이 비어있음 - 차량번호: {}", request.getVhrno());
            return null;

        } catch (Exception e) {
            log.error("[Internal Mode] 자동차 등록원부 조회 실패 - 차량번호: {}", request.getVhrno(), e);
            throw new RuntimeException("자동차 등록원부 조회 실패: " + e.getMessage(), e);
        }
    }

    /**
     * 성공한 응답 개수 계산
     */
    private int countSuccessful(List<VehicleApiResponseVO> responses) {
        int count = 0;
        for (VehicleApiResponseVO response : responses) {
            if (response.isSuccess()) {
                count++;
            }
        }
        return count;
    }
}
