package com.style24.front.biz.thirdparty;

import com.gagaframework.web.parameter.GagaMap;
import com.gagaframework.web.util.GagaFileUtil;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.style24.core.support.env.TscConstants;
import com.style24.core.support.util.CryptoUtils;
import com.style24.front.support.security.session.TsfSession;
import com.style24.persistence.domain.CustSnsInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import javax.annotation.PostConstruct;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;
import java.net.URI;


/**
 * Yes24 로그인
 *
 * @author jsshin
 * @since 2021. 03. 03
 */
@Component
@Slf4j
public class Yes24Login {

	@Autowired
	private Environment env;

	@Autowired
	private RestTemplate restTemplate;

	@Value("${has-ssl}")
	private String hasSsl;


	private String id;
	private String type;
	private String webRequestUrl;
	private String mobRequestUrl;
	private String callBackUrl;
	private String userInfoUrl;
	private String linkUrl;
	private String unlinkUrl;
	private String protocal;

	@PostConstruct
	public void init() {
		id = env.getProperty("yes24.id");
		type = env.getProperty("yes24.type");
		webRequestUrl = env.getProperty("yes24.login.web.requestUrl");
		mobRequestUrl = env.getProperty("yes24.login.mob.requestUrl");
		callBackUrl = env.getProperty("yes24.login.callbackUrl");
		userInfoUrl = env.getProperty("yes24.userInfoUrl");
		linkUrl = env.getProperty("yes24.linkUrl");
		unlinkUrl = env.getProperty("yes24.unlinkUrl");

		boolean isSslServer = Boolean.parseBoolean(hasSsl);

		if (isSslServer) {
			protocal = "https://";
		} else {
			protocal = "http://";
		}

		log.debug("\n\n---- YES24 initialization started ----");
		log.debug("id: [{}]", id);
		log.debug("type: [{}]", type);
		log.debug("webRequestUrl: [{}]", webRequestUrl);
		log.debug("mobRequestUrl: [{}]", mobRequestUrl);
		log.debug("callBackUrl: [{}]", callBackUrl);
		log.debug("userInfoUrl: [{}]", userInfoUrl);
		log.debug("linkUrl: [{}]", linkUrl);
		log.debug("unlinkUrl: [{}]", unlinkUrl);
		log.debug("\n--- YES24 initialization completed ----\n");
	}

	/**
	 * YES24 로그인 화면
	 * @param state - 콜백 시 해당 값으로 비교 및 모바일을 redirect 값이 있음
	 * @return String - 호출 url정보
	 * @author jsshin
	 * @since 2021. 03. 03
	 */
	public String getAuthorizeUrl(String state) {
		String idGb = "PID";
		String requestUrl = TsfSession.getFrontGb().equals("P") ? webRequestUrl : mobRequestUrl;
		StringBuilder apiUrlBuilder = new StringBuilder();
		String redirectUri = GagaFileUtil.getConcatenationPath(protocal + TsfSession.getHttpServletRequest().getServerName(), callBackUrl);
		apiUrlBuilder.append(requestUrl)
				.append("?")
				.append(idGb)
				.append("=")
				.append(id)
				.append("&ReturnURL=")
				.append(redirectUri);
		log.info("apiUrlBuilder ===> {}", apiUrlBuilder.toString());
		return apiUrlBuilder.toString();
	}

	/**
	 * YES24 고객 정보
	 *
	 * @param inpin - yes24 전달 해준 암호화된 : "요청날짜|CI"
	 * @return String - 호출 url정보
	 * @author jsshin
	 * @since 2021. 03. 03
	 */
	public GagaMap getUserInfo(String inpin) {
		GagaMap result = new GagaMap();
		try {
			// 1. ipin 복호화
			String decryptIpin = CryptoUtils.decryptYes24AES(inpin);

			// 2. ipin 값에서 ci 값 분리
			String decryptIpinValues[] = decryptIpin.split("\\|");

			// 3. Ci 다시 암호화
			String encryptCi = CryptoUtils.encryptYes24AES(decryptIpinValues[1]);

			MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
			params.add("str_ci", encryptCi);
			params.add("str_Type", type);

			// Header
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

			HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(params, headers);
			URI url = URI.create(userInfoUrl);

			// POST방식으로 호출
			ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, request, String.class);
			log.info("getUserInfo responseEntity.getStatusCode(): {} ", responseEntity.getStatusCode());
			String responseEntityBody = responseEntity.getBody();
			log.info("getUserInfo responseEntity.getBody(): {} ", responseEntityBody);

			// 4. XML 데이터 파싱
			result = getCustInfoXmlParsing(responseEntityBody);
		} catch (Exception e) {
			log.error(e.getMessage());
		}

