package nlib.restful.service;

import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import nlib.util.StringUtil;

/**
 * <pre>
 * @Class Name : DataApiInterface.java
 * 
 * @Description : DAO에서 상속할 DataApi의 부모 클래스들을 위한 인터페이스 
 * 
 * 
 * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
 *
 * </pre>
 *
 * @ ------------    --------    ---------------------------
 * @ 수정일                           수정자                  수정내용
 * @ ------------    --------    ---------------------------
 * @ 2021. 7. 9.     KNKIM       최초 생성
 *
 * 
 * @author 이씨플라자 * DIGITALSHIP KNKIM
 * @since 2021. 7. 9.
 * @version 1.0
 *
 */
public interface DataApiInterface {

	static final Logger log = LoggerFactory.getLogger(DataApiInterface.class);
	
	/**
	 * 조회 
	 * 
	 * @param reqVO
	 * @return
	 */
	public DataApiResVO get(DataApiReqVO reqVO);
	
	/**
	 * 등록 
	 * 
	 * @param reqVO
	 * @return
	 */
	public DataApiResVO put(DataApiReqVO reqVO);
	
	/**
	 * 수정 
	 * 
	 * @param reqVO
	 * @return
	 */
	public DataApiResVO post(DataApiReqVO reqVO);

	/**
	 * 삭제 
	 * 
	 * @param reqVO
	 * @return
	 */
	public DataApiResVO delete (DataApiReqVO reqVO);

	/**
	 * 실제 RESTful API 서버로 요청을 전송하고, 응답받은 자료를 응답VO에 담아서 리턴한다.
	 * 
	 * @param reqVO
	 * @param method
	 * @return
	 */
	public DataApiResVO send(DataApiReqVO reqVO, HttpMethod method);


    /**
     * 요청 VO를 Map 형태로 변환한다.
     * 
     * @param reqVO
     * @return
     */
    public static MultiValueMap<String, String> makeParamMap(DataApiReqVO reqVO) {
    	
    	MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
    	
		// 공통 
		map.add("authKey",	 reqVO.getAuthKey());
		map.add("rows",	 "" + reqVO.getPageSize());
		map.add("page",	 "" + reqVO.getPageIndex());
		
		// 추가 정보 
		if(reqVO.hasInfo()) {
			HashMap<String, Object> info = reqVO.getInfo();
			for(String key : info.keySet()) {
				Object val = info.get(key);
				if(val instanceof HashMap) {
					HashMap<String, String> subInfo = (HashMap)val;
	    			for(String subKey : subInfo.keySet()) {
	    				String subVal = subInfo.get(subKey);
	    				map.add(subKey, subVal);
	    			}
				} else {
					map.add(key, (String)val);
				}
			}
		}
		
		// 요청 파라메타 확인 
		for(String key : map.keySet()) {
			log.debug("MultiValueMap > " + key + "=" + map.get(key));
		}
		
		return map;
    }
    
	
    /**
     * 요청전 공통 입력 파라메터를 확인한다.
     * 
     * @param reqVO
     * @return
     * @throws Exception
     */
    public static DataApiResVO checkReqCommonParams(DataApiReqVO reqVO) throws Exception {
    	
    	if(reqVO == null) {
    		return new DataApiResVO("ERR_NO_REQ", "데이터송수신 요청객체가 존재하지 않습니다.");
    	}
    	
    	if(StringUtil.isEmpty(reqVO.getReqUrl())) {
    		return new DataApiResVO("ERR_NO_RURL", "데이터 요청 업무ID에 대한 URL/RUI 정보가 존재하지 않습니다.");
    	}
    	if(StringUtil.isEmpty(reqVO.getAuthKey())) {
    		return new DataApiResVO("ERR_NO_AUTHKEY", "데이터 요청에 대한 권한키 정보가 존재하지 않습니다.");
    	}
    	
    	return null;
    }
    
    /**
     * 처리결과 정보를 입력받아 DataApiResVO를 생성한다.
     * 
     * @param resultCode
     * @param resultMessage
     * @return
     */
    public static DataApiResVO makeErrorRes(String resultCode, String resultMessage) {
    	return new DataApiResVO(resultCode, resultMessage);
    }
    
    /**
     * 응답받은 XML 문자열을 DataApiResVO (내부 Map객체 포함) 객체로 변환하여 리턴한다. 
     * 
     * @param xmlStr
     * @return
     */
    public static DataApiResVO convertXmlToResVO(String xmlStr) {
    	
    	DataApiResVO resVO = new DataApiResVO();
        Map<String, Object> map = null;
        
        try {
        	map = XmlConverter.convert(xmlStr);
        } catch(Exception e) {
        	e.printStackTrace();
        	
        	resVO.setResultCode("ERR_RES_XML_FORMAT");
        	resVO.setResultMessage(String.format("올바르지 않은 XML 형식의 응답입니다. : [%s]", xmlStr));
        	
        	return resVO;
        }
    	
    	// 처리결과 확인 
    	String commonKeyList = "|resulttype|code|message|page|totpages|records|".toLowerCase();
    	String lowerKey = null;
    	for( String key : map.keySet()) {
    		
    		lowerKey = key.toLowerCase();
    		if(commonKeyList.contains("|" + lowerKey + "|")) {
    			
    			if(lowerKey.equals("resulttype")) {
    	    		String resultType = (String)map.get(key);
    	    		if(!StringUtil.isEmpty(resultType) && resultType.toLowerCase().compareTo("success") == 0) {
    	    			resVO.setResultCode("S0000");
    	    		}
    	    	}
    	    	
    	    	if(lowerKey.equals("code")) {
    	    		String code = (String)map.get(key);
    	    		int codeInt = 0;
    	    		try {
    	    			codeInt = Integer.parseInt(code);

        	    		if(codeInt != 0) {
        	    			resVO.setResultCode(String.format("ERR_BIZERR(%s)", code));
        	    		} else {
        	    			resVO.setResultCode("S0000");
        	    		}
    	    		} catch(Exception e) {
    	    			if(StringUtil.isNotEmpty(code) && code.startsWith("S")) {
    	    				codeInt = 0;
    	    				resVO.setResultCode("S0000");
    	    			} else {
    	    				resVO.setResultCode(String.format("ERR_BIZERR(%s)", code));
        	    			log.error("회신 code 정보를 정수로 변환처리 중 오류가 발생하였습니다." + e.toString());
        	    			codeInt = -1;
        	    			e.printStackTrace();
    	    			}
    	    		}
    	    	}
    	    	
    	    	if(lowerKey.equals("message")) {
    	    		resVO.setResultMessage((String)map.get(key));
    	    	}

    	    	if(lowerKey.equals("page")) {
    	    		resVO.setPageIndex(StringUtil.toNumber((String)map.get(key)));
    	    	}
    	    	
    	    	if(lowerKey.equals("totpages")) {
    	    		resVO.setPageLastIndex(StringUtil.toNumber((String)map.get(key)));
    	    	}

    	    	if(lowerKey.equals("records")) { 
    	    		resVO.setRecordTotCount(StringUtil.toNumber((String)map.get(key), 0));
    	    	}
    		} else {
    			if(resVO.getInfo() == null) resVO.setInfo(new HashMap<String,Object>());
    			HashMap<String,Object> info = resVO.getInfo();
    			info.put(key, map.get(key));
    		}
    	}
    	
    	return resVO;
    }
}
