package com.madeu.batch;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.madeu.dao.web.webpublicholiday.WebPublicHolidaySqlMapDAO;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class InsertPublicHolidayBatchExcute {
	
	@Autowired 
	private WebPublicHolidaySqlMapDAO webPublicHolidaySqlMapDAO;
	
	// 21~22년 (공공 api 조회 가능 연도가 내년꺼까지만 가능.) https://www.data.go.kr/dataset/15012690/openapi.do
	@Scheduled(cron = "0 0 03 1 * ?") // 매월 1일 03:00
//	@Scheduled(cron = "0 0/1 * * * ?")
	public void go() {
		log.debug("InsertPublicHolidayBatchExcute - run start");

		List<HashMap<String, Object>> publicHolidayList = new ArrayList<HashMap<String, Object>>();
		
		Calendar c = Calendar.getInstance();
		int year = c.get(Calendar.YEAR);
		
		for (int i = year; i <= year+1; i++) {
			// 공휴일을 가져온다
			for(int j=1; j<=12; j++) {
				int month = j;
				
				if(i==year) {
					month = c.get(Calendar.MONTH)+j;
				}
				
				if(12 < month) {
					
				}else {
					String yearString = String.valueOf(i);
					String monthString = String.valueOf(month);
					
					if(10 > month) {
						//한자리수일시 01, 02같이 0을 필요로함, request param이 2자리수
						monthString = "0" + monthString;
					}
					
					List<HashMap<String, Object>> listTemp = getPublicHolidayMap(yearString,  monthString);
					log.debug(yearString+"년 "+monthString+"월 결과 : " + listTemp);
					
					publicHolidayList.addAll(listTemp);
				}
			}
			log.debug(i + "년의 totalPublicHolidayCount : " + publicHolidayList.size());
			//logger.debug("publicHolidayList : " + publicHolidayList);
		}
		
		int insertedCount = 0;
		
		for(int i=0; i<publicHolidayList.size(); i++) {
			HashMap<String, Object> publicHolidayParamMap = publicHolidayList.get(i);
			StringBuffer sbTemp = new StringBuffer(String.valueOf(publicHolidayParamMap.get("locdate")));
			sbTemp.insert(6, "-");
			sbTemp.insert(4, "-");
			
			String dateName = publicHolidayParamMap.get("dateName").toString().replaceAll(" ", "");
			publicHolidayParamMap.put("dateName", dateName);
			publicHolidayParamMap.put("locDate", sbTemp.toString());
			
			List<Map<String, Object>> listMapTemp = webPublicHolidaySqlMapDAO.selectListPublicHolidayDate(publicHolidayParamMap);
			
			// 존재하는 공휴일일 경우
			if(1 <= listMapTemp.size()) {
				
			}
			else{
				String muPublicHolidayId = ("PH").concat(String.valueOf(System.currentTimeMillis()));
				publicHolidayParamMap.put("muPublicHolidayId", muPublicHolidayId);
				publicHolidayParamMap.put("regId", "BATCH_SYSTEM");
				publicHolidayParamMap.put("modId", "BATCH_SYSTEM");
				publicHolidayParamMap.put("useYn", "Y");
				webPublicHolidaySqlMapDAO.insertPublicHoliday(publicHolidayParamMap);
				insertedCount++;
			}
		}
		
		log.debug("InsertPublicHolidayBatchExcute - " + insertedCount + " record inserted");
		
		log.debug("InsertPublicHolidayBatchExcute - run end");
	}
	
	// 해당 년/월의 공휴일을 가져오는 메서드
	public List<HashMap<String, Object>> getPublicHolidayMap(String year, String month) {
		List<HashMap<String, Object>> holidayList = new ArrayList<HashMap<String, Object>>(); 
		
		log.debug("InsertPublicHolidayBatchExcute getPublicHolidayMap START");
		
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setNamespaceAware(true);
		DocumentBuilder builder;
		Document doc = null;
		
		String addr       = "http://apis.data.go.kr/B090041/openapi/service/SpcdeInfoService";
		String query      = "/getRestDeInfo?";
			
		StringBuffer stringBuffer = new StringBuffer();
		stringBuffer.append(addr);
		stringBuffer.append(query);
		stringBuffer.append("ServiceKey=" + "IMP1dVPnFLL2UYlH8yyENSeLeS5UMLYxnaomTs5L2IHp8qnyd%2FzApTGcCUV9%2FD76wZQzD24HegGoNFotIoh9GA%3D%3D");
		stringBuffer.append("&solYear=" + year);
		stringBuffer.append("&solMonth=" + month);
		
		log.debug("stringBuffer.toString() "+ stringBuffer.toString());
		
		try {
			URL url = new URL(stringBuffer.toString());
			
			URLConnection conn = url.openConnection();
			
			BufferedReader rd = null;
			
			rd = new BufferedReader(new InputStreamReader(conn.getInputStream(),"UTF-8"));
			StringBuffer result = new StringBuffer();
			
			String line;
			
			while((line=rd.readLine())!=null){
				result.append(line.trim());
			}
			
			// xml 리절트 출력부분
			/*if(0<result.toString().length()){
				logger.debug("result    :"+result.toString());
			}*/
			
			rd.close();
			
			InputSource is = new InputSource(new StringReader(result.toString()));
			builder = factory.newDocumentBuilder();
			doc = builder.parse(is);
			XPathFactory xpathFactory = XPathFactory.newInstance();
			XPath xpath = xpathFactory.newXPath();
			XPathExpression expr = xpath.compile("//items/item");
			NodeList nodeList = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
			for (int i = 0; i < nodeList.getLength(); i++) {
				NodeList child = nodeList.item(i).getChildNodes();
				HashMap<String, Object> holidayMapTemp = new HashMap<String, Object>();
				for (int j = 0; j < child.getLength(); j++) {
					Node node = child.item(j);
					log.debug("NodeName : " + node.getNodeName());
					log.debug("NodeType: " + node.getNodeType());
					log.debug("NodeContent: " + node.getTextContent());
					holidayMapTemp.put(node.getNodeName(), node.getTextContent());
				}
				holidayList.add(holidayMapTemp);
			}
			
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		
		log.debug("InsertPublicHolidayBatchExcute getPublicHolidayMap END");
		
		return holidayList;
	}

}
