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

import java.util.Properties;

import org.apache.commons.lang3.StringUtils;

import com.eactive.eai.common.inflow.Bucket;
import com.eactive.eai.common.inflow.InflowTargetVO;
import com.eactive.eai.common.inflow.dual.DualBucket;
import com.eactive.eai.common.inflow.dual.DualCustomBucket;
import com.eactive.eai.common.message.EAIMessage;
import com.eactive.eai.custom.inflow.ClientDualBucket;
import com.eactive.eai.inbound.processor.RequestProcessor;

/**
 * 어댑터/인터페이스/클라이언트 유량제어 차단 시 어느 버킷(PER_SECOND/THRESHOLD)에서
 * 차단됐는지 에러 메시지에 포함하는 RequestProcessor 확장.
 *
 * <p>ClientDualInflowControlManager와 함께 사용:
 * <pre>
 * inflow.control.bucket.className=com.eactive.eai.common.inflow.dual.ClientDualInflowControlManager
 * </pre>
 *
 * <p>Spring Bean 등록 후 기존 RequestProcessor 대신 이 클래스를 어댑터에 설정한다.
 */
public class DJBRequestProcessor extends RequestProcessor {

    @Override
    protected String checkCustomInflow(Bucket bucket, EAIMessage eaiMsg, Properties prop) {
        String clientId = eaiMsg.getClientId();
        if (StringUtils.isBlank(clientId)) return null;
        if (bucket instanceof ClientDualBucket) {
            return ((ClientDualBucket) bucket).isClientPassDetail(clientId);
        }
        return null;
    }

    @Override
    protected InflowTargetVO resolveCustomInflowThreshold(Bucket bucket, EAIMessage eaiMsg, Properties prop) {
        if (bucket instanceof ClientDualBucket) {
            return ((ClientDualBucket) bucket).getClientInflowThreshold(eaiMsg.getClientId());
        }
        return null;
    }

    @Override
    protected String checkAdapterInflow(Bucket bucket, String adapterGroupName) {
        if (bucket instanceof DualBucket) {
            return ((DualBucket) bucket).isAdapterPassDetail(adapterGroupName);
        }
        return super.checkAdapterInflow(bucket, adapterGroupName);
    }

    @Override
    protected String checkInterfaceInflow(Bucket bucket, String eaiSvcCd) {
        if (bucket instanceof DualBucket) {
            return ((DualBucket) bucket).isInterfacePassDetail(eaiSvcCd);
        }
        return super.checkInterfaceInflow(bucket, eaiSvcCd);
    }

    /**
     * 차단 원인에 따라 에러 메시지에 한도 정보를 포함.
     * <ul>
     *   <li>PER_SECOND: "API 호출 한도 초과 [name: Nreq/sec]"</li>
     *   <li>THRESHOLD:  "API 호출 한도 초과 [name: Nreq/UNIT]"</li>
     *   <li>그 외:      "API 호출 한도 초과 [name]" (기존 동작)</li>
     * </ul>
     */
    @Override
    protected String buildInflowTargetErrorMsg(InflowTargetVO inflowTargetVO, String blockedType) {
        if (DualCustomBucket.RESULT_BLOCKED_PER_SECOND.equals(blockedType)) {
            return String.format("API 호출 한도 초과 [%s: %dreq/sec]",
                    inflowTargetVO.getName(),
                    inflowTargetVO.getThresholdPerSecond());
        }
        if (DualCustomBucket.RESULT_BLOCKED_THRESHOLD.equals(blockedType)) {
            return String.format("API 호출 한도 초과 [%s: %dreq/%s]",
                    inflowTargetVO.getName(),
                    inflowTargetVO.getThreshold(),
                    inflowTargetVO.getThresholdTimeUnit());
        }
        return super.buildInflowTargetErrorMsg(inflowTargetVO, blockedType);
    }
}
