package kr.co.i4way.cst.controller;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.web.client.RestTemplate;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.HttpStatusCodeException;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import kr.co.i4way.util.JsonUtil;
import kr.co.i4way.cst.model.RecLicenseVo;
import kr.co.i4way.cst.service.CstScheduleService;
import kr.co.i4way.util.HttpUtil;
import net.minidev.json.JSONArray;

/**
 * Skill용 Controller
 * @author jkhong
 *
 */
@Controller
public class CstScheduleController {
	
	@Value("${ccc-service.enc-iv}")
    private String enc_iv;
	
	@Value("${ccc-service.enc-key}")
    private String enc_key;
	
	@Value("${ccc-service.user-service-url}")
    private String user_service_url;
	
	@Value("${ccc-service.org-service-url}")
    private String org_service_url;

	@Value("${rec-service.license-url}")
	private String rec_license_url;
	
	@Value("${boardinfo.server_type}")
	private String server_type;
	
	private final Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName());
	@Autowired(required=true)
	private CstScheduleService service; 
	
	/**
	 * 상담사 정보 적재
	 * 공통의 상담사 정보를 Select해서 MSSQL에 Insert
	 */
	@Scheduled(cron="${ccc-service.cron.user-service}")
	public void AgentInfo(){
		// rest template 선언
		RestTemplate restTemplate = new RestTemplate();
		int insert_count = 0;
			
		// 전송 parameter 정의
		Map<String, Object> mapParam = new HashMap<String, Object>();
	        
		// 수정일시 전달
		mapParam.put("changeDatetime", getToday());
	        
		HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(mapParam);		
		try {
			// 서버에서 데이터를 수신한다.
			ResponseEntity<Map> response = restTemplate.exchange (user_service_url + getToday(), HttpMethod.GET, requestEntity, Map.class);
	        	
			Map output = response.getBody();
			List<Map<String, Object>> data = (List) output.get("result");

			// 정상의 경우 처리 ... 
			logger.info("read Agent Count => " + data.size());
			
			List<Map<String, Object>> tmpData = new ArrayList<Map<String, Object>>();
			
			for(int i=0; i < data.size(); i++ ) {
				tmpData.add(insert_count, data.get(i));
		    	if(insert_count > 80 || data.size() == i+1) {
		    		service.insertCCCUser(tmpData);
		    		insert_count = 0;
		    		tmpData.clear();
		    	}else {
		    		insert_count++;
		    	}
			}
	        	
		}catch(HttpStatusCodeException e) {
	        	
			// validation exception이 발생한 경우 처리
			if( e.getStatusCode() == HttpStatus.UNPROCESSABLE_ENTITY) {
				// 오류발생 시 처리
				try {
	        			
					// output으로 전달된 결과는 json으로 치환가능
					JSONObject jsonMessage = new JSONObject(e.getResponseBodyAsString());
	        			
					logger.info( jsonMessage.toString() ); // VALIDATION
					logger.info( jsonMessage.getString("type") ); // VALIDATION
					logger.info( jsonMessage.getString("code") ); // -1
					logger.info( jsonMessage.getString("message") ); // exception message
					logger.info( jsonMessage.getString("trace") ); // null  {optional}
					logger.info( jsonMessage.getString("error") ); // false {optional}
	        			
				} catch (JSONException e1) {
					throw new RuntimeException (e);
				}
			} 
			// 일반 오류가 발생한 경우 처리
			else {
				e.printStackTrace();
				throw new RuntimeException (e);
			}
	    		
		}catch(Exception e) {
			e.printStackTrace();
			throw new RuntimeException (e);
		}
	}
	
	/**
	 * 조직 정보 적재
	 * 공통의 조직 정보를 Select해서 MSSQL에 Insert
	 */
	@Scheduled(cron="${ccc-service.cron.org-service}")
	public void OrgInfo(){
		// rest template 선언
		RestTemplate restTemplate = new RestTemplate();
		int insert_count = 0;
		
		// 전송 parameter 정의
		Map<String, Object> mapParam = new HashMap<String, Object>();
	        
		// 수정일시 전달
		mapParam.put("changeDatetime", getToday());
	        
		HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(mapParam);		
		try {
			// 서버에서 데이터를 수신한다.
			//ResponseEntity<Map> response = restTemplate.exchange (org_service_url + getToday(), HttpMethod.GET, requestEntity, Map.class);
			ResponseEntity<Map> response = restTemplate.exchange (org_service_url, HttpMethod.GET, requestEntity, Map.class);
	        	
			Map output = response.getBody();
			List<Map<String, Object>> data = (List) output.get("result");

			// 정상의 경우 처리 ... 
			logger.info("read Org Count => " + data.size());
			
			List<Map<String, Object>> tmpData = new ArrayList<Map<String, Object>>();
			
			for(int i=0; i < data.size(); i++ ) {
				tmpData.add(insert_count, data.get(i));
		    	if(insert_count > 80 || data.size() == i+1) {
					service.insertCCCGroup(data);
		    		insert_count = 0;
		    		tmpData.clear();
		    	}else {
		    		insert_count++;
		    	}
			}
			
	        	
		}catch(HttpStatusCodeException e) {
	        	
			// validation exception이 발생한 경우 처리
			if( e.getStatusCode() == HttpStatus.UNPROCESSABLE_ENTITY) {
				// 오류발생 시 처리
				try {
	        			
					// output으로 전달된 결과는 json으로 치환가능
					JSONObject jsonMessage = new JSONObject(e.getResponseBodyAsString());
	        			
					logger.info( jsonMessage.toString() ); // VALIDATION
					logger.info( jsonMessage.getString("type") ); // VALIDATION
					logger.info( jsonMessage.getString("code") ); // -1
					logger.info( jsonMessage.getString("message") ); // exception message
					logger.info( jsonMessage.getString("trace") ); // null  {optional}
					logger.info( jsonMessage.getString("error") ); // false {optional}
	        			
				} catch (JSONException e1) {
					throw new RuntimeException (e);
				}
			} 
			// 일반 오류가 발생한 경우 처리
			else {
				e.printStackTrace();
				throw new RuntimeException (e);
			}
	    		
		}catch(Exception e) {
			e.printStackTrace();
			throw new RuntimeException (e);
		}
	}
	
