<%@ page language="java" contentType="text/html; charset=utf-8"%>
<%@ page import="java.io.*"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ include file="/jsp/common/include/localemessage.jsp" %>
<%
    response.setHeader("Pragma", "No-cache");
    response.setHeader("Cache-Control", "no-cache");
    response.setHeader("Expires", "0");
%>

<html>
<head>
    <title></title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <script defer src="<c:url value="/addon/alpinejs-3.14.3/alpinejs.min.js"/>"></script>
    <jsp:include page="/jsp/common/include/css.jsp"/>
    <jsp:include page="/jsp/common/include/script.jsp"/>

    <link href="<c:url value="/addon/bootstrap-5.3.2/css/bootstrap.min.css"/>" rel="stylesheet" />
    <script src="<c:url value="/addon/bootstrap-5.3.2/js/bootstrap.bundle.min.js"/>"></script>
    <link href="<c:url value="/addon/select2-4.1.0/css/select2.min.css"/>" rel="stylesheet" />
    <link href="<c:url value="/addon/select2-4.1.0/css/select2-bootstrap.min.css"/>" rel="stylesheet" />
    <script src="<c:url value="/addon/select2-4.1.0/js/select2.min.js"/>"></script>
    <link href="<c:url value="/addon/bootstrap5-toggle-5.0.6/css/bootstrap5-toggle.min.css"/>" rel="stylesheet" />
    <script src="<c:url value="/addon/bootstrap5-toggle-5.0.6/js/bootstrap5-toggle.jquery.min.js"/>"></script>
    <link href="<c:url value="/addon/bootstrap-icons-1.11.3/bootstrap-icons.min.css"/>" rel="stylesheet" />
    <script src="<c:url value="/addon/jquery-validation-1.19.5/jquery.validate.min.js"/>"></script>
    <script src="<c:url value="/addon/jquery-validation-1.19.5/localization/messages_ko.min.js"/>"></script>
    <script src="<c:url value="/addon/jquery-confirm/jquery-confirm.min.js"/>"></script>
    <link href="<c:url value="/addon/jquery-confirm/jquery-confirm.min.css"/>" rel="stylesheet" />
    <style>
        label{
            color:#003c78
        }

        .tooltip-inner {
            min-width: 300px; /* the minimum width */
        }

        .form-check-input{
            margin-left: 0px;
        }
        .form-check-label{
            margin-left: 1.25rem;
        }

        input[readonly] {
            background-color: #eeeeee;
            border-color: #cccccc;
        }
        
        /* input-group 안에서 invalid-feedback이 차지하는 공간 없애기, 유효성검사 할 때 현재 스타일 바뀌지않게 CSS 처리 */
		.input-group > .invalid-feedback {
		  position: absolute;
		  top: 100%; 
		  left: 0;
		  width: 100%;
		  margin-top: .25rem;
		}
		
		.input-group {
		  position: relative;
		}
		
		/* 어댑터, 메서드 select2 사용시 width 깨짐 방지 */
		.select2-container {
			width: 100% !important;
			box-sizing: border-box;
		}
		
		/* 버튼 내용이 길어질 경우 말줄임표(...) 처리 */
		.btn-ellipsis {
		    max-width: 100%;
		    white-space: nowrap;
		    overflow: hidden;
		    text-overflow: ellipsis;
		    display: inline-block;
		    vertical-align: middle;
		}

		/* iframe 모달(showModal) 콘텐츠 패딩 제거 — iframe 이 다이얼로그 폭을 최대한 사용해 내부 가로스크롤 방지 */
		.ui-dialog .ui-dialog-content { padding: 0 !important; }

		/* OpenAPI Spec 버튼 상태 색상 (PTL_API_SPEC_INFO 기준) */
		#btn_openapi_spec.spec-exists { background:#ffe08a !important; border-color:#f0c040 !important; color:#5a4600 !important; }
		#btn_openapi_spec.spec-public { background:#b8e6a0 !important; border-color:#7cc257 !important; color:#2c4a15 !important; }
		/* 호버 상태 안내 레이어 */
		#specStatusLayer {
			position: fixed; z-index: 100000; display: none;
			background: rgba(30,30,30,0.92); color: #fff;
			padding: 8px 12px; border-radius: 6px;
			font-size: 12px; line-height: 1.6; max-width: 340px;
			white-space: pre-line; pointer-events: none;
			box-shadow: 0 2px 8px rgba(0,0,0,0.3);
		}

    </style>
    <script language="javascript" >
        var isDetail = false;
        var url ='<c:url value="/onl/transaction/apim/apiInterfaceMan.json" />';
        const url_excel  ='<c:url value="/onl/transaction/apim/apiInterfaceMan.excel" />';
        var url_spec = '<c:url value="/onl/transaction/apim/apiSpecMan.view"/>';
        var url_openapi_spec = '<c:url value="/onl/transaction/apim/djbApiSpecMan.view"/>';
        var url_openapi_spec_json = '<c:url value="/onl/transaction/apim/djbApiSpecMan.json"/>';
        var returnUrl ;
        let headerValues = [];
        let headerNames = [];
        let stdCommonFieldDefinitions = [];

        let standardMessageItems = [];
        let inboundResponseStandardMessageItems = [];
        let currentStandardMessageType = ''; // 현재 다이얼로그가 처리하는 메시지 타입을 추적

        let isHeaderRouting = false;
        let fromAdapterMessageKeyMap ;
        var jsonUrl ;

        $.fn.select2.defaults.set( "theme", "bootstrap" );

        document.addEventListener('alpine:init', () => {
            Alpine.data('apiInterfaceManager', () => ({
                // ApiInterfaceUI 데이터 모델
                apiInterface: {
                    sevrLogLvelNo: null,
                    eaiBzwkDstcd: '',
                    sendRecvType: '',
                    inOutType: null,
                    eaiSvcDesc: '',
                    fromAdapter: '',
                    toAdapter: '',
                    inboundHttpMethod: '',
                    inboundRestPath: '',
                    outboundHttpMethod: '',
                    outboundRestPath: '',
                    inboundRequestLayout: '',
                    requestTransform: '',
                    outboundRequestLayout: '',
                    inboundResponseLayout: '',
                    responseTransform: '',
                    outboundResponseLayout: '',
                    eaiSvcName: '',
                    transformYn: 'N',
                    toutVal: null,
                    simYn: 'N',
                    apiEnabledYn: 'N',
                    authType: '',
                    isHeaderRouting: false,
                    standardMessageItems: [],
                    inboundResponseStandardMessageItems: [],
                    fromResponseAdapter: '',
                    toResponseAdapter: '',
                    inboundResponseHttpMethod: '',
                    inboundResponseRestPath: '',
                    outboundResponseHttpMethod: '', 
                    outboundResponseRestPath: '',
                    syncAsyncType: 'sync',
                    wordType: '1',
                    requestType:'S'
                },

                // 컴퓨티드 프로퍼티
                get showInboundResponse() {
                    return this.apiInterface.syncAsyncType === 'asyncSync';
                },

                // 컴퓨티드 프로퍼티
                get showOutboundResponse() {
                    return this.apiInterface.syncAsyncType === 'syncAsync';
                },
            }));

            // 요청/응답 disable 처리.
            Alpine.store('formState', {
                isReqResDisabled: false
            });
        });

        // Alpine 컴포넌트 접근을 위한 유틸리티 함수
        function getApiInterface() {
            const form = document.querySelector('#ajaxForm');
            const xDataObject = form._x_dataStack[0].apiInterface;
            return xDataObject;
        }

        function init(url,key,callback){
            $('#checkApiCacheUrlKey').on('click', function(e) {
                e.preventDefault();
            });

            $.ajax({
                type : "POST",
                url:url,
                dataType:"json",
                data:{cmd: 'LIST_DETAIL_COMBO'},
                success:function(json){
                    new makeOptions("BIZCODE","BIZNAME").setObj($("select[name=eaiBzwkDstcd]")).setData(json.bizList).setFormat(codeName3OptionFormat).rendering();
                    new makeOptions("BIZCODE","BIZNAME").setObj($("select[name=newBizCode]")).setData(json.bizList).setFormat(codeName3OptionFormat).rendering();
                    new makeOptions("ADPTRBZWKGROUPNAME","ADPTRBZWKGROUPDESC").setObj($("select[name=fromAdapter]")).setFormat(codeName3OptionFormat).setNoValueInclude(true).setAttr('std','ADPTRMSGPTRNCD').setData(json.fromList).rendering();
                    new makeOptions("ADPTRBZWKGROUPNAME","ADPTRBZWKGROUPDESC").setObj($("select[name=fromResponseAdapter]")).setFormat(codeName3OptionFormat).setNoValueInclude(true).setData(json.toList).rendering();
                    new makeOptions("ADPTRBZWKGROUPNAME","ADPTRBZWKGROUPDESC").setObj($("select[name=toAdapter]")).setFormat(codeName3OptionFormat).setNoValueInclude(true).setData(json.toList).rendering();
                    new makeOptions("ADPTRBZWKGROUPNAME","ADPTRBZWKGROUPDESC").setObj($("select[name=toResponseAdapter]")).setFormat(codeName3OptionFormat).setNoValueInclude(true).setData(json.fromList).rendering();
                    //if(key == "") setSearchable(selectName);	// 콤보에 searchable 설정

                    if (typeof callback === 'function') {
                        callback(url,key);
                    }
                    $('#eaiBzwkDstcd').select2();

                    $('#fromAdapter').select2();
                    $('#toAdapter').select2();

                    $('#fromResponseAdapter').select2();
                    $('#toResponseAdapter').select2();

                    $('#inboundHttpMethod').select2();
                    $('#outboundHttpMethod').select2();

                    $('#newBizCode').select2({
						dropdownParent: $('#cloneInterfaceModal'),
						width: '100%'
                    });

                    $('#newInboundHttpMethod').select2({
						dropdownParent: $('#cloneInterfaceModal'),
						width: '100%'
                    });

                    fromAdapterMessageKeyMap = json.fromAdapterMessageKeyMap;
                    stdCommonFieldDefinitions = json.stdCommonFieldDefinitions;
                    initStdCommonFieldDefinitions(stdCommonFieldDefinitions);
                },
                error:function(e){
                    alert(e.responseText);
                }
            });
        }
        function getAdapterInfo(adapterGroupName){
            return new Promise((resolve, reject) => {
                $.ajax({
                    type: "POST",
                    url: jsonUrl,
                    dataType: "json",
                    data: { cmd: 'DETAIL_ADAPTER_INFO', adapterGroupName: adapterGroupName },
                    success: function(data) {
                        resolve(data);
                    },
                    error: function(e) {
                        reject(e);
                    }
                });
            });
        }
        function getAdapterMessageType(adapterGroupName){
            let type;
            $.ajax({
                type : "POST",
                url: jsonUrl,
                dataType:"json",
                async: false,
                data:{cmd: 'DETAIL_ADAPTER_GROUP', adapterGroupName: adapterGroupName},
                success:function(json){
                    switch (json.ADPTRMSGDSTCD) {
                        case 'UJN':
                            type = 'UJSON'; break;
                        case 'UXM':
                            type = 'UXML' ; break;
                        case 'JSN':
                            type = 'JSON'; break;
                        case 'ASC':
                            type = 'BYTES'; break;
                        default:
                            type = json.ADPTRMSGDSTCD; break;
                    }
                },
            });
            return type;
        }

        // 어댑터 설정 정보 객체에 인바운드 응답 관련 설정 추가
        const adapterConfig = {
                inbound: {
                    ioType: 'inbound',
                    methodSelectId: '#inboundHttpMethod',
                    restPathInputId: '#inboundRestPath',
                    adapterUrlId: '#fromAdapterUrl',
                },
                outbound: {
                    ioType: 'outbound',
                    methodSelectId: '#outboundHttpMethod',
                    restPathInputId: '#outboundRestPath',
                    adapterUrlId: '#toAdapterUrl',
                    standardOptionsId: '#standardOutboundOptions',
                	commonFieldId: '#commonFieldPart'
                },
                inboundResponse: {
                    methodSelectId: '#inboundResponseHttpMethod',
                    restPathInputId: '#inboundResponseRestPath',
                    adapterUrlId: '#fromResponseAdapterUrl',
                    standardOptionsId: '#inboundResponseRestPart',
                    commonFieldId: '#inboundResponseCommonFieldPart'
                },
        		outboundResponse: {
        			methodSelectId: '#outboundResponseHttpMethod',
        			restPathInputId: '#outboundResponseRestPath',
        			adapterUrlId: '#toResponseAdapterUrl',
        			standardOptionsId: '#outboundResponseRestPart'
        		}
        };

        // 어댑터 선택 변경 시 호출되는 함수 수정
        async function adapterSelectChange(adapterType, adapterGroupName) {
            const adapterSettings = adapterConfig[adapterType];

            const adapterInfo = await getAdapterInfo(adapterGroupName);
            const isStandardMessage = 'K' == adapterInfo.adapterMessageGroupType;
            if(!isStandardMessage){
                $(adapterSettings.adapterUrlId).text(adapterInfo.urlPath);
            } else {
                //$(adapterSettings.methodSelectId).val('');
                $(adapterSettings.restPathInputId).val('');
                $(adapterSettings.adapterUrlId).text('');
            }
            $(adapterSettings.methodSelectId).prop('disabled', isStandardMessage);
            $(adapterSettings.restPathInputId).prop('disabled', isStandardMessage);

            // 표준전문 공통부 처리 (outbound와 inboundResponse에만 적용)
            if (adapterType === 'outbound' || adapterType === 'inboundResponse') {
                if(isStandardMessage) {
                    $(adapterSettings.standardOptionsId).hide();
                    $(adapterSettings.commonFieldId).show();
                } else {
                    $(adapterSettings.standardOptionsId).show();
                    $(adapterSettings.commonFieldId).hide();
                }
            }
        }

        function setHeaderRoutingLabel(){
            let label = headerNames.map(function(name, index) {
                const value = headerValues[index];
                return name + '=' + value;
            }).join(';');
            if(headerValues.length > 0){
                $("#headerRoutingButton").text('MessageKey ['+label+']');
            }else{
                $("#headerRoutingButton").text('MessageKey 라우팅 정보 없음');
            }
        }

         function setStandardMessageItemsLabel(items, buttonId) {
       	    const label = items.map(function(item) {
       	        return item.COLUMNNAME + '=' + item.COLUMNVALUE;
       	    }).join(';');

       	    const $btn = $('#' + buttonId);

       	    if (items.length > 0) {
       	        $btn.text('수정 [' + label + ']');

       	        $btn.attr('title', '수정 [' + label + ']');

       	        $btn.addClass('btn-ellipsis'); 

       	    } else {
       	        $btn.text('수정');
       	        $btn.removeAttr('title');
       	        
       	        $btn.removeClass('btn-ellipsis'); 
       	    }
       	}

        function setupStdCommonValueModal(type) {
            currentStandardMessageType = type;
            $('#stdCommonValuePairs input').val('');

            const items = type === 'outbound' ? standardMessageItems : inboundResponseStandardMessageItems;
            items.forEach(function(item) {
                $('#stdCommonValuePairs input[columnname="'+item.COLUMNNAME+'"]').val(item.COLUMNVALUE);
            });
        }


        function initStdCommonFieldDefinitions(stdCommonFieldDefinitions){
            // 기존의 모든 헤더 항목을 제거합니다.
            $('#stdCommonValuePairs').empty();

            stdCommonFieldDefinitions.forEach(function(stdCommonFieldDefinition) {
                addStdCommonFieldDefinitions(stdCommonFieldDefinition);
            });
        }

        function addStdCommonFieldDefinitions(stdCommonFieldDefinition) {
            let fieldName = stdCommonFieldDefinition.COLUMNNAME+' ['+stdCommonFieldDefinition.COLUMNDESC+']';
            if('Y' === stdCommonFieldDefinition.ISKEY){
                fieldName += '[*]'
            }
            const newPairHtml = '<div class="row align-items-center header-pair">' +
                '<div class="col" style="text-align: right;">' +
                '<label class="form-label">' + fieldName + '</label>' +
                '</div>' +
                '<div class="col">' +
                '<input type="text" class="form-control mb-2" name="stdCommonFieldValue" columnname="'+stdCommonFieldDefinition.COLUMNNAME+'" placeholder="'+stdCommonFieldDefinition.COLUMNDESC+' 필드 값">' +
                '</div>' +
                '</div>';
            $('#stdCommonValuePairs').append(newPairHtml);
        }

        function initHeaders(headerNames){
            // 기존의 모든 헤더 항목을 제거합니다.
            $('#headerPairs').empty();

            headerNames.forEach(function(headerName) {
                addHeader(headerName);
            });
        }

        function addHeader(headerName) {
            const newPairHtml = '<div class="row align-items-center header-pair">' +
                '<div class="col" style="text-align: right;">' +
                '<label class="form-label">' + headerName + '</label>' +
                '</div>' +
                '<div class="col">' +
                '<input type="text" class="form-control mb-2" name="headerValue" placeholder="MessageKey 값">' +
                '</div>' +
                '</div>';
            $('#headerPairs').append(newPairHtml);
        }

        function detail(url,key){
            jsonUrl = url;
            if (!isDetail)return;
           // $("input[name='btnRadioSyncAsync']").attr('disabled', true);
            $.ajax({
                type : "POST",
                url:url,
                dataType:"json",
                data:{cmd: 'DETAIL', eaiSvcName : key},
                success:function(json){
                    var data = json;

                    // Alpine 데이터 모델 업데이트
                    const apiInterface = getApiInterface();
                    Object.assign(apiInterface, data);

                    // $("input[name='btnRadioSyncAsync']").attr('disabled', true);
                    $("input[name=eaiSvcName]").attr('readonly',true);
                    $("#ajaxForm input, #ajaxForm textarea").each(function(){
                        const name = $(this).attr("name");
                        const tag  = $(this).prop("tagName").toLowerCase();
                        const type  = $(this).prop("type").toLowerCase();
                        if(type === 'radio'){
                            return;
                        }
                        $(tag+"[name="+name+"]").val(data[name]);
                    });

                    if(data.standardMessageItems != null) {
                        standardMessageItems = data.standardMessageItems;
                        setStandardMessageItemsLabel(standardMessageItems, 'standardMessageItemsButton');
                    }

                    if(data.inboundResponseStandardMessageItems != null) {
                        inboundResponseStandardMessageItems = data.inboundResponseStandardMessageItems;
                        setStandardMessageItemsLabel(inboundResponseStandardMessageItems, 'inboundResponseStandardMessageItemsButton');
                    }

                    $("select[name=eaiBzwkDstcd]"            ).val(data["eaiBzwkDstcd"]);//업무구분코드
                    $("select[name=fromAdapter]"             ).val(data["fromAdapter"]);//fromAdapter
                    $("select[name=toAdapter]"               ).val(data["toAdapter"]);//toAdapter
                    if(data["authType"] != null && data["authType"].trim() != ''){
                        $("select[name=authType]"               ).val(data["authType"]);
                    }
                    $("select[name=fromResponseAdapter]"               ).val(data["fromResponseAdapter"]);//fromResponseAdapter
                    
                    $("select[name=toResponseAdapter]"               ).val(data["toResponseAdapter"]);//toResponseAdapter
                    
                    $('#inboundHttpMethod').val(data.inboundHttpMethod);
                    $('#outboundHttpMethod').val(data.outboundHttpMethod);
                    $('#inboundResponseHttpMethod').val(data.inboundResponseHttpMethod);
                    $('#outboundResponseHttpMethod').val(data.outboundResponseHttpMethod);
                    $('#svcLogLvelNo').val(data.svcLogLvelNo);

                    if(data['inboundRequestLayout']!=null && data['outboundRequestLayout']!=null){
                        $('#requestTransform').removeAttr('disabled');
                    }
                    if(data['inboundResponseLayout']!=null && data['outboundResponseLayout']!=null){
                        $('#responseTransform').removeAttr('disabled');
                    }

                    if('Y' == data.transformYn){
                        $('#toggleTransformYn').bootstrapToggle('on');
                    }
                    if('Y' == data.simYn){
                        $('#toggleSimYn').bootstrapToggle('on');
                    }
                    if('Y' == data.apiEnabledYn){
                        $('#toggleApiEnabledYn').bootstrapToggle('on');
                    }
                    if('Y' == data.apiCacheYn){
                        $('#toggleApiCacheYn').bootstrapToggle('on');
                    }
                    if(data.apiCacheType != null && data.apiCacheType.includes("P")){
                        $('#checkApiCacheParamKey').prop('checked', true);
                    }

                    if(data.errResponseTransform != null && data.errResponseTransform != '' && data.errTransformYn == 'Y') {
                    	$('#toggleTransformYn').bootstrapToggle('on');
                        $('#toggleErrTransformYn').bootstrapToggle('on');
                        $('#rowErrResponseTransform').show();
                    } else {
                        $('#toggleErrTransformYn').bootstrapToggle('off');
                        $('#rowErrResponseTransform').hide();
                    }

                    $('#eaiBzwkDstcd').trigger('change');

                    transformSetStateChange();

                    const interfaceId = data['eaiSvcName'].slice(0, -2);
                    $('#eaiSvcName').val(interfaceId);
                    const sendRecvType = data['eaiSvcName'].slice(-2, -1);
                    $('#sendRecvType').val(sendRecvType);
                    const inOutType = data['eaiSvcName'].slice(-1);
                    $('#inOutType').val(inOutType);

                    $("input[name=btnRadioReqRes][value='" + sendRecvType + "']").prop("checked", true);
                    Alpine.store('formState').isReqResDisabled = true;
                    $("input[name=btnRadioInOut][value='" + inOutType + "']").prop("checked", true);
                    $("input[name=btnRadioInOut]").prop("disabled", true);
                    

                    $('#eaiBzwkDstcd').attr("readonly", "readonly");
                    $('#eaiSvcName').attr("readonly", "readonly");
                    $('#sendRecvType').attr("readonly", "readonly");
                    $('#inOutType').attr("readonly", "readonly");
                    checkTagVariableUrl();
                    setInboundRoutingSlide();

                    if(json.headerValues != null){
                        headerValues = json.headerValues;
                    }
                    setHeaderRoutingLabel();

                    $("#fromAdapter").change();
                    $("#toAdapter").change();

                    const eaiSvcName = $('#eaiSvcName').val();
                    $('#cloneOrgInterfaceIdDesc').text(eaiSvcName);

                    $("#fromResponseAdapter").change();
                    $("#toResponseAdapter").change();

                    $("#apiFullPath").val(data["apiFullPath"]); // 스펙 전달용 값

                    $('#inboundHttpMethod').trigger('change');
                    $('#outboundHttpMethod').trigger('change');

                    applyOpenApiSpecStatus();   // OpenAPI Spec 버튼 색상(PTL_API_SPEC_INFO)
                },
                error:function(e){
                    alert(e.responseText);
                }
            });
        }

        function layoutBtnStateChange(part){
            const value = $('#'+part+'Layout').val();
            if(value){
                $('#'+part+'Button').text('수정');
            }else{
                $('#'+part+'Button').text('생성');
            }
        }

        function mappingBtnStateChange(part){
            const transformName = (part === 'ErrResponse' ? 'errResponse' : part.toLowerCase()) + 'Transform';
            const inboundLayoutName = part === 'ErrResponse' ?
                $('#inboundErrResponseLayout').val() :
                $('#inbound'+part+'Layout').val();
            const outboundLayoutName = part === 'ErrResponse' ?
                $('#outboundErrResponseLayout').val() :
                $('#outbound'+part+'Layout').val();
            const value = $('#'+transformName).val();

            if(value){
                $('#'+transformName+'Button').text('수정');
            }else{
                $('#'+transformName+'Button').text('생성');
            }

            const isEnabled = value || (inboundLayoutName != null && inboundLayoutName != ''
                && outboundLayoutName != null && outboundLayoutName != '');

            if(isEnabled && (part !== 'ErrResponse' || $('#toggleErrTransformYn').prop('checked'))){
                $('#'+transformName+'Button').removeClass('btn-secondary').addClass('btn-primary');
                $('#'+transformName+'ButtonTooltip').tooltip('disable');
                $('#'+transformName+'Button').attr('disabled', false);
                $('#'+transformName+'Button').css('pointer-events','all');
            }else{
                $('#'+transformName+'Button').removeClass('btn-primary').addClass('btn-secondary');
                $('#'+transformName+'ButtonTooltip').tooltip('enable')
                $('#'+transformName+'Button').css('pointer-events','none');
                $('#'+transformName+'Button').attr('disabled', true);
            }
        }

        function transformSetStateChange(){
            layoutBtnStateChange('inboundRequest');
            layoutBtnStateChange('outboundRequest');
            layoutBtnStateChange('inboundResponse');
            layoutBtnStateChange('outboundResponse');
            mappingBtnStateChange('Request');
            mappingBtnStateChange('Response');
            layoutBtnStateChange('inboundErrResponse');
            layoutBtnStateChange('outboundErrResponse');
            mappingBtnStateChange('ErrResponse');
        }

        function addLayoutBtnEvent(part, desc, target){
            $('#'+part+'Button').on("click", function(event) {
                modifyLayout(''+part+'Layout', desc, target)
            });
        }

        function openLayoutPopup(layoutPartName){
        	var isLayoutView = $('#toggleLayoutView').prop('checked');
            const layoutName = $('#'+layoutPartName).val();
            var args = {title:layoutName+' 수정', parent: true};
            var url='<c:url value="/onl/admin/rule/layoutMan.view"/>';
            url += '?cmd=DETAIL';
            url += '&loutName='+layoutName;
            url += '&layoutPartName='+layoutPartName;
            url += '&pop=true';
            url += '&isLayoutView=' + isLayoutView;
            const width = parent.document.body.clientWidth - 30;
            const height = parent.document.body.clientHeight - 30;
            showModal(url,args,width,height,null,{fullScreenPopup:true});
        }

        function getFullSvcName(){
            return $('#eaiSvcName').val()+$('#sendRecvType').val()+$('#inOutType').val();
        }

        function openTransformPopup(transformName, transformDesc){
            const svcName = getFullSvcName();
            const svcDesc = encodeURI(encodeURIComponent($('#eaiSvcDesc').val()));
            const cnvsnDesc = encodeURI(encodeURIComponent(transformDesc));
            var args = {title:transformName+' 수정', parent: true};
            var url='<c:url value="/onl/admin/rule/transform2/transform2Man.view"/>';
            url += '?cmd=DETAIL';
            url += '&cnvsnName='+transformName;
            url += '&eaiSvcName='+svcName;
            url += '&eaiSvcDesc='+svcDesc;
            url += '&cnvsnDesc='+cnvsnDesc;
            url += '&pop=true';
            const width = parent.document.body.clientWidth - 30;
            const height = parent.document.body.clientHeight - 30;
            showModal(url,args,width,height,null,{fullScreenPopup: true});
        }

        function afterCreatedApi(){
            $("img[level='W'][status*=DETAIL]").show();
            $("img[level='R'][status*=DETAIL]").show();
            $("#btn_modify").attr('src',"<c:url value='/img/btn_modify.png'/>");
            isDetail = true;
            $("input[name=eaiSvcName]").attr('readonly',true);
        }

        function modifyLayout(layoutPartName, layoutPartDesc, layoutPostFix){
            if(!isDetail){
                function createApiAction(){
                    modifyApi(afterCreatedApi);
                }
                $.confirm({
                    title: 'API 저장',
                    columnClass: 'medium',
                    content: '레이아웃을 생성하기 전에 API를 저장해야 합니다. 저장하시겠습니까?  <br> 업무코드['+$('#eaiBzwkDstcd').val()+'] API 명 ['+getFullSvcName()+']',
                    buttons: {
                        confirm: {
                            text: '저장',
                            btnClass: 'btn-blue',
                            action: createApiAction
                        },
                        cancel: {
                            text: '취소',
                        }
                    }
                });
                return;
            }
            const layoutName = $('#'+layoutPartName).val();
            const bizCd = $('#eaiBzwkDstcd').val();
            const svcName = getFullSvcName();
            const layoutDesc = $('#eaiSvcDesc').val()+" ("+layoutPartDesc+")";
            if(layoutName == null || layoutName == ''){
                const newLayoutName = bizCd+'_'+svcName+'_'+layoutPostFix;

                // 어댑터 선택 로직 수정
                let adapterGroupName;
                if(layoutPartName.startsWith('inbound')){
                    // asyncSync 타입일 때는 fromResponseAdapter 사용
                    if(getApiInterface().syncAsyncType === 'asyncSync' && layoutPartName.endsWith('ResponseLayout')){
                        adapterGroupName = $('#fromResponseAdapter').val();
                    } else {
                        adapterGroupName = $('#fromAdapter').val();
                    }
                } else {
                    adapterGroupName = $('#toAdapter').val();
                }

                if(adapterGroupName == null || adapterGroupName == ""){
                    alert('어댑터가 선택되지 않았습니다. 확인하세요');
                    return;
                }
                const messageType = getAdapterMessageType(adapterGroupName);
                function newLayoutAction(){
                    var args = new Object();
                    const layoutUrl ='<c:url value="/onl/admin/rule/layoutMan.json" />';
                    const postData = {
                        cmd: 'INSERT',
                        layoutItems: '[]',
                        loutPtrnName: messageType,
                        loutName: newLayoutName,
                        loutDesc: layoutDesc,
                        eaiBzwkDstcd: bizCd,
                        eaiSevrDstcd: 'A',
                        useYn: '1',
                    };
                    $.ajax({
                        type : "POST",
                        url: layoutUrl,
                        data: postData,
                        success:function(){
                            alert("생성완료");
                            $('#'+layoutPartName).val(newLayoutName);
                            transformSetStateChange();
                            openLayoutPopup(layoutPartName);
                        },
                        error:function(e){
                            alert(e.responseText);
                        }
                    });
                }
                $.confirm({
                    title: '신규 레이아웃 생성',
                    columnClass: 'medium',
                    content: layoutPartDesc+' 레이아웃을 생성하시겠습니까? <br> 생성 레이아웃 명 ['+newLayoutName+'] 타입['+messageType+']',
                    buttons: {
                        confirm: {
                            text: '생성',
                            btnClass: 'btn-blue',
                            action: newLayoutAction
                        },
                        cancel: {
                            text: '취소',
                        }
                    }
                });
            }else{
                openLayoutPopup(layoutPartName);
            }
        }

        function modifyTransform(reqResType){
            if($('#'+reqResType+'TransformButton').attr('disabled')){
                return;
            }
            const transformName = $('#'+reqResType+'Transform').val();
            let transformDescSubfix;
            let bizCd = $('#eaiBzwkDstcd').val();
            let svcName = getFullSvcName();
            let cnvsnType;
            let srcLayoutName;
            let tgtLayoutName;

            // 오류변환과 일반변환 구분하여 설정
            if(reqResType === 'errResponse') {
                transformDescSubfix = '오류변환';
                cnvsnType = 'ERR';
                srcLayoutName = $('#outboundErrResponseLayout').val();
                tgtLayoutName = $('#inboundErrResponseLayout').val();
            } else {
                transformDescSubfix = reqResType === 'request' ? '요청매핑' : '응답매핑';
                cnvsnType = reqResType === 'request' ? 'REQ' : 'RES';
                srcLayoutName = reqResType === 'request' ? $('#inboundRequestLayout').val() : $('#outboundResponseLayout').val();
                tgtLayoutName = reqResType === 'request' ? $('#outboundRequestLayout').val() : $('#inboundResponseLayout').val();
            }

            const transformDesc = $('#eaiSvcDesc').val()+" ("+transformDescSubfix+")";

            if(!transformName?.trim()){
                const newTransformName = 'TRANSFORM_'+bizCd+'_'+svcName+'_'+cnvsnType;
                function updateFirstLayout(newTransformName, transformDesc){
                    $.ajax({
                        type : "POST",
                        url: '<c:url value="/onl/admin/rule/transform2/transform2Man.json" />',
                        data: { cmd: 'UPDATE',
                            gridData: '[]',
                            eaiSvcName: svcName,
                            cnvsnName: newTransformName,
                            cnvsnDesc: transformDesc,
                            cnvsnType,
                            chkForce: false,
                            srcLayoutName,
                            tgtLayoutName,
                        },
                        success:function(){
                            openTransformPopup(newTransformName, transformDesc);
                        },
                        error:function(e){
                            alert(e.responseText);
                        }
                    });
                }
                function newTransformAction(){
                    var args = new Object();
                    const postData = {
                        cmd: 'INSERT',
                        gridData: '[]',
                        cnvsnType,
                        eaiSvcName: svcName,
                        cnvsnName: newTransformName,
                        cnvsnDesc: transformDesc
                    };
                    $.ajax({
                        type : "POST",
                        url: '<c:url value="/onl/admin/rule/transform2/transform2Man.json" />',
                        data: { cmd: 'INSERT',
                            gridData: '[]',
                            cnvsnType,
                            eaiSvcName: svcName,
                            cnvsnName: newTransformName,
                            cnvsnDesc: transformDesc
                        },
                        success:function(){
                            alert("생성완료");
                            $('#'+reqResType+'Transform').val(newTransformName);
                            transformSetStateChange();
                            updateFirstLayout(newTransformName, transformDesc);
                        },
                        error:function(e){
                            alert(e.responseText);
                        }
                    });
                }
                $.confirm({
                    title: '신규 '+transformDescSubfix+' 생성',
                    columnClass: 'medium',
                    content: transformDescSubfix+'을 생성하시겠습니까? <br> 생성 매핑 룰 명 ['+newTransformName+']',
                    buttons: {
                        confirm: {
                            text: '생성',
                            btnClass: 'btn-blue',
                            action: newTransformAction
                        },
                        cancel: {
                            text: '취소',
                        }
                    }
                });
            }else{
                openTransformPopup(transformName, transformDesc);
            }
        }

        function modifyApi(callback){
            //if (!isValid())return;
            //업무추출키 control
            if(!$("#ajaxForm").valid()){
                return;
            }
            if ($("select[name=fromAdapter] option:selected").attr("std") == "K"){
                //표준일경우 업무추출키 삭제되어야 됨
                $("input[name=bzwkSvcKeyName]").val("");
            }else{
                //표준이 아닐경우 업무추출키 셋팅되어야 됨
                $("input[name=bzwkSvcKeyName]").val($("input[name=eaiTranName]").val());
            }
            
            // 사용자 편의를 위해 Path 앞에 "/" 는 제외, 복제도 포함.
			$("input[name=inboundRestPath]").val(function(index, value) {
			    return value.replace(/^\/+/, ""); 
			});
			$("input[name=inboundResponseRestPath]").val(function(index, value) {
			    return value.replace(/^\/+/, ""); 
			});
			$("input[name=outboundRestPath]").val(function(index, value) {
			    return value.replace(/^\/+/, ""); 
			});
			$("input[name=outboundResponseRestPath]").val(function(index, value) {
			    return value.replace(/^\/+/, ""); 
			});
			
            var postData = $('#ajaxForm').serializeArray();
            
            console.log('modify', postData);
            console.log('method', $('#inboundHttpMethod').val());
            
            if (isDetail){
                postData.push({ name: "cmd" , value:"UPDATE"});
            }else{
                postData.push({ name: "cmd" , value:"INSERT"});
            }
            postData.push({ name: "interfaceId" , value: $("input[name=eaiSvcName]").val()});
            postData = postData.filter(obj => obj.name !== "eaiSvcName");
            postData.push({ name: "eaiSvcName" , value: getFullSvcName()});
            const apiEnabledYn = $('#toggleApiEnabledYn').prop('checked') ? 'Y' : 'N';
            const transformYn = $('#toggleTransformYn').prop('checked') ? 'Y' : 'N';
            const simYn = $('#toggleSimYn').prop('checked') ? 'Y' : 'N';
            const apiCacheYn = $('#toggleApiCacheYn').prop('checked') ? 'Y' : 'N';
            const errTransformYn = $('#toggleErrTransformYn').prop('checked') ? 'Y' : 'N';
            const inboundMethod = $('#inboundHttpMethod').val();
            const outboundMethod = $('#outboundHttpMethod').val();

            if(apiCacheYn === 'Y'){
                if(inboundMethod !== 'get'){
                    alert("인바운드 메소드가 GET 일 경우에만 API 캐시사용이 가능합니다.");
                    return;
                }
                if(outboundMethod !== 'get'){
                    alert("아웃바운드 메소드가 GET 일 경우에만 API 캐시사용이 가능합니다.");
                    return;
                }
            }

            postData.push({ name: "apiEnabledYn" , value: apiEnabledYn});
            postData.push({ name: "transformYn" , value: transformYn});
            postData.push({ name: "errTransformYn" , value: errTransformYn});  // 추가
            postData.push({ name: "simYn" , value: simYn});
            postData.push({ name: "apiCacheYn" , value: apiCacheYn});
            let apiCacheType = "U";
            if($('#checkApiCacheParamKey').prop('checked')){
                apiCacheType+="|P";
            }
            postData.push({ name: "apiCacheType" , value: apiCacheType});
            postData.push({ name: "isHeaderRouting" , value: isHeaderRouting});
            // postData.push({name: "headerRoutingPairs", value: JSON.stringify(headerRoutingPairs)})
            headerValues.forEach(headerValue => {
                postData.push({name: "headerValues[]", value: headerValue});
            });

            const syncAsyncType = getApiInterface().syncAsyncType;
            postData.push({ name: "syncAsyncType" , value: syncAsyncType});

            // standardMessageItems 배열 추가
            for (let i = 0; i < standardMessageItems.length; i++) {
                postData.push({ name: "standardMessageItems[" + i + "].columnname", value: standardMessageItems[i].COLUMNNAME });
                postData.push({ name: "standardMessageItems[" + i + "].columnvalue", value: standardMessageItems[i].COLUMNVALUE });
            }

            // standardMessageItems 배열 추가
            for (let i = 0; i < inboundResponseStandardMessageItems.length; i++) {
                postData.push({ name: "inboundResponseStandardMessageItems[" + i + "].columnname", value: inboundResponseStandardMessageItems[i].COLUMNNAME });
                postData.push({ name: "inboundResponseStandardMessageItems[" + i + "].columnvalue", value: inboundResponseStandardMessageItems[i].COLUMNVALUE });
            }

            $.ajax({
                type: "POST",
                url:url,
                data: postData,
                beforeSend: function() {
                	$("[id^='btn_']").prop("disabled", true);
                	$("#btn_modify").text("처리중 . . . . .");
                },
                success:function(message){
                    alert("저장 되었습니다. \n\n[실시간 반영 결과]\n"+JSON.stringify(message));
                    if (typeof callback === 'function') {
                        callback();
                    }else{
                        goNav(returnUrl);//LIST로 이동
                    }
                },
                error:function(xhr, status, errorMsg){
                    alert(JSON.parse(xhr.responseText).errorMsg);
                },
                complete: function() {
                	$("[id^='btn_']").prop("disabled", false);
					$("#btn_modify").text("수정");
                }
            });
        }

        function setInboundRoutingSlide(){
            const adapterGroupName = $("#fromAdapter").val();
            const messageKeyList = fromAdapterMessageKeyMap[adapterGroupName]
            if(messageKeyList != null && messageKeyList.length > 0){
                headerNames = messageKeyList;
                isHeaderRouting = true;
                initHeaders(headerNames);
                //$('#slideInboundRoutingRule').carousel(0);
                $('#collapseInboundRoutingInfo').collapse('show')
                setHeaderRoutingLabel();
            }else{
                isHeaderRouting = false;
                $('#collapseInboundRoutingInfo').collapse('hide')
                //$('#slideInboundRoutingRule').carousel(1);
            }
        }

        function showApiSpecPopup() {
            var eaiSvcName = getFullSvcName();
            var eaiSvcDesc = $('#eaiSvcDesc').val();
            var apipath = $('#apiFullPath').val();
            var contentType = $('#contentType').val();
            var args = {
                    title:'API 스펙 관리',
                    parent: true,
                    apipath : apipath,
                    eaiSvcDesc : eaiSvcDesc,
                    contentType : contentType
            };
            var popupUrl = url_spec + '?cmd=DETAIL&eaiSvcName=' + encodeURIComponent(eaiSvcName);
            showModal(popupUrl, args, 1200, 800);
        }

        // v2: OpenAPI Spec — 기본은 모달(iframe), Shift+클릭은 새 창.
        // 컨텍스트는 전부 query string 으로 전달(dialogArguments 미사용).
        function showOpenApiSpecPopup(e) {
            var eaiSvcName  = getFullSvcName();
            var eaiSvcDesc  = $('#eaiSvcDesc').val();
            var apipath     = $('#apiFullPath').val();   // METHOD|URL ('|' 포함 → 인코딩 필수)
            var contentType = $('#contentType').val();
            var baseUrl = url_openapi_spec
                + '?cmd=DETAIL'
                + '&eaiSvcName='  + encodeURIComponent(eaiSvcName)
                + '&apipath='     + encodeURIComponent(apipath)
                + '&eaiSvcDesc='  + encodeURIComponent(eaiSvcDesc)
                + '&contentType=' + encodeURIComponent(contentType);
            if (e && e.shiftKey) {
                // Shift+클릭: 새 창. window.open 은 serviceType/menuId 자동 부착 안 되므로 직접 붙임.
                window.open(urlAddServiceType(baseUrl + '&menuId=' + encodeURIComponent(getMenuId())), '_blank');
            } else {
                // 기본: 모달 + iframe. showModal 이 serviceType/menuId/pop 을 자동 부착.
                // 콘텐츠 고정폭 1600 + 다이얼로그 chrome(패딩/보더 ~40px) 때문에 iframe 내부폭이 1600 미만이면 가로스크롤 발생.
                // 뷰포트 내에서 최대한 크게 열어(캡 1720) iframe 내부폭이 1600 이상 확보되게 한다.
                var vw = $(window).width(), vh = $(window).height();
                var modalW = Math.min(vw - 12, 1720);
                var modalH = Math.min(vh - 20, 900);
                // 스펙 편집 모달 닫힘 시 버튼 색상 재조회(공개여부/등록여부 변경 반영)
                showModal(baseUrl, { title: 'OpenAPI Spec' }, modalW, modalH, function(){ applyOpenApiSpecStatus(); });
            }
        }

        // OpenAPI Spec 버튼 색상 = PTL_API_SPEC_INFO(api_id = getFullSvcName()) 상태.
        //  - 미등록: 기본색      - 등록·비공개(display_yn≠Y): 노랑   - 등록·공개(display_yn=Y): 하늘
        function applyOpenApiSpecStatus() {
            var $btn = $('#btn_openapi_spec');
            $btn.removeClass('spec-exists spec-public').data('specMsg', '');
            var eaiSvcName = getFullSvcName();
            if (!eaiSvcName || eaiSvcName.length < 2) return;
            $.ajax({
                type: 'POST',
                url: url_openapi_spec_json,
                dataType: 'json',
                data: { cmd: 'SPEC_STATUS', eaiSvcName: eaiSvcName },
                success: function(res) {
                    var exists   = res && (res.exists === true || res.exists === 'true');
                    var isPublic = res && (res.displayYn === 'Y');
                    var msg;
                    if (!exists) {
                        msg = 'OpenAPI Spec 미등록\n버튼을 눌러 스펙을 생성/편집하세요.';
                    } else if (isPublic) {
                        $btn.addClass('spec-public');
                        msg = 'OpenAPI Spec 등록됨 · 포탈 공개중 (display_yn = Y)\n포탈 메인/문서에 노출됩니다.';
                    } else {
                        $btn.addClass('spec-exists');
                        msg = 'OpenAPI Spec 등록됨 · 비공개 (display_yn ≠ Y)\n포탈에는 노출되지 않습니다.';
                    }
                    $btn.data('specMsg', msg);
                }
            });
        }

        $(document).ready(function() {
            makeValidate();
            // var bootstrapButton = $.fn.button.noConflict()
            // $.fn.bootstrapBtn = bootstrapButton;

            returnUrl = getReturnUrlForReturn();
            var key ="${param.eaiSvcName}";
            key = decodeURIComponent(key);

            if (key != "" && key !="null"){
                isDetail = true;
            }
            init(url,key,detail);

            // v1: 기존 API 스펙 (모달) — 기능 비교용 복원
            $("#btn_api_spec").click(function() {
                showApiSpecPopup();
            });
            // v2: 신규 OpenAPI Spec (새 탭)
            $("#btn_openapi_spec").click(function(e) {
                showOpenApiSpecPopup(e);
            });

            // OpenAPI Spec 버튼 호버 시 현재 상태 안내 레이어
            if ($('#specStatusLayer').length === 0) {
                $('body').append('<div id="specStatusLayer"></div>');
            }
            $("#btn_openapi_spec")
                .on('mouseenter', function() {
                    var msg = $(this).data('specMsg');
                    if (!msg) return;
                    $('#specStatusLayer').text(msg).css('display', 'block');
                })
                .on('mousemove', function(e) {
                    $('#specStatusLayer').css({ left: (e.clientX + 14) + 'px', top: (e.clientY + 16) + 'px' });
                })
                .on('mouseleave', function() {
                    $('#specStatusLayer').hide();
                });

            $("#btn_modify").click(modifyApi);
            $("#btn_delete").click(function(){
            	if(!confirm("삭제하시겠습니까?")){
					return;
            	}
            	
                var postData = $('#ajaxForm').serializeArray();
                postData.push({ name: "cmd" , value:"DELETE"});

                // Alpine 컴포넌트에서 syncAsyncType 가져오기
                const syncAsyncType = getApiInterface().syncAsyncType;
                postData.push({ name: "syncAsyncType" , value: syncAsyncType});

                postData = postData.filter(obj => obj.name !== "eaiSvcName");
                postData.push({ name: "eaiSvcName" , value: getFullSvcName() });
                $.ajax({
                    type : "POST",
                    url:url,
                    data:postData,
                    beforeSend: function() {
                    	$("[id^='btn_']").prop("disabled", true);
                    	$("#btn_delete").text("처리중 . . . . .");
                    },
                    
                    success:function(args){
                        alert("삭제 되었습니다.");
                        goNav(returnUrl);//LIST로 이동

                    },
                    error:function(e){
                        alert(e.responseText);
                    },
                    complete: function() {
                    	$("[id^='btn_']").prop("disabled", false);
    					$("#btn_delete").text("삭제");
                    }
                });
            });
            $("#btn_previous").click(function(){
                goNav(returnUrl);//LIST로 이동
            });

            function callDownload(cmd, targetName){
                const fileName = targetName + '.txt';
                const bzwkDstcd = $('#eaiBzwkDstcd').val();
                const url = '<c:url value="/loader.do" />';
                const postData = [];
                postData.push({ name: "cmd" , value: cmd});
                postData.push({ name: "control" , value:"download"});
                postData.push({ name: "bzwkDstcd" , value: bzwkDstcd});
                postData.push({ name: "fileName" , value: fileName});
                return new Promise((resolve, reject) => {
                    $.ajax({
                        type: "POST",
                        url: url,
                        data: postData,
                        success: function (response) {
                            resolve(response);
                        },
                        error: function (error) {
                            reject(error);
                        }
                    });
                });
            }
            async function doDownload(type, targetName){
                if(targetName != null && targetName.trim() !== ''){
                    const response = await callDownload(type, targetName);
                    return '<br>'+targetName+".txt, msg: "+response.trim();
                }
                return '';
            }
            $("#btn_download").click(async function(){
                try {
                    const interfaceId = getFullSvcName();
                    let response = await callDownload('interface', interfaceId);
                    let resultMessage = '[인터페이스]<br>'+interfaceId+".txt, msg: "+response.trim();

                    let layoutResultMessage = await doDownload('layout', $('#inboundRequestLayout').val());
                    layoutResultMessage += await doDownload('layout', $('#outboundRequestLayout').val());
                    layoutResultMessage += await doDownload('layout', $('#outboundResponseLayout').val());
                    layoutResultMessage += await doDownload('layout', $('#inboundResponseLayout').val());
                    if(layoutResultMessage != null && layoutResultMessage.trim() != ''){
                        resultMessage += '<br>[레이아웃]'+layoutResultMessage;
                    }

                    let transformResultMessage = await doDownload('transform', $('#requestTransform').val());
                    transformResultMessage += await doDownload('transform', $('#responseTransform').val());
                    if(transformResultMessage != null && transformResultMessage.trim() != ''){
                        resultMessage += '<br>[변환]'+transformResultMessage;
                    }
                    // alert(resultMessage);
                    // $.alert({
                    // 	columnClass: 'col-md-8',
                    // 	title: '다운로드 처리 결과',
                    // 	content: resultMessage,
                    // });
                    window.parent.callAlert('다운로드 처리 결과', resultMessage);
                    // 처리된 데이터로 무언가를 수행
                } catch (error) {
                    console.error(error);
                    // 에러 처리
                }
            });
            buttonControl(isDetail);
            titleControl(isDetail);

            $('#toggleApiCacheYn').change(function() {
                if($(this).prop('checked')){
                    $('#collapseApiCache').collapse('show');
                }else{
                    $('#collapseApiCache').collapse('hide');
                }
            })
			
			$('#toggleTransformYn').change(function() {
			    if ($(this).prop('checked')) {
			        $('#toggleLayoutView').bootstrapToggle('off');
			        $('#toggleLayoutView').closest('.form-group').hide();
			        
			        $('#collapseTransform').collapse('show');
			        $('#requestTransform').closest('.form-group').show();
			        $('#responseTransform').closest('.form-group').show();
			    } else {
			        $('#collapseTransform').collapse('hide');
			        $('#toggleLayoutView').closest('.form-group').show();
			    }
			});
			
			$('#toggleLayoutView').change(function() {
			    if ($('#toggleTransformYn').prop('checked')) {
			        return;
			    }
			
			    if ($(this).prop('checked')) {
			        $('#collapseTransform').collapse('show');
			        $('#requestTransform').closest('.form-group').hide();
			        $('#responseTransform').closest('.form-group').hide();
			    } else {
			        $('#collapseTransform').collapse('hide');
			        $('#requestTransform').closest('.form-group').show();
			        $('#responseTransform').closest('.form-group').show();
			    }
			});
			
            if ($('#toggleTransformYn').prop('checked')) {
                 $('#toggleLayoutView').closest('.form-group').hide();
            } else {
                 $('#toggleLayoutView').closest('.form-group').show();
            }

            $('#toggleErrTransformYn').change(function() {
                if($(this).prop('checked')){
                    $('#rowErrResponseTransform').show();
                }else{
                    $('#rowErrResponseTransform').hide();
                }
                mappingBtnStateChange('ErrResponse');
            });

            $('#rowErrResponseTransform').hide();

            $('#toggleSimYn').change(function() {
                if($(this).prop('checked')){
                    $('#slideOutboundAdapter').carousel(0);
                }else{
                    $('#slideOutboundAdapter').carousel(1);
                }
            });
            $('[data-bs-toggle="tooltip"]').tooltip();

            addLayoutBtnEvent('inboundRequest', '인바운드 요청', 'SRCS');
            addLayoutBtnEvent('outboundRequest', '아웃바운드 요청', 'TGTS');
            addLayoutBtnEvent('outboundResponse', '아웃바운드 응답', 'TGTR');
            addLayoutBtnEvent('inboundResponse', '인바운드 응답', 'SRCR');
            addLayoutBtnEvent('inboundErrResponse', '인바운드 오류', 'SRCE');
            addLayoutBtnEvent('outboundErrResponse', '아웃바운드 오류', 'TGTE');

            window.addEventListener('message', function(e) {
                if (e.origin !== window.location.origin) return;

                const popupMessage = e.data;
                if (!popupMessage) return;

                if ('DELETE' == popupMessage.cmd) {
                    if ('layout' == popupMessage.type) {
                        $('#' + popupMessage.layoutPartName).val('');
                    }
                    if ('transform' == popupMessage.type) {
                        const partName = popupMessage.transformName.endsWith('REQ') ? '#requestTransform' : '#responseTransform';
                        $(partName).val('');
                    }
                    transformSetStateChange();
                    return; 
                }

				if(popupMessage.isLayoutView == "false") {
                	// 레이아웃 저장 후 변환 팝업 자동 실행 로직
	                if (popupMessage.action === 'LAYOUT_SAVED_OPEN_TRANSFORM') {
	
	                    // 눈이 보이지않는 팝업창 popup창 닫기
	                    if ($('.ui-dialog-content').length > 0) {
	                        $('.ui-dialog-content').dialog('close');
	                    }
	
	                    const part = popupMessage.layoutPartName || "";
	                    
	                    setTimeout(function() {
	                        if (part.includes('Request')) {
	                            modifyTransform('request');
	                        } else if (part.includes('Response')) {
	                            modifyTransform('response');
	                        } else if (part.includes('ErrResponse')) {
	                            modifyTransform('errResponse');
	                        }
	                    }, 300);
	                }
				}
            });
            // modifyLayout('inboundRequestLayout', '인바운드 요청', 'CBSS')
            
            $('#requestTransformButton').on("click", function(event) {
                modifyTransform('request');
            });
            $('#responseTransformButton').on("click", function(event) {
                modifyTransform('response');
            });
            $('#errResponseTransformButton').on("click", function(event) {
                modifyTransform('errResponse');
            });

            // 함수 사용 예시에 인바운드 응답 처리 추가
            $("#fromAdapter").change(function() {
                const adapterGroupName = $(this).val();
                adapterSelectChange('inbound', adapterGroupName);
                setInboundRoutingSlide();
            });

            $("#toAdapter").change(function() {
                const adapterGroupName = $(this).val();
                adapterSelectChange('outbound', adapterGroupName);
            });

            $("#fromResponseAdapter").change(function() {
                const alpineData = getApiInterface();
                if (alpineData.syncAsyncType === 'asyncSync') {
                    const adapterGroupName = $(this).val();
                    adapterSelectChange('inboundResponse', adapterGroupName);
                }
            });

            $("#toResponseAdapter").change(function() {
                const alpineData = getApiInterface();
                if (alpineData.syncAsyncType === 'syncAsync') {
                    const adapterGroupName = $(this).val();
                    adapterSelectChange('outboundResponse', adapterGroupName);
                }
            });

            $('#outboundRestPath').on('input', function() {
                checkTagVariableUrl();
            });

            function setupHeaderPairs() {
                headerValues.forEach(function(header, index) {
                    $('#headerPairs .header-pair:eq(' + index + ') input[name="headerValue"]').val(header);
                });
            }

            // 모달이 열릴 때마다 헤더 페어 설정
            $('#routingModal').on('show.bs.modal', setupHeaderPairs);

            // 저장 로직
            $('#saveRouting').click(function() {
                headerValues = [];
                $('#headerPairs .header-pair').each(function() {
                    var headerValue = $(this).find('input[name="headerValue"]').val();
                    if (headerValue !== '') {
                        headerValues.push(headerValue);
                    }
                });

                setHeaderRoutingLabel();

                // 모달 닫기
                $('#routingModal').modal('hide');
            });

            function setupStdCommonValueModal(type) {
                currentStandardMessageType = type;
                $('#stdCommonValuePairs input').val('');

                const items = type === 'outbound' ? standardMessageItems : inboundResponseStandardMessageItems;
                items.forEach(function(item) {
                    $('#stdCommonValuePairs input[columnname="'+item.COLUMNNAME+'"]').val(item.COLUMNVALUE);
                });
            }

            $('#saveStdCommonItems').click(function() {
                const newItems = [];
                $('#stdCommonValuePairs input').each(function() {
                    const inputVal = $(this).val();
                    const columnname = $(this).attr('columnname');
                    if (inputVal) {
                        newItems.push({
                            COLUMNNAME: columnname,
                            COLUMNVALUE: inputVal
                        });
                    }
                });

                if (currentStandardMessageType === 'outbound') {
                    standardMessageItems = newItems;
                    setStandardMessageItemsLabel(standardMessageItems, 'standardMessageItemsButton');
                } else {
                    inboundResponseStandardMessageItems = newItems;
                    setStandardMessageItemsLabel(inboundResponseStandardMessageItems, 'inboundResponseStandardMessageItemsButton');
                }

                $('#stdCommonValueModal').modal('hide');
            });

            function setupCloneInterfaceModal(event) {
				const eaiBzwkDstcd = $('#eaiBzwkDstcd').val();
				const eaiSvcName = $('#eaiSvcName').val();
				const eaiSvcDesc = $('#eaiSvcDesc').val();
				const inOutType = $('#inOutType').val();
				const sendRecvType = $('#sendRecvType').val();
				const inboundHttpMethod = $('#inboundHttpMethod').val();
				const inboundRestPath = $('#inboundRestPath').val();

				$('#newBizCode').val(eaiBzwkDstcd).trigger('change');
				$('#newSvcName').val(eaiSvcName);
				$('#newInOutType').val(inOutType);
				$('#newSendRecvType').val(sendRecvType);
				$('#newSvcDesc').val(eaiSvcDesc);
				$('#newInboundHttpMethod').val(inboundHttpMethod).trigger('change');
				$('#newInboundRestPath').val(inboundRestPath);
				                
                if($('#inboundRestPath').prop('disabled')){
                    $('#newRoutingOptionGroup').css('display','none');
                }else{
                    $('#newRoutingOptionGroup').css('display','block');
                }
            }
            $('#cloneInterfaceModal').on('show.bs.modal', setupCloneInterfaceModal);
            $('#doCloneInterfaceButton').click(function() {
                const orgApiInterfaceId = getFullSvcName();
                const newBizCode = $('#newBizCode').val();
                const newSvcName = $('#newSvcName').val();
                const newSvcDesc = $('#newSvcDesc').val();
                const newSendRecvType = $('#newSendRecvType').val();
                const newInOutType = $('#newInOutType').val();
                const newApiInterfaceId = newSvcName+newSendRecvType+newInOutType;
                const newInboundHttpMethod = $('#newInboundHttpMethod').val();

                $("input[name=newInboundRestPath]").val(function(index, value) {
    			    return value.replace(/^\/+/, ""); 
    			});

                const newInboundRestPath = $('#newInboundRestPath').val();

    			
                $.ajax({
                    type: "POST",
                    url: jsonUrl,
                    data: {
                        cmd: 'CLONE',
                        orgApiInterfaceId,
                        newBizCode,
                        newSvcDesc,
                        newApiInterfaceId,
                        newInboundHttpMethod,
                        newInboundRestPath,
                    },
                    beforeSend: function() {
                    	$("[id=doCloneInterfaceButton]").prop("disabled", true);
                    	$("#doCloneInterfaceButton").text("처리중 . . . . .");
                    },
                    success: function () {
                        alert("["+orgApiInterfaceId+"] => ["+newBizCode+"]["+newApiInterfaceId+"] 복제 완료.");
                        $('#cloneInterfaceModal').modal('hide');
                        goNav(returnUrl);//LIST로 이동
                    },
                    error: function (e) {
                        alert(e.responseText);
                    },
                    complete: function() {
                    	$("[id=doCloneInterfaceButton]").prop("disabled", false);
    					$("#doCloneInterfaceButton").text("복제");
                    }
                });
            });

			   // 25.11.25 엑셀다운로드 사용안함.
//             $("#btn_excel_export").click(function () {
//                 const url = url_excel + '?cmd=DETAIL_EXPORT_TO_EXCEL';
//                 const params = new URLSearchParams();
//                 params.append('eaiSvcName', getFullSvcName());
//                 downloadFiles(url, params);
//                 return false;
//             });
			
			
			// JSON 다운로드
            $("#btn_json_export").click(function () {
                const uri = url + '?cmd=DETAIL_EXPORT_TO_JSON';
                const params = new URLSearchParams();
                params.append('eaiSvcName', getFullSvcName());

                downloadFiles(uri, params);

                return false;
            });

            // 이벤트 리스너 수정
            $('#standardMessageItemsButton').click(function() {
                setupStdCommonValueModal('outbound');
                $('#stdCommonValueModalLabel').text('아웃바운드 표준 전문 공통부 값 수정');
                $('#stdCommonValueModal').modal('show');
            });

            $('#inboundResponseStandardMessageItemsButton').click(function() {
                setupStdCommonValueModal('inboundResponse');
                $('#stdCommonValueModalLabel').text('인바운드 응답 표준 전문 공통부 값 수정');
                $('#stdCommonValueModal').modal('show');
            });


        });

        function checkTagVariableUrl(){
            // 이벤트 처리 로직을 여기에 작성합니다.
            const changedValue = $('#outboundRestPath').val();
            const regex = /\{.*\}/;

            if (regex.test(changedValue)) {
                $('#tagVariableUrl').css('display', 'inline');
            } else {
                $('#tagVariableUrl').css('display', 'none');
            }
        }

        function makeValidate(){
            $.validator.addMethod("idRegex", function(value, element) {
                return this.optional(element) || /^[a-z0-9\-_]+$/i.test(value);
            }, "ID값은 영문자, 숫자, 대시(-), 언더바(_)만 허용됩니다.");
            $("#ajaxForm").validate({
                ignore: ":hidden, [readonly=readonly]",
                rules: {
                    eaiSvcName: {required: true, idRegex: true}
                },
                //messages: {
                //	eaiSvcName: "API 명을 입력하세요."
                //},
                errorElement: "em",
                errorPlacement: function ( error, element ) {
                    // Add the `invalid-feedback` class to the error element
                    error.addClass( "invalid-feedback" );

                    if ( element.prop( "type" ) === "checkbox" ) {
                        error.insertAfter( element.next( "label" ) );
                    } else {
                        if($(element).next() != null && 'input-group-prepend' == $(element).next().attr('class')){
                            error.insertAfter( $(element).next().get(0) );
                        }else{
                            error.insertAfter( element );
                        }
                    }
                },
                highlight: function ( element, errorClass, validClass ) {
                    $( element ).addClass( "is-invalid" ).removeClass( "is-valid" );
                },
                unhighlight: function (element, errorClass, validClass) {
                    $( element ).addClass( "is-valid" ).removeClass( "is-invalid" );
                }
            });
        }
        function displaySelectedValue() {
            var selectedValue = document.querySelector('input[name="exampleRadios"]:checked').value;
            document.getElementById('selectedValue').textContent = "Selected Value: " + selectedValue;
        }
    </script>