		return result;
	}

	/**
	 * YES24 고객 정보
	 *
	 * @param responseEntityBody - yes24 전달 고객정보 XML
	 * @return GagaMap - 고객정보
	 * @author jsshin
	 * @since 2021. 03. 26
	 */
	public GagaMap getCustInfoXmlParsing(String responseEntityBody) throws Exception{
		InputSource is = new InputSource(new StringReader(responseEntityBody));
		Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is);
		Node node = document.getDocumentElement();
		NodeList nodeList = node.getChildNodes();
		GagaMap nodeMap = new GagaMap();
		for(int i = 0; i < nodeList.getLength(); i++) {
			Node item = nodeList.item(i);
			if (!"#text".equals(item.getNodeName())) {
				nodeMap.setString(item.getNodeName(), item.getTextContent());
			}
		}
		GagaMap resultMap = new GagaMap();
		String memNo = nodeMap.getString("str_MEM_NO");
		String snsId = nodeMap.getString("str_MEM_ID");
		String custNm = nodeMap.getString("str_MEM_NM");
		String email = nodeMap.getString("str_MEM_EML");
		String telNo = nodeMap.getString("str_ADDR_TEL_NO");     // YES24 회원정보가 - 필수전화
		String mobNo = nodeMap.getString("str_ADDR_MOB_NO"); // YES24 회원정보가 - 휴대전화 
		String birthYmd = nodeMap.getString("str_BIRTH_DM").replaceAll("-","");
		String sexGb = nodeMap.getString("str_SEX").equals("M")? TscConstants.Gender.MALE.value() : TscConstants.Gender.FEMALE.value();
		String ci = nodeMap.getString("str_IPIN_CI");
		String homeZipcode = nodeMap.getString("str_ADDR_ZIP");
		String homeBaseAddr = nodeMap.getString("str_ADDR_ADDR1");
		String homeDtlAddr = nodeMap.getString("str_ADDR_ADDR2");

		String cellphnno = getValidationCellphone(telNo,mobNo);
		
		resultMap.setString("memNo", memNo);
		resultMap.setString("snsId", snsId);
		resultMap.setString("custNm", custNm);
		resultMap.setString("email", email);
		resultMap.setString("ci", ci);
		resultMap.setString("cellPhnno", cellphnno);
		resultMap.setString("birthYmd", birthYmd);
		resultMap.setString("sexGb", sexGb);
		resultMap.setString("homeZipcode", homeZipcode);
		resultMap.setString("homeBaseAddr", homeBaseAddr);
		resultMap.setString("homeDtlAddr",homeDtlAddr);

		return resultMap;
	}

	/**
	 * YES24 고객 연동처리
	 *
	 * @param  custSnsInfo - 고객정보
	 * @return String - 호출 url정보
	 * @author jsshin
	 * @since 2021. 03. 03
	 */
	public void saveLink(CustSnsInfo custSnsInfo) {
		// 1. Ci 다시 암호화
		String encryptCi = CryptoUtils.encryptYes24AES(custSnsInfo.getCi());
		String joinGb = TsfSession.getFrontGb().equals("P") ? "P" : "M";

		try {
			MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
			params.add("str_ci", encryptCi);
			params.add("mem_id", custSnsInfo.getSnsId());
			params.add("partner_id", custSnsInfo.getSnsType()+'_'+custSnsInfo.getMemNo());
			params.add("join_gb", joinGb);
			params.add("str_Type", type);

			// Header
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

			HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(params, headers);
			URI url = URI.create(linkUrl);

			// POST방식으로 호출
			ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, request, String.class);
			log.info("saveLink responseEntity.getStatusCode(): {} ", responseEntity.getStatusCode());
			String responseEntityBody = responseEntity.getBody();
			log.info("saveLink responseEntity.getBody(): {} ", responseEntityBody);

		} catch (Exception e) {
			log.error(e.getMessage());
		}
	}


	/**
	 * YES24 고객 연동해지
	 *
	 * @param  custSnsInfo - 고객정보
	 * @return String - 호출 url정보
	 * @author jsshin
	 * @since 2021. 03. 03
	 */
	public void saveUnLink(CustSnsInfo custSnsInfo) {
		String joinGb = TsfSession.getFrontGb().equals("P") ? "P" : "M";

		// 1. Ci 다시 암호화
		String encryptCi = CryptoUtils.encryptYes24AES(custSnsInfo.getCi());

		try {
			MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
			params.add("str_ci", encryptCi);
			params.add("mem_id", custSnsInfo.getSnsId());
			params.add("partner_id", custSnsInfo.getSnsType()+'_'+custSnsInfo.getMemNo());
			params.add("join_gb", joinGb);
			params.add("str_Type", type);

			// Header
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

			HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(params, headers);
			URI url = URI.create(unlinkUrl);

			// POST방식으로 호출
			ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, request, String.class);
			log.info("getUserInfo responseEntity.getStatusCode(): {} ", responseEntity.getStatusCode());
			String responseEntityBody = responseEntity.getBody();
			log.info("getUserInfo responseEntity.getBody(): {} ", responseEntityBody);


		} catch (Exception e) {
			log.error(e.getMessage());
		}
	}
	
	private String getValidationCellphone (String telNo, String mobNo) {
		String result = "";
		String regExp = "^01(?:0|1|[6-9])[.-]?(\\d{3}|\\d{4})[.-]?(\\d{4})$";
		if(telNo.matches(regExp)) {
			return telNo;
		} else if(mobNo.matches(regExp)) {
			return mobNo;
		}
		return result;
	}




}
