package com.style24.batch.biz.service;

import java.nio.charset.StandardCharsets;
import java.security.Security;
import java.security.SignatureException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import com.style24.batch.support.env.TsbConstants;
import com.style24.core.biz.checkout.base.*;
import com.style24.core.biz.dao.TscScmDao;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.gagaframework.web.parameter.GagaMap;
import com.nhncorp.psinfra.toolkit.SimpleCryptLib;
import com.style24.batch.biz.dao.TsbNaverPayDao;
import com.style24.batch.biz.dao.TsbOrderDao;
import com.style24.core.biz.checkout.MallServiceLocator;
import com.style24.core.biz.checkout.MallServiceSOAP11BindingStub;
import com.style24.core.biz.checkout.mall.GetChangedProductOrderListRequest;
import com.style24.core.biz.checkout.mall.GetChangedProductOrderListResponse;
import com.style24.core.biz.checkout.mall.GetProductOrderInfoListRequest;
import com.style24.core.biz.checkout.mall.GetProductOrderInfoListResponse;
import com.style24.core.biz.checkout.mall.PlaceProductOrderRequest;
import com.style24.core.biz.checkout.mall.PlaceProductOrderResponse;
import com.style24.core.biz.dao.TscOrderChangeDao;
import com.style24.core.biz.dao.TscOrderDao;
import com.style24.core.biz.service.TscNaverPayService;
import com.style24.core.biz.service.TscOrderChangeService;
import com.style24.core.biz.service.TscOrderService;
import com.style24.core.support.env.TscConstants;
import com.style24.persistence.domain.Order;
import com.style24.persistence.domain.OrderChange;
import com.style24.persistence.domain.Payment;

import lombok.extern.slf4j.Slf4j;

/**
 * 네이버페이 Service
 *
 * @author xodud1202
 * @since 2021. 05. 27
 */
@Service
@Slf4j
public class TsbNaverPayService {
	@Autowired
	private TsbNaverPayDao naverPayDao;

	@Autowired
	private Environment env;

	@Autowired
	private TscOrderChangeDao coreOrderChangeDao;

	@Autowired
	private TscOrderDao coreOrderDao;

	@Autowired
	private TscOrderService coreOrderService;

	@Autowired
	private TscNaverPayService coreNaverPayService;

	@Autowired
	private TscOrderChangeService coreOrderChangeService;

	@Autowired
	private TsbOrderDao orderDao;

	@Autowired
	private TscScmDao coreScmDao;


	private String timeStamp;
	private String signature;