</head>
<body>
<div class="right_box">
    <div class="content_top">
        <ul class="path">
            <li><a href="#">${rmsMenuPath}</a></li>
        </ul>
    </div><!-- end content_top -->
    <div class="content_middle" style="margin-top: 40px">
        <div class="search_wrap">
            <button type="button" class="cssbtn" id="btn_clone" level="W" status="DETAIL" data-bs-toggle="modal" data-bs-target="#cloneInterfaceModal"><i class="material-icons">content_copy</i> <%=localeMessage.getString("button.clone2")%></button></button>
            <button type="button" class="cssbtn" id="btn_json_export" level="R" status="DETAIL,NEW"><i class="material-icons">download</i> <%=localeMessage.getString("button.exportJson")%></button></button>
            <button type="button" class="cssbtn" id="btn_delete" level="W" status="DETAIL"><i class="material-icons">delete</i> <%= localeMessage.getString("button.delete") %></button>
            <button type="button" class="cssbtn" id="btn_modify" level="R" status="DETAIL,NEW"><i class="material-icons">save</i> <%= localeMessage.getString("button.modify") %></button>
            <!-- v1: 기존 API 스펙 (모달) — 기능 비교용 복원 -->
            <button type="button" class="cssbtn" id="btn_api_spec" level="R" status="DETAIL"><i class="material-icons">description</i> API 스펙(삭제예정)</button>
            <!-- v2: 신규 OpenAPI Spec (새 탭) -->
            <button type="button" class="cssbtn" id="btn_openapi_spec" level="R" status="DETAIL"><i class="material-icons">api</i> OpenAPI Spec</button>
            <button type="button" class="cssbtn" id="btn_previous" level="R" status="DETAIL,NEW"><i class="material-icons">arrow_back</i> <%= localeMessage.getString("button.previous") %></button>
        </div>
        <div class="title" id="title" style="font-size:1.4em">${rmsMenuName}</div>
        <form id="ajaxForm"
              x-data="apiInterfaceManager">
            <input type="hidden" name="sevrLogLvelNo" ></input>
            <div class="row">
                <div class="col-md-12">
                    <fieldset class="groupbox-border" style="margin-top:0px !important">
                        <legend class="groupbox-border">BASIC OPTIONS</legend>
                        <div class="row">
                            <div class="form-group col-md-2">
                                <label for="eaiBzwkDstcd"><span class="material-icons-outlined">work</span> 업무구분</label>
                                <select id="eaiBzwkDstcd" class="form-select" name="eaiBzwkDstcd" style="width: 100%">
                                </select>
                            </div>
                            
							<div class="form-group col-md-3">
							    <label for="eaiSvcName">
							        <span class="material-icons-outlined">badge</span> <%= localeMessage.getString("eaiMessage.eaiSvcName")%>
							    </label>
							    <div class="input-group">
							        <input type="text" 
							               class="form-control" 
							               id="eaiSvcName" 
							               name="eaiSvcName" 
							               required>
							        <span class="input-group-text" id="sendRecvTypeSpan" style="padding: 0; border: none;">
							            <input type="text" id="sendRecvType" name="sendRecvType"
							                   class="ignore form-control"
							                   readonly="readonly"
							                   style="width: 40px; text-align: center; border-radius: 0; margin-left: -1px;"
							                   :value="apiInterface.requestType">
							        </span>
							        <span class="input-group-text" id="inOutTypeSpan" style="padding: 0; border: none;">
							            <input type="text" id="inOutType" name="inOutType"
							                   class="ignore form-control"
							                   readonly="readonly"
							                   style="width: 40px; text-align: center; border-radius: 0; margin-left: -1px;"
							                   :value="apiInterface.wordType">
							        </span>
							    </div>
							</div>
							
                            <div class="form-group col-md-4">
                                <label for="eaiSvcDesc"><span class="material-icons-outlined">chat</span> API 명</label>
                                <input type="text" class="form-control" id="eaiSvcDesc" name="eaiSvcDesc" required></input>
                            </div>
                            <div class="form-group col-md-1">
                                <label for="toggleTransformYn"><span class="material-icons">account_tree</span> 전문변환</label><br>
                                <input type="checkbox" name="toggleTransformYn" id="toggleTransformYn" data-toggle="toggle" data-onstyle="success"  data-on="사용" data-off="미사용" data-width="100" data-offstyle="secondary" data-style="ios" />
                            </div>
                            <div class="form-group col-md-1">
						    <label for="toggleLayoutView"><span class="material-icons">visibility</span> 전문보기</label><br>
						    <input type="checkbox" id="toggleLayoutView" data-toggle="toggle" data-onstyle="info" data-on="보기" data-off="숨김" data-width="100" data-offstyle="secondary" data-style="ios" />
							</div>
                            <div class="form-group col-md-1">
							<label for="toggleSimYn"><span class="material-icons" >science</span> 가상응답</label><br>
								<input type="checkbox" name="toggleSimYn" id="toggleSimYn" data-toggle="toggle" data-onstyle="success" data-on="사용" data-off="미사용" data-width="100" data-offstyle="secondary" data-style="ios"/>
							</div>
                        </div>
                    </fieldset>
                </div>
            </div>
            <div class="row">
                <div class="col-md-12">
                    <!-- 기존 인터페이스 타입 영역을 Alpine 컴포넌트로 감싸기 -->
                    <fieldset class="groupbox-border">
                        <legend class="groupbox-border">INTERFACE TYPE</legend>
                        <div class="row">
                        	<!-- <div class="form-group col-md-3">
                            <label for="eaiBzwkDstcd"><span class="material-icons-outlined">sync</span> Sync/Async 타입</label><br>
	                            <div class="btn-group" id="btnGroupSyncAsync" role="group">
	                                <input type="radio"
	                                       class="btn-check"
	                                       name="btnRadioSyncAsync"
	                                       id="btnTypeSync"
	                                       value="sync"
	                                       x-model="apiInterface.syncAsyncType">
	                                <label class="btn btn-outline-primary" for="btnTypeSync">
	                                    <i class="bi bi-arrow-repeat"></i> Sync
	                                </label>
	
	                                <input type="radio"
	                                       class="btn-check"
	                                       name="btnRadioSyncAsync"
	                                       id="btnTypeAsync"
	                                       value="async"
	                                       x-model="apiInterface.syncAsyncType">
	                                <label class="btn btn-outline-primary" for="btnTypeAsync">
	                                    <i class="bi bi-arrow-left-right"></i> Async
	                                </label>
	
	                                <input type="radio"
	                                       class="btn-check"
	                                       name="btnRadioSyncAsync"
	                                       id="btnTypeAsyncSync"
	                                       value="asyncSync"
	                                       x-model="apiInterface.syncAsyncType">
	                                <label class="btn btn-outline-primary" for="btnTypeAsyncSync">
	                                    <i class="bi bi-arrow-return-left"></i> A > S
	                                </label>
	                                
									<input type="radio" 
											class="btn-check" 
											name="btnRadioSyncAsync" 
											id="btnTypeSyncAsync" 
											value="syncAsync"
											x-model="apiInterface.syncAsyncType">
									<label class="btn btn-outline-primary" for="btnTypeSyncAsync">
										<i class="bi bi-share-fill"></i> S > A
									</label>
	                            </div>
	                        </div> -->
                            <div class="form-group col-md-3">
								<label for="eaiBzwkDstcd">요청/응답 구분</label><br>
								<div class="btn-group" role="group" aria-label="Basic radio toggle button group"
								     x-effect="if (apiInterface.syncAsyncType !== 'async') apiInterface.requestType = 'S'">
										<input type="radio" class="btn-check" name="btnRadioReqRes" id="btnTypeRequest" 
											x-model="apiInterface.requestType" 
											value="S" :disabled="$store.formState.isReqResDisabled">
										<label class="btn btn-outline-primary" for="btnTypeRequest"><i class="bi bi-arrow-bar-right"></i> 요청</label>
	
										<input type="radio" class="btn-check" name="btnRadioReqRes" id="btnTypeResponse" 
											x-model="apiInterface.requestType"
											value="R" :disabled="$store.formState.isReqResDisabled">
										<label class="btn btn-outline-primary" for="btnTypeResponse"><i class="bi bi-arrow-bar-left"></i> 응답</label>
								</div>
							</div>
							<div class="form-group col-md-3">
								<label for="eaiBzwkDstcd">당/타발 구분</label><br>
								<div class="btn-group" role="group" aria-label="Basic radio toggle button group">
									<input type="radio" class="btn-check" name="btnRadioInOut" id="btnTypeInword" value="1" x-model="apiInterface.wordType" checked>
									<label class="btn btn-outline-primary" for="btnTypeInword"><i class="bi bi-arrow-right-circle"></i> 당발</label>

									<input type="radio" class="btn-check" name="btnRadioInOut" id="btnTypeOutword" value="2" x-model="apiInterface.wordType">
									<label class="btn btn-outline-primary" for="btnTypeOutword"><i class="bi bi-arrow-left-circle"></i> 타발</label>
								</div>
							</div>
							<input type="hidden" id="apiFullPath" value="">
                        </div>
                    </fieldset>
                </div>
                <div class="col-md-10">
                    <fieldset class="groupbox-border">
                        <legend class="groupbox-border">TRANSACTION OPTIONS</legend>
                        <div class="row">
                            <div class="form-group col-md-2">
                                <label for="svcLogLvelNo"><span class="material-icons-outlined">assignment</span> 로그레벨</label>
                                <select id="svcLogLvelNo" class="form-select" name="svcLogLvelNo"></input>
                                    <option value="0">[0]로그 OFF</option>
                                    <option value="1">[1]오류 로그만(900)</option>
                                    <option value="2">[2]인바운드(100,400)</option>
                                    <option value="3" selected>[3]전체로그</option>
                                    <option value="4">[4]업무데이터 제외</option>
                                </select>
                            </div>
                            <div class="form-group col-md-2">
                                <label for="toutVal"><span class="material-icons-outlined">timer</span> 타임아웃 값</label>
                                <input type="number" class="form-control" id="toutVal" name="toutVal" required></input>
                            </div>
                            <div class="form-group col-md-2" x-show="showInboundResponse">
									<label for="toutVal"><span class="material-icons-outlined">timer</span> 타임아웃 값2</label>
									<input type="number" class="form-control" id="toutVal2" name="toutVal2" required :disabled="!showInboundResponse"></input>
							</div>
							<div id="contentTypePart" class="form-group col-md-6">
									<label for="contentType"><span class="material-icons-outlined">movie</span> Content-Type (기본값:application/json)</label>
									<input type="text" class="form-control" id="contentType" name="restContentType"></input>
							</div>
                        </div>
                    </fieldset>
                </div>
                <div class="col-md-2">
                    <fieldset class="groupbox-border">
                        <legend class="groupbox-border">AUTH</legend>
                        <div class="row">
                            <div class="form-group col-md-12">
                                <label for="authType"><span class="material-icons-outlined">vpn_key</span> 인증타입</label>
                                <select id="authType" class="form-select" name="authType"></input>
                                    <option value="none" selected>NONE</option>
                                    <option value="oauth">OAUTH</option>
                                    <option value="api_key">API_KEY</option>
                                    <!-- <option value="ca">CA</option> -->
                                </select>
                            </div>
                        </div>
                    </fieldset>
                </div>
            </div>
            <div class="row">
                <div class="col-md-12">
                    <fieldset class="groupbox-border">
                        <legend class="groupbox-border">ADAPTERS</legend>
                        <div class="row">
                            <div class="form-group col-md-6">
                                <label for="fromAdapter"><span class="material-icons">login</span> INBOUND 어댑터</label>
                                <select id="fromAdapter" class="form-select" name="fromAdapter" required></select>
                                <small id="fromAdapterUrl" class="form-text text-muted" style="margin-bottom:-20px"></small>
                            </div>
                            <div class="form-group col-md-6">
                                <label for="toAdapter"><span class="material-icons">logout</span> OUTBOUND 어댑터</label>
                                <div id="slideOutboundAdapter" class="carousel slide" data-ride="carousel" data-interval="false">
                                    <div class="carousel-inner" style="margin-bottom:-20px">
                                        <div class="carousel-item" style="text-align: center;">
                                            <h1 style="font-family: Righteous">USING SIMULATION ADAPTER</h1>
                                        </div>
                                        <div class="carousel-item active">
                                            <select id="toAdapter" class="form-select" name="toAdapter" required></select>
                                            <small id="toAdapterUrl" class="form-text text-muted"></small>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="row">
                            <div class="form-group col-md-6">
                             	<div x-show="showInboundResponse">
	                                <label for="fromResponseAdapter">
	                                    <span class="material-icons">keyboard_return</span>
	                                    INBOUND (ASYNC) 응답 어댑터
	                                </label>
	                                <select id="fromResponseAdapter"
	                                        class="form-select"
	                                        name="fromResponseAdapter"
	                                        required
	                                        :disabled="!showInboundResponse">
	                                </select>
	                                <small id="fromResponseAdapterUrl" class="form-text text-muted"></small>
                            	</div>
                        	</div>
                            <div class="form-group col-md-6">
                            	<!-- toAdapterUrl 겹치지 않도록 mt-3 속성 추가 -->
                             	<div class="mt-3" x-show="showOutboundResponse">
	                                <label for="toResponseAdapter">
	                                    <span class="material-icons">keyboard_return</span>
	                                    OUTBOUND (ASYNC) 응답 어댑터
	                                </label>
	                                <select id="toResponseAdapter"
	                                        class="form-select"
	                                        name="toResponseAdapter"
	                                        required
	                                        :disabled="!showOutboundResponse">
	                                </select>
	                                <small id="toResponseAdapterUrl" class="form-text text-muted"></small>
                            	</div>
                        	</div>
                        </div>
                    </fieldset>
                </div>
            </div>
            <div class="row">
                <div class="col-md-6">
                    <fieldset class="groupbox-border">
                        <legend class="groupbox-border">INBOUND ROUTING</legend>
                        <div class="row">
                            <div class="col-md-4">
                                <label for="inboundHttpMethod">
                                    <span class="material-icons">http</span>
                                    <%= localeMessage.getString("apiInterface.recvMethod") %>
                                </label>
                                <select id="inboundHttpMethod" class="form-select" name="inboundHttpMethod" disabled>
                                    <option value="post">POST</option>
                                    <option value="get">GET</option>
                                    <option value="put">PUT</option>
                                    <option value="patch">PATCH</option>
                                    <option value="delete">DELETE</option>
                                </select>
                            </div>
                            <div class="form-group col-md-8">
                                <div id="slideInboundRoutingRule">
                                    <div class="row">
                                        <div class="col-md-12">
                                            <label for="inboundRestPath">
                                                <span class="material-icons">link</span>
                                                수신 REST PATH(URL)
                                            </label>
                                            <input type="text" class="form-control" id="inboundRestPath"
                                                   name="inboundRestPath" disabled>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="collapse mt-2" id="collapseInboundRoutingInfo">
                        	<div class="form-group col-md-12">
                                 <label>
                                     <span class="material-icons justify-content-md-start">http</span>
                                     수신 라우팅 정보
                                 </label>
                                 <div class="d-grid gap-2">
                                     <button type="button" id="headerRoutingButton" class="btn btn-primary"
                                             data-bs-toggle="modal" data-bs-target="#routingModal">
                                         수정
                                     </button>
                                 </div>
                          	</div>
                        </div>
                        <div id="inboundResponseMethodPathRow"
                             x-show="showInboundResponse">
                            <div id="inboundResponseRestPart" class="row">
                                <div class="form-group col-md-4">
                                    <label for="inboundResponseHttpMethod">
                                        <span class="material-icons">http</span>
                                        응답 송신 메소드
                                    </label>
                                    <select id="inboundResponseHttpMethod"
                                            class="form-select"
                                            name="inboundResponseHttpMethod"
                                            disabled>
                                        <option value="post">POST</option>
                                        <option value="get">GET</option>
                                        <option value="put">PUT</option>
                                        <option value="patch">PATCH</option>
                                        <option value="delete">DELETE</option>
                                    </select>
                                </div>
                                <div class="form-group col-md-8">
                                    <label for="inboundResponseRestPath">
                                        <span class="material-icons">link</span>
                                        응답 송신 REST PATH(URL)
                                    </label>
                                    <input type="text"
                                           class="form-control"
                                           id="inboundResponseRestPath"
                                           name="inboundResponseRestPath"
                                           disabled>
                                </div>
                            </div>
                            <!-- 표준전문 공통부 값 -->
                            <div id="inboundResponseCommonFieldPart" class="row" style="display:none">
                                <div class="form-group col-md-12">
                                    <label for="inboundResponseStandardMessageItemsButton">
                                        <span class="material-icons-outlined">view_list</span>
                                        표준전문 공통부 값
                                    </label>
                                    <div class="d-grid gap-2">
                                        <button type="button"
                                                id="inboundResponseStandardMessageItemsButton"
                                                class="btn btn-primary"
                                                data-bs-toggle="modal"
                                                data-bs-target="#stdCommonValueModal">
                                            수정
                                        </button>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </fieldset>
                </div>
				<div class="col-md-6">
				    <fieldset class="groupbox-border">
				        <legend class="groupbox-border">OUTBOUND ROUTING</legend>
				        <div id="outboundRoutingContent">
				            <div class="row" id="standardOutboundOptions">
				                <div class="form-group col-md-4">
				                    <label for="outboundHttpMethod">
				                        <span class="material-icons">http</span>
				                        송신 메소드
				                    </label>
				                    <select id="outboundHttpMethod" class="form-select" name="outboundHttpMethod" disabled>
				                        <option value="post">POST</option>
				                        <option value="get">GET</option>
				                        <option value="put">PUT</option>
				                        <option value="patch">PATCH</option>
				                        <option value="delete">DELETE</option>
				                    </select>
				                </div>
				                <div class="form-group col-md-8">
				                    <label for="outboundRestPath">
				                        <span class="material-icons">link</span>
				                        <span class="badge badge-warning" id="tagVariableUrl" style="display: none">가변</span>
				                        송신 REST PATH(URL)
				                    </label>
				                    <input type="text" class="form-control" id="outboundRestPath"
				                           name="outboundRestPath" disabled>
				                </div>
				            </div>
                            <div id="commonFieldPart" class="row" style="display:none">
                                <div class="form-group col-md-12">
                                    <label for="standardMessageItemsButton">
                                        <span class="material-icons-outlined">view_list</span>
                                        표준전문 공통부 값
                                    </label>
                                    <div class="d-grid gap-2">
                                        <button type="button" id="standardMessageItemsButton" class="btn btn-primary"
                                                data-bs-toggle="modal" data-bs-target="#stdCommonValueModal">
                                            수정
                                        </button>
                                    </div>
                                </div>
                            </div>				            
				
				            <div id="outboundResponseMethodPathRow" 
				            		x-show="showOutboundResponse">
				                <div id="outboundResponseRestPart" class="row">
				                    <div class="form-group col-md-4">
				                        <label for="outboundResponseHttpMethod">
				                            <span class="material-icons">http</span>
				                            응답 수신 메소드
				                        </label>
				                        <select id="outboundResponseHttpMethod" class="form-select" name="outboundResponseHttpMethod" disabled>
					                        <option value="post">POST</option>
					                        <option value="get">GET</option>
					                        <option value="put">PUT</option>
					                        <option value="patch">PATCH</option>
					                        <option value="delete">DELETE</option>
				                        </select>
				                    </div>
				                    <div class="form-group col-md-8">
				                        <label for="outboundResponseRestPath">
				                            <span class="material-icons">link</span>
				                            응답 수신 REST PATH(URL)
				                        </label>
				                        <input type="text" class="form-control" id="outboundResponseRestPath" name="outboundResponseRestPath" disabled>
				                    </div>
				                </div>

					            <div id="outboundResponseCommonFieldPart" class="row" style="display:none">
					                <div class="form-group col-md-12">
					                    <label for="standardMessageItemsButton">
					                        <span class="material-icons-outlined">view_list</span>
					                        표준전문 공통부 값
					                    </label>
					                    <div class="d-grid gap-2">
					                        <button type="button" id="standardMessageItemsButton" class="btn btn-primary"
					                                data-bs-toggle="modal" data-bs-target="#stdCommonValueModal">
					                            수정
					                        </button>
					                    </div>
					                </div>
					            </div>
				            </div>
				        </div>
				    </fieldset>
				</div>
            </div>
            <div class="collapse" id="collapseTransform">
                <div class="row">
                    <div class="col-md-12">
                        <fieldset class="groupbox-border">
                            <div style="display: flex; align-items: center;">
                                <legend class="groupbox-border" style="display: contents">변환정보</legend>
                            </div>
                            <div class="row" id="rowRequestTransform">
                                <div class="form-group col-md-4">
                                    <label for="inboundRequestLayout"><span class="material-icons-outlined">keyboard_double_arrow_right</span> 인바운드 요청</label>
                                    <div class="input-group">
                                        <input type="text" class="form-control" id="inboundRequestLayout" name="inboundRequestLayout" placeholder="인바운드 요청 레이아웃 없음" readonly>
                                        <div class="input-group-append">
                                            <button class="btn btn-info" id="inboundRequestButton" type="button" data-bs-toggle="tooltip">생성</button>
                                        </div>
                                    </div>
                                </div>
                                <div class="form-group col-md-4">
                                    <label for="requestTransform"><span class="material-icons-outlined">keyboard_double_arrow_right</span> 요청변환</label>
                                    <div class="input-group">
                                        <input type="text" class="form-control" id="requestTransform" name="requestTransform" placeholder="요청 변환 없음" readonly>
                                        <div class="input-group-append">
													<span tabindex="0" id="requestTransformButtonTooltip" data-bs-toggle="tooltip" data-html="true" title="매핑룰을 등록할 수 없습니다. 우선 요청 레이아웃을 모두 등록하세요.">
														<button class="btn btn-secondary" id="requestTransformButton" type="button" >생성</button>
													</span>
                                        </div>
                                    </div>
                                </div>
                                <div class="form-group col-md-4">
                                    <label for="outboundRequestLayout"><span class="material-icons-outlined">keyboard_double_arrow_right</span> 아웃바운드 요청</label>
                                    <div class="input-group">
                                        <input type="text" class="form-control" id="outboundRequestLayout" name="outboundRequestLayout" placeholder="아웃바운드 요청 레이아웃 없음" readonly>
                                        <div class="input-group-append">
                                            <button class="btn btn-info" id="outboundRequestButton" type="button" data-bs-toggle="tooltip">생성</button>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="row" id="rowResponseTransform">
                                <div class="form-group col-md-4">
                                    <label for="inboundResponseLayout"><span class="material-icons-outlined">keyboard_double_arrow_left</span> 인바운드 응답</label>
                                    <div class="input-group">
                                        <input type="text" class="form-control" id="inboundResponseLayout" name="inboundResponseLayout" placeholder="인바운드 응답 레이아웃 없음" readonly>
                                        <div class="input-group-append">
                                            <button class="btn btn-info" id="inboundResponseButton" type="button" data-bs-toggle="tooltip">생성</button>
                                        </div>
                                    </div>
                                </div>
                                <div class="form-group col-md-4">
                                    <label for="responseTransform"><span class="material-icons-outlined">keyboard_double_arrow_left</span> 응답변환</label>
                                    <div class="input-group">
                                        <input type="text" class="form-control" id="responseTransform" name="responseTransform" placeholder="응답 변환 없음" readonly>
                                        <div class="input-group-append">
													<span tabindex="0" id="responseTransformButtonTooltip" data-bs-toggle="tooltip" data-html="true" title="매핑룰을 등록할 수 없습니다. 우선 응답 레이아웃을 모두 등록하세요.">
														<button class="btn btn-secondary" id="responseTransformButton" type="button">생성</button>
													</span>
                                        </div>
                                    </div>
                                </div>
                                <div class="form-group col-md-4">
                                    <label for="outboundResponseLayout"><span class="material-icons-outlined">keyboard_double_arrow_left</span> 아웃바운드 응답</label>
                                    <div class="input-group">
                                        <input type="text" class="form-control" id="outboundResponseLayout" name="outboundResponseLayout" placeholder="아웃바운드 응답 레이아웃 없음" readonly>
                                        <div class="input-group-append">
                                            <button class="btn btn-info" id="outboundResponseButton" type="button" data-bs-toggle="tooltip">생성</button>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div style="margin-top: 10px;">
                                <label for="toggleErrTransformYn"><span class="material-icons-outlined">error_outline</span> 오류 변환</label>
                                <input type="checkbox" name="toggleErrTransformYn" id="toggleErrTransformYn"
                                       data-toggle="toggle" data-onstyle="success" data-offstyle="secondary"
                                       data-height="1" data-width="40" data-size="xs"/>
                            </div>
                            <div class="row" id="rowErrResponseTransform">
                                <div class="form-group col-md-4">
                                    <label for="inboundErrResponseLayout">
                                        <span class="material-icons-outlined">keyboard_double_arrow_left</span> 인바운드 오류 응답
                                    </label>
                                    <div class="input-group">
                                        <input type="text" class="form-control" id="inboundErrResponseLayout"
                                               name="inboundErrResponseLayout" placeholder="인바운드 오류 레이아웃 없음" readonly>
                                        <div class="input-group-append">
                                            <button class="btn btn-info" id="inboundErrResponseButton"
                                                    type="button" data-bs-toggle="tooltip">생성</button>
                                        </div>
                                    </div>
                                </div>
                                <div class="form-group col-md-4">
                                    <label for="errResponseTransform">
                                        <span class="material-icons-outlined">error_outline</span> 오류 응답 변환
                                    </label>
                                    <div class="input-group">
                                        <input type="text" class="form-control" id="errResponseTransform"
                                               name="errResponseTransform" placeholder="오류 변환 없음" readonly>
                                        <div class="input-group-append">
                                            <span tabindex="0" id="errResponseTransformButtonTooltip"
                                                  data-bs-toggle="tooltip" data-html="true"
                                                  title="매핑룰을 등록할 수 없습니다. 우선 오류 레이아웃을 모두 등록하세요.">
                                                <button class="btn btn-secondary" id="errResponseTransformButton"
                                                        type="button">생성</button>
                                            </span>
                                        </div>
                                    </div>
                                </div>
                                <div class="form-group col-md-4">
                                    <label for="outboundErrResponseLayout">
                                        <span class="material-icons-outlined">keyboard_double_arrow_left</span> 아웃바운드 오류 응답
                                    </label>
                                    <div class="input-group">
                                        <input type="text" class="form-control" id="outboundErrResponseLayout"
                                               name="outboundErrResponseLayout" placeholder="아웃바운드 오류 레이아웃 없음" readonly>
                                        <div class="input-group-append">
                                            <button class="btn btn-info" id="outboundErrResponseButton"
                                                    type="button" data-bs-toggle="tooltip">생성</button>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </fieldset>
                    </div>
                </div>
            </div>
        </form>
    </div><!-- end content_middle -->
    <div class="modal fade" id="routingModal" tabindex="-1" role="dialog" aria-labelledby="routingModalLabel" aria-hidden="true">
        <div class="modal-dialog" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title" id="routingModalLabel">MessageKey 기반 라우팅 수정</h5>
                    <button type="button" class="close" data-bs-dismiss="modal" aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                    </button>
                </div>
                <div class="modal-body">
                    <form id="routingForm">
                        <div id="headerPairs">
                        </div>
                    </form>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">닫기</button>
                    <button type="button" class="btn btn-primary" id="saveRouting">적용</button>
                </div>
            </div>
        </div>
    </div>
    <div class="modal fade" id="stdCommonValueModal" tabindex="-1" role="dialog" aria-labelledby="stdCommonValueModalLabel" aria-hidden="true">
        <div class="modal-dialog modal-lg" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title" id="stdCommonValueModalLabel">표준 전문 공통부 값 수정</h5>
                    <button type="button" class="close" data-bs-dismiss="modal" aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                    </button>
                </div>
                <div class="modal-body">
                    <h6 class="modal-title">해당 값을 설정하면 표준전문 공통부에 설정됩니다.</h6>
                    <form id="stdCommonValueForm">
                        <div id="stdCommonValuePairs">
                            <!-- 동적으로 생성되는 필드들이 여기에 들어갑니다 -->
                        </div>
                    </form>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">닫기</button>
                    <button type="button" class="btn btn-primary" id="saveStdCommonItems">적용</button>
                </div>
            </div>
        </div>
    </div>
    <div class="modal fade" id="cloneInterfaceModal" tabindex="-1" role="dialog" aria-labelledby=cloneInterfaceModalLabel" aria-hidden="true">
        <div class="modal-dialog modal-xl" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title" id="cloneInterfaceModalLabel">API 인터페이스 복제</h5>
                    <button type="button" class="close" data-bs-dismiss="modal" aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                    </button>
                </div>
                <div class="modal-body">
                    <h6 class="modal-title mb-2">[<span id="cloneOrgInterfaceIdDesc" ></span>]에서 복제 할 업무코드, API ID, REST PATH 정보 입력하세요(저장 되어있는 API 기준으로 복제)</h6>
                    <form id="cloneInterfaceForm">
                        <fieldset class="groupbox-border" style="margin-top:0px !important">
                            <legend class="groupbox-border">BASIC</legend>
                            <div class="row">
                                <div class="form-group col-md-2">
                                    <label for="newBizCode"><span class="material-icons-outlined">work</span> 업무구분</label>
                                    <select id="newBizCode" class="form-select" name="newBizCode" style="width: 100%">
                                    </select>
                                </div>
                                <div class="form-group col-md-6">
                                    <label for="newSvcName"><span class="material-icons-outlined">badge</span> <%= localeMessage.getString("eaiMessage.eaiSvcName")%></label>
                                    <div class="input-group">
                                        <input type="text" class="form-control" id="newSvcName" name="newSvcName" required>
                                        <span class="input-group-text" style="padding: 0; border: none;">
												<input type="text" id="newSendRecvType" name="newSendRecvType" class="ignore form-control" readonly="readonly" style="width: 40px; text-align: center; border-radius: 0; margin-left: -1px;" value="S">
											</span>
                                        <span class="input-group-text" style="padding: 0; border: none;">
												<input type="text" id="newInOutType" name="newInOutType" class="ignore form-control" readonly="readonly" style="width: 40px; text-align: center; border-radius: 0; margin-left: -1px;" value="1">
											</span>
                                    </div>
                                </div>
                                <div class="form-group col-md-4">
                                    <label for="newSvcDesc"><span class="material-icons-outlined">badge</span> API 명</label>
                                    <div class="input-group">
                                        <input type="text" class="form-control" id="newSvcDesc" name="newSvcDesc">
                            		</div>
                            	</div>
                            </div>
                        </fieldset>
                        <fieldset id="newRoutingOptionGroup" class="groupbox-border">
                            <legend class="groupbox-border">ROUTING</legend>
                            <div class="row">
                                <div class="form-group col-md-4">
                                    <label for="newInboundHttpMethod"><span class="material-icons">http</span> <%= localeMessage.getString("apiInterface.recvMethod") %></label>
                                    <select id="newInboundHttpMethod" class="form-select" name="newInboundHttpMethod"></input>
                                        <option value="post">POST</option>
                                        <option value="get">GET</option>
                                        <option value="put">PUT</option>
                                        <option value="patch">PATCH</option>
                                        <option value="delete">DELETE</option>
                                    </select>
                                </div>
                                <div class="form-group col-md-8">
                                    <label for="newInboundRestPath"><span class="material-icons">link</span> 수신 REST PATH(URL)</label>
                                    <input type="text" class="form-control" id="newInboundRestPath" name="newInboundRestPath"></input>
                                </div>
                            </div>
                        </fieldset>
                    </form>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">닫기</button>
                    <button type="button" class="btn btn-primary" id="doCloneInterfaceButton">복제</button>
                </div>
            </div>
        </div>
    </div>
</div><!-- end right_box -->
</body>
</html>
                </div>
            </div>
        </div>
    </div>
</div><!-- end right_box -->
</body>
</html>