package com.eactive.eai.custom.message;

import static org.junit.jupiter.api.Assertions.*;

import java.util.HashMap;
import java.util.Properties;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import com.eactive.eai.message.StandardMessage;
import com.eactive.eai.message.StandardMessageUtil;
import com.ext.eai.common.stdmessage.STDMessageKeys;

class InterfaceMapperDJBTest {

    private InterfaceMapperDJB mapper;
    private StandardMessage    message;

    @BeforeEach
    void setUp() throws Exception {
        // CSV에서 표준전문 레이아웃 로드
        message = StandardMessageUtil.generateMessageFromCsvFile(
                "src/main/resources/standard-layout-djb.csv");
        assertNotNull(message, "standard-layout-djb.csv 로드 실패");
        message.setReadPosition(0);

        // 매핑 설정 로드
        Properties props = new Properties();
        try (java.io.InputStream in = getClass().getClassLoader()
                .getResourceAsStream("standard-message-mapping-config-djb.properties")) {
            assertNotNull(in, "standard-message-mapping-config-djb.properties 로드 실패");
            props.load(in);
        }

        HashMap<String, String> pathMap = new HashMap<>();
        for (String key : props.stringPropertyNames()) {
            pathMap.put(key.trim(), props.getProperty(key).trim());
        }

        mapper = new InterfaceMapperDJB();
        mapper.initPathMap(pathMap);
    }

    // ----------------------------------------------------------------
    // GUID
    // ----------------------------------------------------------------

    @Test
    void setGuid_40자_정상_설정() {
        String guid = GUIDGeneratorDJB.getGUID("EAI");
        mapper.setGuid(message, guid);
        assertEquals(guid, mapper.getGuid(message));
    }

    @Test
    void setGuid_40자_아닌경우_예외발생() {
        assertThrows(RuntimeException.class, () -> mapper.setGuid(message, "SHORT"));
    }

    @Test
    void setGuid_null이면_예외발생() {
        assertThrows(RuntimeException.class, () -> mapper.setGuid(message, null));
    }

    // ----------------------------------------------------------------
    // GUID 진행번호 (guid_prgs_no - 별도 필드)
    // ----------------------------------------------------------------

    @Test
    void guidSeq_초기값_및_nextGuidSeq_증가() {
        // 초기값 설정
        mapper.setGuidSeq(message, "001");
        assertEquals("001", mapper.getGuidSeq(message));

        // +1 증가
        String next = mapper.nextGuidSeq(message);
        assertEquals("002", next);
        assertEquals("002", mapper.getGuidSeq(message));
    }

    @Test
    void nextGuidSeq_3자리_zero_padding() {
        mapper.setGuidSeq(message, "009");
        assertEquals("010", mapper.nextGuidSeq(message));

        mapper.setGuidSeq(message, "099");
        assertEquals("100", mapper.nextGuidSeq(message));
    }

    // ----------------------------------------------------------------
    // 원거래 GUID (ortr_guid)
    // ----------------------------------------------------------------

    @Test
    void orgGuid_설정_조회() {
        String guid = GUIDGeneratorDJB.getGUID("EAI");
        mapper.setOrgGuid(message, guid);
        assertEquals(guid, mapper.getOrgGuid(message));
    }

    // ----------------------------------------------------------------
    // 처리결과구분코드 (S/F ↔ 엔진 내부 NR/ER)
    // ----------------------------------------------------------------

    @Test
    void setResponseType_정상_NR_to_S() {
        mapper.setResponseType(message, STDMessageKeys.RESPONSE_TYPE_CODE_N); // "NR"
        assertEquals("S", message.findItemValue("HEAD.procs_rslt_dvcd"));
    }

    @Test
    void setResponseType_오류_ER_to_F() {
        mapper.setResponseType(message, STDMessageKeys.RESPONSE_TYPE_CODE_E); // "ER"
        assertEquals("F", message.findItemValue("HEAD.procs_rslt_dvcd"));
    }

    @Test
    void getResponseType_S_to_NR() {
        message.setData("HEAD.procs_rslt_dvcd", "S");
        assertEquals(STDMessageKeys.RESPONSE_TYPE_CODE_N, mapper.getResponseType(message));
    }

    @Test
    void getResponseType_F_to_ER() {
        message.setData("HEAD.procs_rslt_dvcd", "F");
        assertEquals(STDMessageKeys.RESPONSE_TYPE_CODE_E, mapper.getResponseType(message));
    }

    // ----------------------------------------------------------------
    // 원거래복원여부 (Y/N ↔ 엔진 내부 1/0)
    // ----------------------------------------------------------------

    @Test
    void recoverYn_Y면_1반환() {
        message.setData("HEAD.ortr_restr_yn", "Y");
        assertEquals("1", mapper.getRecoverYn(message));
    }

    @Test
    void recoverYn_N면_0반환() {
        message.setData("HEAD.ortr_restr_yn", "N");
        assertEquals("0", mapper.getRecoverYn(message));
    }

    @Test
    void setRecoverYn_1이면_Y설정() {
        mapper.setRecoverYn(message, "1");
        assertEquals("Y", message.findItemValue("HEAD.ortr_restr_yn"));
    }

    @Test
    void setRecoverYn_0이면_N설정() {
        mapper.setRecoverYn(message, "0");
        assertEquals("N", message.findItemValue("HEAD.ortr_restr_yn"));
    }

    // ----------------------------------------------------------------
    // 인터페이스ID (trim)
    // ----------------------------------------------------------------

    @Test
    void getInterfaceId_공백_trim() {
        message.setData("HEAD.if_id", "  IF001  ");
        assertEquals("IF001", mapper.getInterfaceId(message));
    }

    @Test
    void getInterfaceId_null이면_빈문자열() {
        // 초기 공백상태
        String ifId = mapper.getInterfaceId(message);
        assertNotNull(ifId);
        assertEquals("", ifId.trim());
    }

    // ----------------------------------------------------------------
    // EAI 서비스코드 조합
    // ----------------------------------------------------------------

    @Test
    void getEaiSvcCode_인터페이스ID_요청응답_내외구분_조합() {
        message.setData("HEAD.if_id",         "IF_TEST_001");
        message.setData("HEAD.dman_rspn_dvcd", "S");
        message.setData("HEAD.hmab_dvcd",      "1");

        String svcCode = mapper.getEaiSvcCode(message);
        assertTrue(svcCode.startsWith("IF_TEST_001"), "EAI 서비스코드: " + svcCode);
        assertTrue(svcCode.contains("S"), "요청응답구분 포함: " + svcCode);
    }

    // ----------------------------------------------------------------
    // 필드 경로 기본 동작 확인 (매핑 설정 유효성)
    // ----------------------------------------------------------------

    @Test
    void sendRecvDivision_설정_조회() {
        mapper.setSendRecvDivision(message, "R");
        assertEquals("R", mapper.getSendRecvDivision(message));
    }

    @Test
    void inExDivision_설정_조회() {
        mapper.setInExDivision(message, "1");
        assertEquals("1", mapper.getInExDivision(message));
    }

    @Test
    void errorCode_설정_조회() {
        mapper.setErrorCode(message, "ERR001");
        assertEquals("ERR001", mapper.getErrorCode(message));
    }

    @Test
    void errorMsg_설정_조회() {
        mapper.setErrorMsg(message, "오류가 발생했습니다.");
        assertEquals("오류가 발생했습니다.", mapper.getErrorMsg(message));
    }
}