	/**
	 * 구매 확정 정보 수정
	 * @param changedProductOrderList
	 * @return
	 * @author xodud1202
	 * @since  2021. 05. 28
	 */
	@Transactional("shopTxnManager")
	public Order updateOrderConfirm(ChangedProductOrderInfo[] changedProductOrderList) throws Exception {
		try {
			String[] productOrderIdList = new String[changedProductOrderList.length];
			Order po = new Order();
			for(int i = 0 ; i < changedProductOrderList.length ; i++) {
				productOrderIdList[i] = changedProductOrderList[i].getProductOrderID();
			}

			ProductOrderInfo[] productOrderInfo = productOrderInfoList(productOrderIdList);

			List<Order> list = new ArrayList<Order>();

			if (productOrderInfo != null) {
				for (ProductOrderInfo orderInfo : productOrderInfo) {
					Order order = new Order();
					order.setOrdNo(Integer.parseInt(orderInfo.getProductOrder().getMerchantCustomCode1()));
					order.setNpayOrdDtlNo(orderInfo.getProductOrder().getProductOrderID());

					order = naverPayDao.getOrderConfirmTargetList(order);
					if(order != null) {
						order.setRegNo(TsbConstants.REG_NO);
						order.setUpdNo(TsbConstants.REG_NO);
						order.setOrdDtlStat(TscConstants.OrderDetailStat.PURCHASE_CONFIRM.value());
						coreOrderService.saveOrdDtlStat(order);

						log.info("NAVERPAY 구매확정 성공");
						log.info("NAVERPAY SUCCESS NPAY_ORD_DTL_NO :::: {}", order.getNpayOrdDtlNo());
						log.info("NAVERPAY SUCCESS ORD_DTL_NO :::: {}", order.getOrdDtlNo());
					} else {
						log.info("NAVERPAY 구매확정 조회 실패");
						log.info("NAVERPAY SUCCESS ORD_NO :::: {}", orderInfo.getProductOrder().getMerchantCustomCode1());
						log.info("NAVERPAY SUCCESS NPAY_ORD_DTL_NO :::: {}", orderInfo.getProductOrder().getProductOrderID());
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;
	}

	@Transactional("shopTxnManager")
	public Order cancelOrderInfo(ChangedProductOrderInfo[] changedProductOrderList) throws Exception {
		Order result = new Order();
		List<String> tempProductOrderIdList = new ArrayList<String>();

		Order po = new Order();
		for(ChangedProductOrderInfo orderInfo : changedProductOrderList) {
			po.setNpayOrdDtlNo(orderInfo.getProductOrderID());
			po.setPgGb(TscConstants.PgGb.NAVER_ORDER.value());
			Order detailInfo = naverPayDao.getProductOrderIdInfo(po);
			if(detailInfo != null && detailInfo.getOrdDtlNo() != null && detailInfo.getOrdDtlNo() > 0) {
				tempProductOrderIdList.add(orderInfo.getProductOrderID());
			}
		}

		String[] productOrderIdList = tempProductOrderIdList.toArray(new String[tempProductOrderIdList.size()]);
		ProductOrderInfo[] productOrderInfo = productOrderInfoList(productOrderIdList);

		// 요청 온 정보 취소신청처리
		if(productOrderInfo != null) {
			for(ProductOrderInfo orderInfo : productOrderInfo) {
				Order param = new Order();
				param.setOrdNo(Integer.parseInt(orderInfo.getProductOrder().getMerchantCustomCode1()));		// 주문번호
				param.setNpayOrdDtlNo(orderInfo.getProductOrder().getProductOrderID());		// 상품주문번호
				param.setPgGb(TscConstants.PgGb.NAVER_ORDER.value());
				param.setChgGb("CANCEL_COMPLETE");		// 반려일 경우
				int completeCnt = naverPayDao.getOrdDtlCancelCheck(param);		// 이미 취소 완료되었는지 확인

				if(completeCnt > 0) {
					log.info("이미 취소완료된 주문입니다.(ordNo) : " + param.getOrdNo() + " , (npayOrdDtlNo) : " + param.getNpayOrdDtlNo());
				} else {
					String changeReasonCd = orderInfo.getCancelInfo().getCancelReason().getValue();
					param.setChgMemo(orderInfo.getCancelInfo().getCancelDetailedReason());

					if("PRODUCT_UNSATISFIED".equals(changeReasonCd)) {
						// 단순변심 (네이버 : 서비스 및 상품 불만족)
						param.setChgReason(TscConstants.OrderCancelReason.CHANGE_CUSTOMER.value());
					} else if("DELAYED_DELIVERY".equals(changeReasonCd)) {
						// 배송 지연
						param.setChgReason(TscConstants.OrderCancelReason.DELAY_ORDER.value());
					} else if ("SOLD_OUT".equals(changeReasonCd)) {
						// 품절 취소
						param.setChgReason(TscConstants.OrderCancelReason.SOLDOUT_CANCEL.value());
					} else if ("INTENT_CHANGED".equals(changeReasonCd)) {
						// 구매 의사 취소
						param.setChgReason(TscConstants.OrderCancelReason.CHANGE_CUSTOMER.value());
					} else if ("COLOR_AND_SIZE".equals(changeReasonCd)) {
						// 색상 및 사이즈 변경
						param.setChgReason(TscConstants.OrderCancelReason.CHANGE_CUSTOMER.value());
					} else if ("WRONG_ORDER".equals(changeReasonCd)) {
						// 다른 상품 잘못 주문
						param.setChgReason(TscConstants.OrderCancelReason.CHANGE_CUSTOMER.value());
					} else if ("INCORRECT_INFO".equals(changeReasonCd)) {
						// 상품정보 상이
						param.setChgReason(TscConstants.OrderCancelReason.INCORRECT_INFO.value());
					} else {
						// 사유 확인 불가 (기타 - 추후 네이버페이 자체 사유 추가에 대비)
						param.setChgReason(TscConstants.OrderCancelReason.ETC.value());
					}

					param.setGoodsCd(orderInfo.getProductOrder().getProductID());
					param.setOptCd(orderInfo.getProductOrder().getProductOption());

					Order info = naverPayDao.getProductOrderIdInfo(param);

					int[] dtlNoArr = {info.getOrdDtlNo()};			// 주문상세번호
					int[] cnclQtyArr = {info.getOrdQty()};			// 취소수량 네이버페이 주문형은 수량 취소 없음. 주문 수량을 취소수량으로 전달

					OrderChange change = new OrderChange();
					change.setOrdNo(param.getOrdNo());
					change.setChgGb(TscConstants.OrderChangeGb.CANCEL.value());		// 주문취소
					change.setChgReason(param.getChgReason());						// 취소사유
					change.setChgMemo(param.getChgMemo());							// 취소사유 메모
					change.setUserNo(TsbConstants.REG_NO);							// 배치는 0
					change.setOrdDtlNoArr(dtlNoArr);								// 주문상세번호배열
					change.setCnclRtnReqQtyArr(cnclQtyArr);							// 취소수량배열
					change.setCustNo(info.getCustNo());								// 주문고객번호
					change.setOrdNm(info.getOrdNm());								// 주문자명 (비회원용)
					change.setOrdPhnno(info.getOrdPhnno());							// 주문자휴대폰번호 (비회원용)

					GagaMap cancelInfo = coreOrderChangeService.orderCancelPreInfo(change, change.getUserNo());
				}
			}
		}

		return result;
	}

	/**
	 * 서명생성
	 * @param operationName
	 * @param secreKey
	 * @author xodud1202
	 * @since  2021. 05. 28
	 */
	private void generateSignature(String operationName, String secretKey) {
		timeStamp = SimpleCryptLib.getTimestamp();

		String data = timeStamp + env.getProperty("naverPay.service.name") + operationName;

		try {
			signature = SimpleCryptLib.generateSign(data, secretKey);
		} catch (SignatureException e) {
			log.error(e.getMessage()); //서명정보 실패
		}
	}

	public Collection<Order> getNotWriteWdInvoiceNoChangeList() {
		return naverPayDao.getNotWriteWdInvoiceNoChangeList();
	}

	@Transactional("shopTxnManager")
	public Order getNaverPayWdInvoiceNo(Collection<Order> params) {
		Order result = new Order();
		String[] productOrderIdList = new String[params.size()];
		int z = 0;
		for(Order param : params) { productOrderIdList[z++] = param.getNpayOrdDtlNo(); }

		ProductOrderInfo[] productOrderInfo = productOrderInfoList(productOrderIdList);

		if(productOrderInfo != null && productOrderInfo.length > 0 ) {
			for(int i = 0 ; i < productOrderInfo.length; i++) {
				// 교환인지 반품인지 구분 (교환 : ExchangeInfo , 반품 : ReturnInfo)
				String rInvoiceNo = "";
				String rShipCompCd = "";
				String orderStat = "";
				String claimType = productOrderInfo[i].getProductOrder().getClaimType().toString();

				if (claimType != null && !claimType.equals("")) {
					// 반품 건
					if (claimType.equals("RETURN")) {
						ReturnInfo returnInfo = productOrderInfo[i].getReturnInfo();		// 반품정보
						rInvoiceNo = returnInfo.getCollectTrackingNumber();					// 회수송장번호
						rShipCompCd = returnInfo.getCollectDeliveryCompany();				// 수거택배사코드(네이버페이코드)
						orderStat = TscConstants.OrderChangeStat.RETURN.value();
					} else { // 교환건
						ExchangeInfo exchangeInfo = productOrderInfo[i].getExchangeInfo();	// 교환정보
						rInvoiceNo = exchangeInfo.getCollectTrackingNumber();				// 회수송장번호
						rShipCompCd = exchangeInfo.getCollectDeliveryCompany();				// 수거택배사코드(네이버페이코드)
						orderStat = TscConstants.OrderChangeStat.EXCHANGE.value();
					}

					Order invoiceParam = new Order();
					invoiceParam.setChgOrdDtlStat(orderStat);
					invoiceParam.setNaverPayShipCompCd(rShipCompCd);
					invoiceParam.setWdInvoiceNo(rInvoiceNo);
					invoiceParam.setNpayOrdDtlNo(productOrderInfo[i].getProductOrder().getProductOrderID());
					invoiceParam.setUpdNo(TsbConstants.REG_NO);
					naverPayDao.updateNaverPayWdInvoiceNo(invoiceParam);
				}
			}
		}
		return result;
	}

	/**
	 * 주문상세 정보 조회
	 * @param productOrderIdList
	 * @return
	 * @author xodud1202
	 * @since  2021. 05. 28
	 */
	@Transactional("shopTxnManager")
	public ProductOrderInfo[] productOrderInfoList(String[] productOrderIdList) {
		ProductOrderInfo[] result =  null;
		try {
			if (productOrderIdList != null) {
				Security.addProvider(new BouncyCastleProvider());
				AccessCredentialsType accessCredentialsType = new AccessCredentialsType();
				MallServiceLocator MSL = new MallServiceLocator(env.getProperty("naverPay.port.address"));
				MallServiceSOAP11BindingStub stub = new MallServiceSOAP11BindingStub();
				stub = (MallServiceSOAP11BindingStub) MSL.getMallServiceSOAP11Port();
				GetProductOrderInfoListRequest request = new GetProductOrderInfoListRequest();
				GetProductOrderInfoListResponse response = new GetProductOrderInfoListResponse();

				//서명생성
				generateSignature("GetProductOrderInfoList", env.getProperty("naverPay.secret.key"));
				log.info("GetProductOrderInfoList(상품주문 내역 상세 조회) :: timeStamp === " + timeStamp);

				//인증정보
				accessCredentialsType.setAccessLicense(env.getProperty("naverPay.access.license"));
				accessCredentialsType.setSignature(signature);
				accessCredentialsType.setTimestamp(timeStamp);

				request.setAccessCredentials(accessCredentialsType);
				request.setDetailLevel("Full");
				request.setVersion(env.getProperty("naverPay.version"));
				request.setRequestID("");
				request.setProductOrderIDList(productOrderIdList);

				//GetChangedProductOrderList Response 수신
				response = stub.getProductOrderInfoList(request);

				String resultStr = "";
				if (response.getResponseType() != null) {
					resultStr = response.getResponseType().toUpperCase();
				}

				//결과 출력
				if ("SUCCESS".equals(resultStr)) {
					result = response.getProductOrderInfoList();
				} else {
					log.info("상품주문내역조회 에러");
					log.info("Code    : " + response.getError().getCode());
					log.info("Message : " + response.getError().getMessage());
					log.info("Detail  : " + response.getError().getDetail());
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		log.info("***** productOrderInfoList end *****");

		return result;
	}
}