//    @Scheduled(cron="${genesysinfo.cron.license-service}")
//    //@Scheduled(cron="0 * * * * *")
//    public void genesysLicenseCount(){
//    	RecLicenseVo vo = new RecLicenseVo();
//    	
//    	try {
//    		ArrayList dncnt = null;
//    		if(server_type.equals("prod")) {
//    			dncnt = service.getDnCnt();
//    		}else {
//    			dncnt = service.getDnCnt_Dev();
//    		}
//    		if(dncnt != null) {
//    			HashMap<String,Integer> map1 = (HashMap<String,Integer>) dncnt.get(0); 
//    			vo.setUsed_cnt(map1.get("CNT_DN"));
//    		}
//    		if(vo.getUsed_cnt() > 0) {
//    			vo.setLicense_cnt(vo.getUsed_cnt() + (int)(vo.getUsed_cnt() * 0.1));
//    		}
//    		vo.setSolution_type("CTI");
//    		vo.setServer_id("1");
//    		
//			service.setGenesysLicenseInfo(vo);
//			logger.info("genesysLicenseCount Success");
//		} catch (Exception e) {
//			logger.error("error : ", e);
//		}
//    }
    
    public static JsonObject convertMapToJson(Map<String, Object> map) {
        
    	JsonObject json = new JsonObject();
        String key = "";
        Object value = null;
        for(Map.Entry<String, Object> entry : map.entrySet()) {
            key = entry.getKey();
            value = entry.getValue();
           	json.add(key, (JsonElement) value);
        }
        return json;
    }

    public static Map<String, Object> getMapFromJsonObject(JsonObject jsonObj){
        Map<String, Object> map = null;
        
        try {
           map = new ObjectMapper().readValue(jsonObj.toString(), Map.class);
        } catch (JsonParseException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return map;
    }
    
    private String getParam(Map<String, Object> param, String qryStr, String type){
		String rtnstr = "";
		if(type.equals("I")){
			rtnstr = "0";
		}
		try{
			rtnstr = param.get(qryStr).toString();
		}catch(Exception e){ 
			logger.error("error : ", e);
		}
		return rtnstr;
	}

//    @Scheduled(cron="${rec-service.cron.license-service}")
//    //@Scheduled(cron="30 0,10,20,30,40,50 * * * *")
//    public void recLicenseCount(){
//    	RecLicenseVo vo = new RecLicenseVo();
//    	JsonParser jparser = new JsonParser();
//    	List<RecLicenseVo> licenseList = new ArrayList<RecLicenseVo>();
//    	JsonObject rtnobj = null;
//    	logger.info("recLicenseCount Start");
//    	try {
//	    	rtnobj = HttpUtil.callApi_type_normal(rec_license_url,"GET");    //녹취 라이선스 사용 현황 조회
//	    	net.minidev.json.JSONObject param = JsonUtil.decrypt_param2(getMapFromJsonObject(rtnobj), enc_key, enc_iv, "Yes");  	
//	    	logger.info("param=" + param.toJSONString());
//			//JsonElement server_list = jparser.parse(getParam(param, "license_list", "S"));
//	    	JSONArray arr = (JSONArray) param.get("license_list");
//	    	
//	    	for (Object server : arr) {
//	    		net.minidev.json.JSONObject JsonObject = (net.minidev.json.JSONObject)server;
//	    		vo.setSolution_type("REC");
//	    		vo.setServer_id("1");
//	    		vo.setServer_type("REC");
//	    		vo.setServer_type_name("레코더");
//	    		vo.setLicense_cnt((int)JsonObject.getAsNumber("license_cnt"));
//	    		vo.setUsed_cnt((int)JsonObject.getAsNumber("used_cnt"));
//	    		licenseList.add(vo);
//			}
//	    	if(licenseList.size() > 0) {
//					service.setRecLicenseInfo(licenseList);
//	    	}
//	    	logger.info("recLicenseCount Success");
//		} catch (Exception e) {
//			logger.error("error : ", e);
//		}
//    }
    
    private String getToday() {
    	
		Date nowDate = new Date();
        
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd"); 
		String strNowDate = simpleDateFormat.format(nowDate); 
		return strNowDate;
	}
}
