package com.eactive.eai.custom.inbound.action;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;

import com.eactive.eai.adapter.AdapterGroupVO;
import com.eactive.eai.adapter.AdapterManager;
import com.eactive.eai.adapter.Keys;
import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceKey;
import com.eactive.eai.adapter.http.dynamic.impl.HttpAdapterServiceRest;
import com.eactive.eai.common.exception.ExceptionUtil;
import com.eactive.eai.common.stdmessage.STDMessageManager;
import com.eactive.eai.common.util.MessageKeyExtractor;
import com.eactive.eai.inbound.action.ActionException;
import com.eactive.eai.inbound.action.RequestActionSupport;

public class RestAdapterMethodUrlFallbackRequestAction extends RequestActionSupport {

    /**
     * 1. 기능 : Inbound Adapter를 통해 전달받은 비표준메시지에서 표준메시지를 생성하기 위한 키값을 추출
     * 2. 처리 개요 :
     *     - TYPE_HTTP_CUSTOM / TYPE_REST: 전체 URI로 키를 먼저 조회하고,
     *       없으면 뒤 경로를 하나씩 제거하면서 일치하는 키를 탐색한다.
     *     - 그 외: MessageKeyExtractor를 통해 추출
     *
     * @param message Object 타입의 요청메시지
     * @return String 비표준메시지의 메시지키값
     **/
    public String[] perform(Object message) throws ActionException {
        String[] key = null;

        AdapterManager adapterManager = AdapterManager.getInstance();
        AdapterGroupVO adptGrpVO = adapterManager.getAdapterGroupVO(adapterGroupName);
        String adptGrpName = adptGrpVO.getName();

        if (StringUtils.equals(adptGrpVO.getType(), Keys.TYPE_HTTP_CUSTOM)
                || StringUtils.equals(adptGrpVO.getType(), Keys.TYPE_REST)) {
            try {
                String requestMethod = prop
                        .getProperty(HttpAdapterServiceRest.PROPERTIES_NAME_HTTP_REQUEST_METHOD);

                // /api/v1/public/getUserInfo.svc
                String inboundUri = prop.getProperty(HttpAdapterServiceKey.INBOUND_EXTURI);
                String apiPath = prop.getProperty(HttpAdapterServiceKey.API_PATH);

                // /getUserInfo.svc
                String apiUri = org.apache.commons.lang.StringUtils.removeStart(inboundUri, apiPath);

                Set<String> allKeys = new HashSet<>(Arrays.asList(
                        STDMessageManager.getInstance().getAllSTDMessageKeys()));

                // 전체 URI부터 시작해서 뒤 경로를 하나씩 제거하며 일치하는 키를 탐색
                String searchUri = apiUri;
                for (int i = 0; i < 10; i++) {
                    String candidateKey = adptGrpName + ":" + requestMethod + "|"
                            + StringUtils.removeStart(searchUri, "/");
                    if (allKeys.contains(candidateKey)) {
                        return new String[] { candidateKey };
                    }
                    String shortened = StringUtils.substringBeforeLast(searchUri, "/");
                    if (StringUtils.isBlank(shortened)) {
                        break;
                    }
                    searchUri = shortened;
                }

                // 일치하는 키가 없으면 원래 키로 fallback
                String apiKey = adptGrpName + ":" + requestMethod + "|"
                        + StringUtils.removeStart(apiUri, "/");
                return new String[] { apiKey };

            } catch (Exception e) {
                throw new ActionException(ExceptionUtil.getErrorCode(e, "RECEAIIRA001"));
            }
        }

        if (message instanceof byte[]) {
            try {
                key = MessageKeyExtractor.getMessageKeyValueForRest(this.adapterGroupName, message, prop, "url", true);
            } catch (Exception e) {
                throw new ActionException(ExceptionUtil.getErrorCode(e, "RECEAIIRA001"));
            }
            if (logger.isDebug())
                logger.debug(adapterName + "] received data >> [" + new String((byte[]) message) + "]");
        } else {
            try {
                key = MessageKeyExtractor.getMessageKeyValueForRest(this.adapterGroupName, message, prop, "url", true);
            } catch (Exception e) {
                throw new ActionException(ExceptionUtil.getErrorCode(e, "RECEAIIRA001"));
            }
            if (logger.isDebug())
                logger.debug(adapterName + "] received data >> [" + message + "]");
        }

        for (int i = 0; i < key.length; i++) {
            key[i] = adptGrpName.trim() + key[i];
        }

        return key;
    }
}
