package com.eactive.eai.custom.adapter.http.dynamic.filter;

import java.util.Properties;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.http.HttpStatus;

import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceKey;
import com.eactive.eai.adapter.http.dynamic.filter.FilterCryptoException;
import com.eactive.eai.adapter.http.dynamic.filter.HttpAdapterFilter;
import com.eactive.eai.adapter.http.dynamic.filter.InCryptoFilter;
import com.eactive.eai.adapter.service.DJBApiAdapterService;
import com.eactive.eai.common.util.JacksonUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

/**
 * 더존 연동용 수신 암복호화 필터.
 *
 * {@code HttpAdapterServiceKey.INBOUND_HEADER} 프로퍼티로 전달된 수신 헤더 Map에서
 * 두 가지 컨텍스트 값을 추출하여 {@link InCryptoFilter}에 위임한다.
 *
 *   x-emp-nm  : GCM AAD 값 ({@code CRYPTO_AAD_HEADER} 프로퍼티에 설정)
 *   x-chnl-nm : DYNAMIC 키 도출 컨텍스트 ({@code contextKey} 프로퍼티에 설정)
 *               → {@code HsmContextSha256KeyDerivationStrategy}가 채널명 기반으로 키를 동적 생성
 *
 * 암복호화 필드 경로: {@code /encryptedData}
 *
 * 필터 타입 등록 (FQCN):
 *   com.eactive.eai.custom.adapter.http.dynamic.filter.DouzoneEncFieldInCryptoFilter
 */
public class DouzoneEncFieldInCryptoFilter implements HttpAdapterFilter {

	private final InCryptoFilter filter = new InCryptoFilter();

	protected Properties setProp(Properties p) {
		p.setProperty(InCryptoFilter.PROP_DEC_FROM_PATH, "/encryptedData");
		p.setProperty(InCryptoFilter.PROP_ENC_TO_PATH, "/encryptedData");
		return p;
	}

	private void setContext(Properties tempProp) {
		Properties inboundHeaders = (Properties) tempProp.get(HttpAdapterServiceKey.INBOUND_HEADER);
		String chnlNm = inboundHeaders.getProperty("x-chnl-nm");
		tempProp.setProperty("x-chnl-nm", chnlNm);

		tempProp.setProperty(InCryptoFilter.PROP_AAD_HEADER, "x-emp-nm");
	}

	@Override
	public Object doPreFilter(String adptGrpName, String adptName, Object message, Properties prop,
			HttpServletRequest request, HttpServletResponse response) throws Exception {
		try {
			setContext(prop);
			return filter.doPreFilter(adptGrpName, adptName, message, setProp(prop), request, response);
		} catch (Exception e) {
			throw new FilterCryptoException("복호화 오류", InCryptoFilter.ERROR_DEC_FAIL, HttpStatus.INTERNAL_SERVER_ERROR.value(), e);
		}
	}

	@Override
	public Object doPostFilter(String adptGrpName, String adptName, Object resultMessage, Properties prop,
			HttpServletRequest request, HttpServletResponse response) throws Exception {
		try {
			setContext(prop);
			
			JsonNode root = JacksonUtil.readTree(resultMessage);
			ObjectNode rootObjectNode = (ObjectNode) root;
			String headerGroupName = prop.getProperty(DJBApiAdapterService.HEADER_GROUP);
			JsonNode header = null;
			if(headerGroupName != null) {
				header = rootObjectNode.get(headerGroupName);
				rootObjectNode.remove(headerGroupName);
			}
			
			Object enc = filter.doPostFilter(adptGrpName, adptName, rootObjectNode, setProp(prop), request, response);
			ObjectNode encJson = (ObjectNode)JacksonUtil.readTree(enc);
			if(header != null)
				encJson.set(headerGroupName, header);
			
			return encJson;
			
		} catch (Exception e) {
			throw new FilterCryptoException("암호화 오류", InCryptoFilter.ERROR_ENC_FAIL, HttpStatus.INTERNAL_SERVER_ERROR.value(), e);
		}
	}
	
}
