package nlib.restful.service.impl;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.util.MultiValueMap;

import com.fasterxml.jackson.dataformat.xml.XmlMapper;

import nlib.restful.service.DataApiInterface;
import nlib.restful.service.DataApiReqVO;
import nlib.restful.service.DataApiResVO;
import nlib.restful.service.DataApiServerResponseVO;
import nlib.restful.service.DataApiVO;
import nlib.util.StringUtil;

/**
 * <pre>
 * @Class Name : DataApiTempXml.java
 * 
 * @Description : DataAPI의 요청에 대해서 로컬의 테스트용 XML 파일을 읽어서 응답을 처리한다. (자체 선개발 진행용) 
 * 
 * 
 * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
 *
 * </pre>
 *
 * @ ------------    --------    ---------------------------
 * @ 수정일                     수정자             수정내용
 * @ ------------    --------    ---------------------------
 * @ 2021. 7. 9.     KNKIM       최초 생성
 *
 * 
 * @author 이씨플라자 * DIGITALSHIP KNKIM
 * @since 2021. 7. 9.
 * @version 1.0
 *
 */
public class DataApiTempXml implements DataApiInterface {

	private static final Logger log = LoggerFactory.getLogger(DataApiTempXml.class);
	
	/* DataApi 접속 서버 정보 */ 
	@Value("#{properties['dataapi.temp.xml.path']}") 
	private String DAPI_TEMP_XML_PATH;
	

	/**
	 * 실제 RESTful API 서버로 요청을 전송하고, 응답받은 자료를 응답VO에 담아서 리턴한다.
	 * 
	 * @param reqVO
	 * @param method
	 * @return
	 */
	public DataApiResVO request(DataApiReqVO reqVO) {
		
		log.debug("request > " + reqVO.getReqMethod());
		
    	DataApiResVO resVO = null;
    	
    	try {
        	//-----------------------------------
    		// 입력값 검증작업 
        	//-----------------------------------
    		resVO = DataApiInterface.checkReqCommonParams(reqVO);
        	if(resVO != null) return resVO;
        	HttpMethod method = reqVO.getReqMethod();

        	//-----------------------------------
        	// 폼 파라메터 생성 작업 (요청데이터 확인용)
        	//-----------------------------------
    		HttpHeaders headers = new HttpHeaders();
    		headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
    		MultiValueMap<String, String> parameters = DataApiInterface.makeRequestParamMultiValueMap(reqVO); 
    		
        	//-----------------------------------
        	// 응답 처리  
        	//-----------------------------------
    	    HttpStatus statusCode = HttpStatus.OK; 
    	    String resultXML = getTempDataFromXmlFile(reqVO);
    	    //log.debug("RES resultXML : " + resultXML);
    	    
    	    // 응답 자료 객체화 
    		resVO = DataApiInterface.convertXmlToResVO(resultXML);
    		
    		// 처리결과 코드 확인 
    		if(StringUtil.isEmpty(resVO.getResultCode())) {
    			String resultMessage = resVO.getResultMessage();
        	    if (statusCode == HttpStatus.OK) {
        	    	resVO.setResultCode("S_HTTP_STATUS_OK");
        	    	resVO.setResultMessage(StringUtil.isEmpty(resultMessage) ? "정상처리되었습니다." : resultMessage);
        	    } else {
        	    	resVO.setResultCode("E_STATUS_CODE_FAIL");
        	    	resVO.setResultMessage(StringUtil.isEmpty(resultMessage) ? String.format("처리에 실패하였습니다. (HTTP상태코드 : %s)", statusCode.toString()) : resultMessage);
        	    }
    		}
    		
    		log.debug("RES resVO : resultCode    = " + resVO.getResultCode());
    		log.debug("RES resVO : resultMessage = " + resVO.getResultMessage());
    		
    	} catch(Exception e) {
    		e.printStackTrace();
    		return DataApiInterface.makeErrorRes("E_REQ_EXCEPTION", e.toString());
    	}
    	
	    return resVO;	
	}
	
	/**
	 * 요청 URI와 메소드를 기반으로 임시 응답 XML 파일을 찾아서 내용을 문자열로 리턴한다. 
	 * 
	 * @param reqVO
	 * @param method
	 * @return
	 * @throws Exception
	 */
	private String getTempDataFromXmlFile(DataApiReqVO reqVO) throws Exception {
	
		HttpMethod method = reqVO.getReqMethod();
		String fileName = reqVO.getReqUrl().substring(1).replaceAll("/", ".");
		String xmlPath = DAPI_TEMP_XML_PATH + "/" + fileName + "_" + method.toString().toUpperCase() + ".xml";
		String returnXmlStr = null;
		
		log.info("XML FILE PATH : " + xmlPath);
		
		
		DataApiServerResponseVO resVO = null;
		
		File xmlFile = new File(xmlPath);
		if(!xmlFile.exists()) {
			resVO = new DataApiServerResponseVO("-20", String.format("%s 파일을 찾을 수 없습니다.",xmlPath));
			XmlMapper mapper = new XmlMapper();
			returnXmlStr = mapper.writer().withRootName("result").writeValueAsString(resVO);
		}
		
		if(resVO == null && !xmlFile.isFile()) {
			resVO = new DataApiServerResponseVO("-21", String.format("%s는 파일이어야 합니다.",xmlPath));
			XmlMapper mapper = new XmlMapper();
			returnXmlStr = mapper.writer().withRootName(DataApiVO.XML_EL_NAME_ROOT_NAME).writeValueAsString(resVO);
		}
		
		if(resVO == null) {
			StringBuilder strBd = new StringBuilder();
			
			try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(xmlPath),StandardCharsets.UTF_8))) {
				
			    String line;
			    int i = 0;
			    while ((line = br.readLine()) != null) {
			    	strBd.append(line + "\n");
			    }
			    returnXmlStr = strBd.toString();
			} catch (IOException e) {
				log.error("XML 파일 읽는 중 오류 발생 : " + e.toString());
				e.printStackTrace();
				
				resVO = new DataApiServerResponseVO("-22", String.format("%s 파일을 읽는 중 오류가 발생하였습니다(%s). ",xmlPath, e.toString()));
				XmlMapper mapper = new XmlMapper();
				returnXmlStr = mapper.writer().withRootName(DataApiVO.XML_EL_NAME_ROOT_NAME).writeValueAsString(resVO);
			}
			
		}
		
		//log.info("RESUTN XML STR : " + returnXmlStr);
		return returnXmlStr;
	}

}
