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;

	public Order setInitData() {
		Order time = this.getSelectDt();
		String stdt = time.getStdt();
		String eddt = time.getEddt();

		if("locd".equals(env.getProperty("spring.profiles.active"))) {
			stdt = "20210701000000";
			eddt = "20210701235959";

			log.info("stdt : eddt ---> " + stdt + " : " + eddt);
		}

		Date tmp1 	= new SimpleDateFormat("yyyyMMddHHmmss").parse(stdt, new ParsePosition(0));
		Date tmp2 	= new SimpleDateFormat("yyyyMMddHHmmss").parse(eddt, new ParsePosition(0));

		Calendar from = Calendar.getInstance();
		Calendar to = Calendar.getInstance();

		from.setTime(tmp1);
		to.setTime(tmp2);
		SimpleDateFormat fmt 	= new SimpleDateFormat("yyyyMMddHHmmss");
		stdt = fmt.format(from.getTime());
		eddt = fmt.format(to.getTime());

		Order naverParams = new Order();
		naverParams.setStdt(stdt);
		naverParams.setEddt(eddt);
		naverParams.setFrom(from);
		naverParams.setTo(to);

		return naverParams;
	}

	/**
	 * 네이버페이 시간 조건 조회 (최근3시간)
	 * @return Order
	 * @author xodud1202
	 * @since  2021. 05. 27
	 */
	public Order getSelectDt() {
		return naverPayDao.getSelectDt();
	}

	/**
	 * 네이버페이 주문 변경 리스트 조회
	 * @param option, from, to
	 * @return
	 * @throws Exception
	 * @author xodud1202
	 * @since  2021. 05. 28
	 */
	@Transactional("shopTxnManager")
	public ChangedProductOrderInfo[] changedProductOrderList(ProductOrderChangeType option, Calendar from, Calendar to) throws Exception {
		ChangedProductOrderInfo[] result = null;

		String mallId = env.getProperty("naverPay.shop.id");
		String accessLicense = env.getProperty("naverPay.access.license");
		String secretKey = env.getProperty("naverPay.secret.key");

		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();

		GetChangedProductOrderListRequest request 		= new GetChangedProductOrderListRequest();
		GetChangedProductOrderListResponse response 	= new GetChangedProductOrderListResponse();

		//서명생성
		generateSignature("GetChangedProductOrderList", secretKey);
		log.info("GetChangedProductOrderList(변경 상품주문 조회) :: timeStamp === " + timeStamp);

		//인증정보
		accessCredentialsType.setAccessLicense(accessLicense);
		accessCredentialsType.setSignature(signature);
		accessCredentialsType.setTimestamp(timeStamp);
		request.setAccessCredentials(accessCredentialsType);

		//GetChangedProductOrderList 파라메터 설정
		request.setDetailLevel("Full");
		request.setVersion(env.getProperty("naverPay.version"));
		request.setRequestID("");
		request.setMallID(mallId);
		request.setInquiryTimeFrom(from);
		request.setInquiryTimeTo(to);
		request.setLastChangedStatusCode(option);

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

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

		//결과 출력
		if ("SUCCESS".equals(resultStr)) {
			result = response.getChangedProductOrderInfoList();
		} else {
			Order fail = new Order();

			log.info("response.getResponseType()) : " + response.getResponseType());
			log.info("option.toString() : " + option.toString());
			log.info("Code : " + response.getError().getCode());
			log.info("Message : " + response.getError().getMessage());
			log.info("Detail : " + response.getError().getDetail());

			fail.setErrorReason("변경상품주문조회 에러");
			fail.setOrdNo(0);
			fail.setOptCd(option.toString());
			fail.setResultCd(response.getError().getCode());
			fail.setResultMsg(response.getError().getMessage());
			fail.setMallCd(mallId);
			fail.setAccessLicense(accessLicense);
			fail.setSecretKey(secretKey);
			fail.setRegNo(TsbConstants.REG_NO);

			coreOrderDao.createNaverPayErrorLog(fail);
		}

		return result;
	}

	/**
	 * 결제 정보 수정
	 * @param changedProductOrderList
	 * @return
	 * @author xodud1202
	 * @since  2021. 05. 28
	 */
	@Transactional("shopTxnManager")
	public Order createOrderInfo(ChangedProductOrderInfo[] changedProductOrderList) throws Exception {
		String[] productOrderIdList = new String[changedProductOrderList.length];
		String orderStat = TscConstants.OrderDetailStat.PAYMENT_COMPLETE.value();	// 결제완료

		for (int i=0; i<changedProductOrderList.length; i++) {
			productOrderIdList[i] = changedProductOrderList[i].getProductOrderID();
		}

		ProductOrderInfo[] productOrderInfo = productOrderInfoList(productOrderIdList);
		byte[] encryptKey = null;
		encryptKey = SimpleCryptLib.generateKey(timeStamp, env.getProperty("naverPay.secret.key"));
		log.info("결제완료 :: timeStamp === " + timeStamp);

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

		String rcpDtlAddr 	= "";
		String orderNo = "";
		String naverSeq = "";

		if (productOrderInfo != null) {
			for (ProductOrderInfo orderInfo : productOrderInfo) {
				rcpDtlAddr = "";

				Order naverParams = new Order();
				orderNo = orderInfo.getProductOrder().getMerchantCustomCode1();        // 가맹점 주문번호
				// naverSeq 	= productOrderInfo[i].getProductOrder().getProductOrderID();		// 네이버주문번호순번
				if (StringUtils.isNotBlank(orderNo) && !"0".equals(orderNo)) {
					// TB_ORDER 네이버페이 주문번호 UPDATE
					naverParams.setOrdNo(Integer.parseInt(orderNo));
					naverParams.setOrdNm(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getOrder().getOrdererName()), StandardCharsets.UTF_8));
					naverParams.setOrdPhnno(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getOrder().getOrdererTel1()), StandardCharsets.UTF_8));
					naverParams.setOrdEmail(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getOrder().getOrdererID()), StandardCharsets.UTF_8) + "@naver.com");
					naverParams.setGoodsCd(orderInfo.getProductOrder().getProductID());    // 네이버페이 상품코드
					naverParams.setSiteCd(orderInfo.getProductOrder().getMallID());
					naverParams.setUpdNo(0);
					Collection<Order> dtlList = naverPayDao.getOrdBaseInfo(naverParams);

					// 결제대기상태만 진행
					if (dtlList.size() > 0) {
						naverParams.setNpayOrdNo(orderInfo.getOrder().getOrderID());            // 네이버 주문번호
						coreOrderDao.updateNaverPayOrderNo(naverParams);

						Order orderDtlList = updateNpayOrderDtl(orderInfo, encryptKey, naverParams);

						// TB_PAYMENT 결제 완료로 변경 및 데이터 수정
						log.info("CHECK orderNo ::::: {}", orderNo);
						Payment payment = new Payment();
						payment.setOrdNo(Integer.parseInt(orderNo));
						payment.setPayStat(TscConstants.PaymentStat.PAYMENT_COMPLETE.value());
						payment.setPgTid(orderInfo.getOrder().getPaymentNumber());
						payment.setPayMeans(orderInfo.getOrder().getPaymentMeans());
						naverPayDao.updateNaverpayPaymentInfo(payment);
					}
				}
			}
		}

		return null;
	}

	@Transactional("shopTxnManager")
	public Order updateNpayOrderDtl(ProductOrderInfo productOrderInfo, byte[] encryptKey, Order npayParam) throws Exception {
		Order order = new Order();
		order.setGoodsCd(productOrderInfo.getProductOrder().getProductID());			// 네이버페이 상품코드
		String npayOrdDtlNo = productOrderInfo.getProductOrder().getProductOrderID();	// 네이버페이 상품주문번호
		order.setOptCd(productOrderInfo.getProductOrder().getOptionManageCode());		// 고유 상품 옵션 번호 (optCd)

		log.info("CHECK GOODS_CD :::: {}", order.getGoodsCd());
		log.info("CHECK NPAY_ORD_DTL_NO :::: {}", npayOrdDtlNo);
		log.info("CHECK OPT_CD :::: {}", order.getOptCd());

		// 옵션정보 존재하지 않으면 return null;
		if(StringUtils.isBlank(order.getOptCd())) return null;
		if(StringUtils.isBlank(npayOrdDtlNo)) return null;

		// 주문정보 조회 (상품타입, 주문상품들 조회)
		order.setNpayOrdDtlNo(npayOrdDtlNo);
		order.setOrdNo(npayParam.getOrdNo());
		order.setNpayOrdNo(npayParam.getNpayOrdNo());
		Collection<Order> orderDtlList = naverPayDao.getOrdBaseInfo(order);
		int ordDtlNo = 0;

		// 같은 상품 중 ordDtlNo 찾기
		for(Order dtl : orderDtlList) {
			// 세트상품일경우
			if(TscConstants.GoodsType.SET.value().equals(dtl.getGoodsType())) {
				if(order.getOptCd().contains("/")) {
					String[] optCds = order.getOptCd().split("/");
					boolean chkItem = true;

					for(String optCd : optCds) {
						dtl.setOptCd(optCd);
						if(naverPayDao.getIsNaverPayItem(dtl) < 1) {
							chkItem = false;
						}
					}

					// 해당 Dtl List에 있는 옵션이 모두 같으면 상품주문번호 저장
					if(chkItem) {
						dtl.setOrdDtlStat(TscConstants.OrderDetailStat.PAYMENT_COMPLETE.value());
						dtl.setNpayOrdDtlNo(order.getNpayOrdDtlNo());
						dtl.setRegNo(TsbConstants.REG_NO);
						dtl.setUpdNo(TsbConstants.REG_NO);
						dtl.setCustNo(TsbConstants.REG_NO);
						dtl.setSellGb("10");
						ordDtlNo = dtl.getOrdDtlNo();
						naverPayDao.updateNpayOrdDtlNo(dtl);
						coreOrderDao.createOrderDetailHst(dtl);
						coreScmDao.updateOrderDetailItemStat(dtl);
						
						// 2021.06.25 네이버페이 결제완료 (정산구분값추가)
						dtl.setOrdDtlStat(TscConstants.OrdDtlItemStat.SALE_PAYMENT_COMPLETE.value());
						coreOrderDao.createOrderDetailItemHstFromDtlNo(dtl);
						
						coreOrderDao.createSellQty(dtl);
					}
				} else if (order.getOptCd().length() > 0) {
					//if(dtl.getOptCd().equals(order.getOptCd())) {
						// 세트상품인데 구성 상품이 하나밖에 없을때. 존재하지 않을것으로 보임.
						dtl.setOptCd(order.getOptCd());
						Collection<Order> item = coreOrderChangeDao.getOrderDetailItem(dtl);

						for(Order itemOne : item) {
							if(itemOne.getOptCd().equals(dtl.getOptCd())) {
								itemOne.setOrdDtlStat(TscConstants.OrderDetailStat.PAYMENT_COMPLETE.value());
								itemOne.setNpayOrdDtlNo(order.getNpayOrdDtlNo());
								itemOne.setRegNo(TsbConstants.REG_NO);
								itemOne.setUpdNo(TsbConstants.REG_NO);
								itemOne.setCustNo(TsbConstants.REG_NO);
								itemOne.setSellGb("10");
								ordDtlNo = itemOne.getOrdDtlNo();
								naverPayDao.updateNpayOrdDtlNo(itemOne);
								coreOrderDao.createOrderDetailHst(itemOne);
								coreScmDao.updateOrderDetailItemStat(itemOne);
								
								// 2021.06.25 네이버페이 결제완료 (정산구분값추가)
								itemOne.setOrdDtlStat(TscConstants.OrdDtlItemStat.SALE_PAYMENT_COMPLETE.value());
								coreOrderDao.createOrderDetailItemHstFromDtlNo(itemOne);
								coreOrderDao.createSellQty(itemOne);
							}
						}
					//}
				}
			} else {
				// 일반상품일경우(딜상품도 네이버페이 송부시에는 일반으로 송부함)
				// 네이버페이 수신 옵션 정보 주문 조회 - 세트 상품이 아닐 경우 결과값 1ROW만 나옴
				//if(dtl.getOptCd().equals(order.getOptCd())) {
					dtl.setOptCd(order.getOptCd());
					Collection<Order> item = coreOrderChangeDao.getOrderDetailItem(dtl);

					for (Order itemOne : item) {
						if(itemOne.getOptCd().equals(dtl.getOptCd())) {
							itemOne.setOrdDtlStat(TscConstants.OrderDetailStat.PAYMENT_COMPLETE.value());
							itemOne.setNpayOrdDtlNo(order.getNpayOrdDtlNo());
							itemOne.setRegNo(TsbConstants.REG_NO);
							itemOne.setUpdNo(TsbConstants.REG_NO);
							itemOne.setCustNo(TsbConstants.REG_NO);
							itemOne.setSellGb("10");
							ordDtlNo = itemOne.getOrdDtlNo();
							naverPayDao.updateNpayOrdDtlNo(itemOne);
							coreOrderDao.createOrderDetailHst(itemOne);
							coreScmDao.updateOrderDetailItemStat(itemOne);
							
							// 2021.06.25 네이버페이 결제완료 (정산구분값추가)
							itemOne.setOrdDtlStat(TscConstants.OrdDtlItemStat.SALE_PAYMENT_COMPLETE.value());
							coreOrderDao.createOrderDetailItemHstFromDtlNo(itemOne);
							coreOrderDao.createSellQty(itemOne);
						}
					}
				//}
			}
		}

		// 배송지 정보 수정
		if(ordDtlNo > 0) {
			npayParam.setOrdDtlNo(ordDtlNo);
			order.setOrdDtlNo(ordDtlNo);
			order.setRecipNm(new String(SimpleCryptLib.decrypt(encryptKey, productOrderInfo.getProductOrder().getShippingAddress().getName()), StandardCharsets.UTF_8));
			order.setRecipPhnno(new String(SimpleCryptLib.decrypt(encryptKey, productOrderInfo.getProductOrder().getShippingAddress().getTel1()), StandardCharsets.UTF_8));
			order.setRecipZipcode(productOrderInfo.getProductOrder().getShippingAddress().getZipCode().replaceAll("-", ""));
			order.setRecipBaseAddr(new String(SimpleCryptLib.decrypt(encryptKey, productOrderInfo.getProductOrder().getShippingAddress().getBaseAddress()), StandardCharsets.UTF_8));
			order.setRecipDtlAddr(new String(SimpleCryptLib.decrypt(encryptKey, productOrderInfo.getProductOrder().getShippingAddress().getDetailedAddress()), StandardCharsets.UTF_8));
			order.setDelvMemo(productOrderInfo.getProductOrder().getShippingMemo());

			if(StringUtils.isNotBlank(productOrderInfo.getProductOrder().getShippingAddress().getTel2())) {
				order.setRecipTelno(new String(SimpleCryptLib.decrypt(encryptKey, productOrderInfo.getProductOrder().getShippingAddress().getTel2()), StandardCharsets.UTF_8));
			}

			naverPayDao.updateShippingAddressInfo(order);
		}

		order.setRegNo(TsbConstants.REG_NO);
		order.setUpdNo(TsbConstants.REG_NO);
		order.setCustNo(TsbConstants.REG_NO);
		order.setSellGb("10");
		order.setPgGb(TscConstants.PgGb.NAVER_ORDER.value());
		order.setPayMeans(TscConstants.PayMeans.CREDIT_CARD.value());
		//coreOrderService.updateOrderInfo(order);

		return order;
	}

	/**
	 * 구매 확정 정보 수정
	 * @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(0);											// 배치는 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;
	}

	@Transactional("shopTxnManager")
	public Order recvExchangeReqOrder(ChangedProductOrderInfo[] changedProductOrderList) throws Exception {
		String[] productOrderIdList = new String[changedProductOrderList.length];
		for(int i = 0 ; i < changedProductOrderList.length ; i++) {
			productOrderIdList[i] = changedProductOrderList[i].getProductOrderID();
		}

		ProductOrderInfo[] productOrderInfo = productOrderInfoList(productOrderIdList);

		byte[] encryptKey = SimpleCryptLib.generateKey(timeStamp, env.getProperty("naverPay.secret.key"));

		for(ProductOrderInfo orderInfo : productOrderInfo) {
			// 교환 접수 대상 주문 정보 조회
			Order order = new Order();

			// ordChgSq 묶음 상품 정보 조회
			order.setNpayOrdDtlNo(orderInfo.getProductOrder().getProductOrderID());
			log.info("CHECK orderInfo.getExchangeInfo().getClaimDeliveryFeeProductOrderIds() :::: {}", orderInfo.getExchangeInfo().getClaimDeliveryFeeProductOrderIds());
			if(StringUtils.isNotBlank(orderInfo.getExchangeInfo().getClaimDeliveryFeeProductOrderIds())) {
				order.setClaimNpayOrdDtlNos(orderInfo.getExchangeInfo().getClaimDeliveryFeeProductOrderIds().replaceAll(" ", "").split(","));
			} else {
				String[] npayOrdDtlNos = {orderInfo.getProductOrder().getProductOrderID()};
				order.setClaimNpayOrdDtlNos(npayOrdDtlNos);
			}

			Collection<Order> itemList = naverPayDao.getNotExchangeOrderInfoList(order);

			// 정보가 없을 경우 다음 주문건으로 변경
			if(itemList.size() < 1) continue;

			// 교환 정보 리스트
			List<Order> cancelReqList = new ArrayList<>();

			// 교환 사유 코드
			String changeReasonCode 	= orderInfo.getExchangeInfo().getExchangeReason().getValue();

			// 교환 접수 처리
			OrderChange change = new OrderChange();
			int addDelvFee = 0;
			if(orderInfo.getExchangeInfo().getClaimDeliveryFeeDemandAmount() != null) {
				 addDelvFee = orderInfo.getExchangeInfo().getClaimDeliveryFeeDemandAmount();
			}

			log.info("ORD_NO ::::::::: {}", orderInfo.getProductOrder().getMerchantCustomCode1());

			change.setOrdNo(Integer.parseInt(orderInfo.getProductOrder().getMerchantCustomCode1()));	// 주문번호
			change.setAddPayCost(addDelvFee);															// 추가배송비
			change.setWdInvoiceNo(orderInfo.getExchangeInfo().getCollectTrackingNumber());				// 회수송장번호

			if ("COLOR_AND_SIZE".equals(changeReasonCode)) {				// 색상 및 사이즈 변경
				change.setIsCustomer(true);		// 고객 사유 여부
				change.setChgReason(TscConstants.OrderChangeReason.CHANGE_OPTION.value());		// 사이즈 변경
			} else if ("WRONG_ORDER".equals(changeReasonCode)) {			// 다른 상품 잘못 주문
				change.setIsCustomer(true);		// 고객 사유 여부
				change.setChgReason(TscConstants.OrderChangeReason.CHANGE_OPTION.value());		// 사이즈 변경
			} else if ("PRODUCT_UNSATISFIED".equals(changeReasonCode)) {	// 서비스 및 상품 불만족
				change.setIsCustomer(false);	// 고객 사유 여부
				change.setChgReason(TscConstants.OrderChangeReason.INCORRECT_OPTION.value());	// 상품 정보와 상이함 (상품 불만족이 존재하지 않아 상품정보 상이로 지정)
			} else if ("INCORRECT_INFO".equals(changeReasonCode)) {			// 상품정보 상이
				change.setIsCustomer(false);	// 고객 사유 여부
				change.setChgReason(TscConstants.OrderChangeReason.INCORRECT_OPTION.value());	// 상품 정보와 상이함
			} else if ("BROKEN".equals(changeReasonCode)) {					// 상품파손
				change.setIsCustomer(false);	// 고객 사유 여부
				change.setChgReason(TscConstants.OrderChangeReason.BROKEN.value());				// 상품이 파손되어 배송됨
			} else if ("WRONG_DELIVERY".equals(changeReasonCode)) {			// 오배송
				change.setIsCustomer(false);	// 고객 사유 여부
				change.setChgReason(TscConstants.OrderChangeReason.INCORRECT_DELV.value());		// 상품주문과 다른 상품이 배송됨
			} else if ("WRONG_OPTION".equals(changeReasonCode)) {			// 색상 등 다른 상품잘못 배송
				change.setIsCustomer(false);	// 고객 사유 여부
				change.setChgReason(TscConstants.OrderChangeReason.CHANGE_OPTION.value());		// 상품주문과 다른 상품이 배송됨
			} else if ("DROPPED_DELIVERY".equals(changeReasonCode)) {		// 배송누락
				change.setIsCustomer(false);	// 고객 사유 여부
				change.setChgReason(TscConstants.OrderChangeReason.NOT_DELV_ALL.value());		// 일부 상품이 배송되지 않음
			}

			// 직접 반송일 경우 회수지정보 (네이버페이 주문형은 배송지도 동일 적용 (배송지 주소 작성란 없음))
			// 회수 지시에 대한 내용은 모든 금액을 네이버페이에서 처리하기로(21/06/28 - 정지혜K 확인) 하였으나, 회수지시 불가 상품이 있는 경우에 대비하여 처리
			// 교환 요청시
			if(orderInfo.getExchangeInfo().getCollectDeliveryMethod() == null) {
				change.setWdGb("D");
				change.setWdTargetYn("N");

				// 회수자명, 휴대폰번호, 우편번호, 기본주소, 상세주소
				change.setRecipZipcode(orderInfo.getProductOrder().getShippingAddress().getZipCode().replaceAll("-", ""));
				change.setRecipNm(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getProductOrder().getShippingAddress().getName()), StandardCharsets.UTF_8));
				change.setRecipPhnno(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getProductOrder().getShippingAddress().getTel1()), StandardCharsets.UTF_8));
				change.setRecipBaseAddr(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getProductOrder().getShippingAddress().getBaseAddress()), StandardCharsets.UTF_8));
				if(StringUtils.isNotBlank(orderInfo.getProductOrder().getShippingAddress().getZipCode())) {
					change.setRecipZipcode(orderInfo.getProductOrder().getShippingAddress().getZipCode().replaceAll("-", ""));
				}
				if(StringUtils.isNotBlank(orderInfo.getProductOrder().getShippingAddress().getDetailedAddress())) {
					change.setRecipDtlAddr(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getProductOrder().getShippingAddress().getDetailedAddress()), StandardCharsets.UTF_8));
				}
			} else if("RETURN_INDIVIDUAL".equals(orderInfo.getExchangeInfo().getCollectDeliveryMethod().toString())) {
				change.setWdGb("D");
				change.setWdTargetYn("N");

				// 회수자명, 휴대폰번호, 우편번호, 기본주소, 상세주소
				change.setRecipNm(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getProductOrder().getShippingAddress().getName()), StandardCharsets.UTF_8));
				change.setRecipPhnno(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getProductOrder().getShippingAddress().getTel1()), StandardCharsets.UTF_8));
				change.setRecipBaseAddr(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getProductOrder().getShippingAddress().getBaseAddress()), StandardCharsets.UTF_8));
				if(StringUtils.isNotBlank(orderInfo.getProductOrder().getShippingAddress().getZipCode())) {
					change.setRecipZipcode(orderInfo.getProductOrder().getShippingAddress().getZipCode().replaceAll("-", ""));
				}
				if(StringUtils.isNotBlank(orderInfo.getProductOrder().getShippingAddress().getDetailedAddress())) {
					change.setRecipDtlAddr(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getProductOrder().getShippingAddress().getDetailedAddress()), StandardCharsets.UTF_8));
				}
			} else {			// 수거 요청일 경우
				change.setWdGb("W");
				change.setWdTargetYn("N");

				// 회수자명, 휴대폰번호, 우편번호, 기본주소, 상세주소
				change.setRecipNm(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getExchangeInfo().getCollectAddress().getName()), StandardCharsets.UTF_8));
				change.setRecipPhnno(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getExchangeInfo().getCollectAddress().getTel1()), StandardCharsets.UTF_8));
				change.setRecipBaseAddr(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getExchangeInfo().getCollectAddress().getBaseAddress()), StandardCharsets.UTF_8));
				change.setRecipDtlAddr(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getExchangeInfo().getCollectAddress().getDetailedAddress()), StandardCharsets.UTF_8));
				if(StringUtils.isNotBlank(orderInfo.getExchangeInfo().getCollectAddress().getZipCode())) {
					change.setRecipZipcode(orderInfo.getExchangeInfo().getCollectAddress().getZipCode().replaceAll("-", ""));
				}
			}

			// 배송지 정보 (네이버페이 주문형 배송지는 회수지와 동일 적용 (배송지 주소 작성란 없음))
			change.setChgerNm(change.getRecipNm());
			change.setChgerPhnno(change.getRecipPhnno());
			change.setChgerZipcode(change.getRecipZipcode());
			change.setChgerBaseAddr(change.getRecipBaseAddr());
			change.setChgerDtlAddr(change.getRecipDtlAddr());

			log.info("change.getRecipNm() ::::: {}", change.getRecipNm());
			log.info("change.getRecipPhnno() ::::: {}", change.getRecipPhnno());
			log.info("change.getRecipZipcode() ::::: {}", change.getRecipZipcode());
			log.info("change.getRecipBaseAddr() ::::: {}", change.getRecipBaseAddr());
			log.info("change.getRecipDtlAddr() ::::: {}", change.getRecipDtlAddr());
			log.info("CHECK ClaimDeliveryFeeDemandAmount :::: {}", orderInfo.getExchangeInfo().getClaimDeliveryFeeDemandAmount());
			log.info("CHECK ClaimDeliveryFeeProductOrderIds :::: {}", orderInfo.getExchangeInfo().getClaimDeliveryFeeProductOrderIds());
			log.info("CHECK ClaimDeliveryFeePayMethod :::: {}", orderInfo.getExchangeInfo().getClaimDeliveryFeePayMethod());
			log.info("CHECK ClaimDeliveryFeePayMeans :::: {}", orderInfo.getExchangeInfo().getClaimDeliveryFeePayMeans());
			log.info("CHECK CollectDeliveryCompany :::: {}", orderInfo.getExchangeInfo().getCollectDeliveryCompany());
			log.info("CHECK CollectTrackingNumber :::: {}", orderInfo.getExchangeInfo().getCollectTrackingNumber());

			for(Order item : itemList) {
				addDelvFee = 0;
				// 추가 배송비
				if(orderInfo.getExchangeInfo().getClaimDeliveryFeeDemandAmount() != null) {
					addDelvFee = orderInfo.getExchangeInfo().getClaimDeliveryFeeDemandAmount();
				}

				// SELECT 후 필요 데이터
				change.setCustNo(item.getCustNo());														// 회원번호
				change.setSelfGoodsYn(item.getSelfGoodsYn());											// 자사 상품 여부

				Order cancelReq = new Order();
				cancelReq.setOrdDtlNo(item.getOrdDtlNo());												// 주문상세번호
				cancelReq.setOrdDtlItemSq(item.getOrdDtlItemSq());										// 주문상세단품일련번호
				cancelReq.setDelvFeeCd(item.getDelvFeeCd());											// 출고처코드
				cancelReq.setSupplyCompCd(item.getSupplyCompCd());										// 공급업체코드
				cancelReq.setChgQty(item.getOrdQty());													// 교환수량 (네이버페이주문형은 수량부분 취/반/교 없음. 전체수량.)
				cancelReq.setOrdChgOpt(item.getOptCd2());												// 교환옵션 (네이버페이주문형은 교환 옵션이 존재하지 않음. 메모를 보고 수정해야함)
				cancelReq.setExcDelvFee(item.getDelvFee() + item.getRtnDelvFee());						// 교환 배송비 (기준 교환 배송비 = 배송비 + 반품배송비)
				cancelReq.setRtnDelvFee(item.getRtnDelvFee());											// 반품배송비

				cancelReqList.add(cancelReq);
			}

			change.setCancelReqList(cancelReqList);;

			// 교환접수 처리
			change.setRegNo(TsbConstants.REG_NO);
			change.setUpdNo(TsbConstants.REG_NO);
			change.setPgGb(TscConstants.PgGb.NAVER_ORDER.value());
			String delvFeeMemo = "";
			if(orderInfo.getExchangeInfo().getClaimDeliveryFeeDemandAmount() != null && orderInfo.getExchangeInfo().getClaimDeliveryFeeDemandAmount() > 0) {
				if(StringUtils.isNotBlank(orderInfo.getExchangeInfo().getClaimDeliveryFeePayMethod()) && orderInfo.getExchangeInfo().getClaimDeliveryFeePayMethod().contains("동봉")) {
					delvFeeMemo = "/배송비동봉 " + orderInfo.getExchangeInfo().getClaimDeliveryFeeDemandAmount();
				} else if(StringUtils.isNotBlank(orderInfo.getExchangeInfo().getClaimDeliveryFeePayMethod()) && orderInfo.getExchangeInfo().getClaimDeliveryFeePayMethod().contains("송금")) {
					delvFeeMemo = "/배송비송금 " + orderInfo.getExchangeInfo().getClaimDeliveryFeeDemandAmount();
				}
			}

			change.setChgMemo("[네이버페이]-교환 " + delvFeeMemo + "/" + orderInfo.getExchangeInfo().getExchangeDetailedReason());					// 교환 상세 사유
			change.setWdTargetYn("N");
			log.info("CHECK CHG_MEMO :::: {}", change.getChgMemo());

			GagaMap result = coreOrderChangeService.exchReq(change);

			// 추가배송비 결제 이력 있으면 TB_PAYMENT 넣고 deliveryFee에 PAY_SQ UPDATE
			if(orderInfo.getExchangeInfo().getClaimDeliveryFeeDemandAmount() != null && orderInfo.getExchangeInfo().getClaimDeliveryFeeDemandAmount() > 0) {
				if (StringUtils.isNotBlank(orderInfo.getExchangeInfo().getClaimDeliveryFeePayMethod()) && orderInfo.getExchangeInfo().getClaimDeliveryFeePayMethod().contains("결제")) {
					if(StringUtils.isNotBlank(orderInfo.getExchangeInfo().getClaimDeliveryFeePayMeans())) {
						Payment payment = new Payment();
						payment.setOrdNo(Integer.parseInt(orderInfo.getProductOrder().getMerchantCustomCode1()));
						payment.setPayMeans(TscConstants.PayMeans.CREDIT_CARD.value());
						payment.setPayAmt(orderInfo.getExchangeInfo().getClaimDeliveryFeeDemandAmount());
						payment.setPayGb("D");
						payment.setPayStat(TscConstants.PaymentStat.PAYMENT_COMPLETE.value());
						payment.setPgGb(TscConstants.PgGb.NAVER_ORDER.value());
						payment.setPgTid(orderInfo.getOrder().getPaymentNumber());
						payment.setPgShopId(env.getProperty("naverPay.shop.id"));
						payment.setOrdChgSq(result.getInt("ordChgSq"));
						payment.setCardPcableYn("Y");
						payment.setEscrowYn("N");
						payment.setRegNo(TsbConstants.REG_NO);
						payment.setUpdNo(TsbConstants.REG_NO);

						coreOrderDao.insertPayment(payment);
						coreOrderDao.updateDeliveryFeePaySq(payment);

						log.info("::::: 네이버페이 교환 추가 배송비 결제 완료 등록 성공");
					}
				}
			}

			log.info("NAPAY_ORD_NO 교환 접수 성공 :::: {}", order.getNpayOrdDtlNo());
		}

		return null;
	}

	@Transactional("shopTxnManager")
	public Order cancelReqOrderInfo(ChangedProductOrderInfo[] changedProductOrderList) throws Exception {
		Order result = new Order();
		log.info("주문취소가 요청 된 건수 = " + changedProductOrderList.length);
		// 어드민 주문취소에 필요한 인자 세팅
		String cancelQty 		= "";
		String companyMngIdx 	= "";
		String localShipIdx 	= "";
		String soldoutCancelYn 	= "";
		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);

		int isChk, isChk2;
		Order orderInfo;
		if (productOrderInfo != null) {
			for (ProductOrderInfo info : productOrderInfo) {
				Order param = new Order();
				param.setOrdNo(Integer.parseInt(info.getProductOrder().getMerchantCustomCode1()));        // 주문번호
				param.setNpayOrdDtlNo(info.getProductOrder().getProductOrderID());        // 상품주문번호

				// 취소신청, 완료 정보 확인 (네이버페이 주문형은 수량취소 안되는것으로 확인)
				param.setPgGb(TscConstants.PgGb.NAVER_ORDER.value());
				isChk = naverPayDao.getOrdDtlCancelCheck(param);

				// 취소 반려된 데이터인지 확인
				param.setChgGb("COMPANION");        // 반려일 경우
				isChk2 = naverPayDao.getOrdDtlCancelCheck(param);

				// 취소 불가능한 상태인지 확인
				orderInfo = naverPayDao.getProductOrderIdInfo(param);

				if (isChk > 0) {
					log.info("이미 취소완료된 주문입니다.(ordNo) : " + param.getOrdNo() + " , (npayOrdDtlNo) : " + param.getNpayOrdDtlNo());
				} else if (isChk2 > 0) {
					log.info("이미 취소반려된 주문입니다.(ordNo) : " + param.getOrdNo() + " , (npayOrdDtlNo) : " + param.getNpayOrdDtlNo());
				} else if (!TscConstants.OrderDetailStat.PAYMENT_COMPLETE.value().equals(orderInfo.getOrdDtlStat()) && !TscConstants.OrderDetailStat.GOODS_PREPARE.value().equals(orderInfo.getOrdDtlStat()) && !TscConstants.OrderDetailStat.DELIVERY_PREPARE.value().equals(orderInfo.getOrdDtlStat())) {
					log.info("취소 불가능한 상태입니다.(ordNo) : " + param.getOrdNo() + " , (npayOrdDtlNo) : " + param.getNpayOrdDtlNo());
				} else {
					String changeReasonCd = info.getCancelInfo().getCancelReason().getValue();
					param.setChgMemo(info.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(info.getProductOrder().getProductID());
					param.setOptCd(info.getProductOrder().getProductOption());

					int[] dtlNoArr = {orderInfo.getOrdDtlNo()};            // 주문상세번호
					int[] cnclQtyArr = {orderInfo.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(0);                                            // 배치는 0
					change.setOrdDtlNoArr(dtlNoArr);                                // 주문상세번호배열
					change.setCnclRtnReqQtyArr(cnclQtyArr);                            // 취소수량배열
					coreOrderChangeService.cancelRequest(change);                        // 취소접수처리
				}
			}
		}

		return result;
	}

	/**
	 * 네이버페이 주문형 배송준비중 주문 정보 조회
	 * @param time
	 * @return Collection
	 * @author xodud1202
	 * @since  2021. 06. 14
	 */
	public Collection<Order> getReadyDeliveryList(Order time) {
		time.setPgGb(TscConstants.PgGb.NAVER_ORDER.value());
		time.setOrdDtlStat(TscConstants.OrderDetailStat.DELIVERY_PREPARE.value());
		return naverPayDao.getReadyDeliveryList(time);
	}

	/**
	 * 서명생성
	 * @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()); //서명정보 실패
		}
	}

	/**
	 * 네이버페이 주문형 배송준비중 주문 정보 조회
	 * @param params
	 * @return Order
	 * @author xodud1202
	 * @since  2021. 05. 28
	 */
	@Transactional("shopTxnManager")
	public Order sendNaverPayReadyDeliveryOrder(Collection<Order> params) throws Exception {
		Order result = new Order();
		try {
			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();

			PlaceProductOrderRequest placeProductOrderRequest 	= null;
			PlaceProductOrderResponse placeProductOrderResponse = null;

			String rcpNm 		= "";
			String rcpTel 		= "";
			String rcpFixAddr 	= "";
			String rcpDtlAddr 	= "";
			String rcpZipCode 	= "";

			int i = 0 ;
			for(Order param : params) {
				param.setAccessLicense(env.getProperty("naverPay.access.license"));
				param.setSecretKey(env.getProperty("naverPay.secret.key"));
				param.setMallCd(env.getProperty("naverPay.shop.id"));

				generateSignature("PlaceProductOrder", param.getSecretKey());

				byte[] encryptKey = SimpleCryptLib.generateKey(timeStamp, param.getSecretKey());

				accessCredentialsType.setAccessLicense(param.getAccessLicense());
				accessCredentialsType.setSignature(signature);
				accessCredentialsType.setTimestamp(timeStamp);

				placeProductOrderRequest = new PlaceProductOrderRequest();
				placeProductOrderRequest.setAccessCredentials(accessCredentialsType);
				placeProductOrderRequest.setDetailLevel("Full");
				placeProductOrderRequest.setVersion(env.getProperty("naverPay.version"));
				placeProductOrderRequest.setRequestID("");
				placeProductOrderRequest.setProductOrderID(String.valueOf(param.getNpayOrdDtlNo()));

				placeProductOrderResponse = stub.placeProductOrder(placeProductOrderRequest);

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

				//결과 출력
				if ("SUCCESS".equals(resultStr)) {
					//네이버페이에서 배송지 정보가 변경됐으면 주소를 변경해준다.
					if (placeProductOrderResponse.getIsReceiverAddressChanged() != null
							&& placeProductOrderResponse.getIsReceiverAddressChanged()) {

						String[] productOrderIdList = {String.valueOf(param.getNpayOrdDtlNo())};
						ProductOrderInfo[] productOrderInfo = productOrderInfoList(productOrderIdList);

						if(productOrderInfo != null){
							// TEST MALL_ID
							if("istyle24".equals(env.getProperty("naverPay.shop.id"))) {
								// 개발반영
								rcpNm 		= productOrderInfo[0].getProductOrder().getShippingAddress().getName();
								rcpTel 		= productOrderInfo[0].getProductOrder().getShippingAddress().getTel1();
								rcpFixAddr 	= productOrderInfo[0].getProductOrder().getShippingAddress().getBaseAddress();

								if (productOrderInfo[0].getProductOrder().getShippingAddress().getDetailedAddress() != null) {
									rcpDtlAddr = productOrderInfo[0].getProductOrder().getShippingAddress().getDetailedAddress();
								}
							} else {		// 운영 MALL_ID (istyle2424)
								//운영반영시 변경
								rcpNm 		= new String(SimpleCryptLib.decrypt(encryptKey,  productOrderInfo[i].getProductOrder().getShippingAddress().getName()), StandardCharsets.UTF_8);
								rcpTel 		= new String(SimpleCryptLib.decrypt(encryptKey,  productOrderInfo[i].getProductOrder().getShippingAddress().getTel1()), StandardCharsets.UTF_8);
								rcpFixAddr 	= new String(SimpleCryptLib.decrypt(encryptKey,  productOrderInfo[0].getProductOrder().getShippingAddress().getBaseAddress()), StandardCharsets.UTF_8);

								if (productOrderInfo[0].getProductOrder().getShippingAddress().getDetailedAddress() != null) {
									rcpDtlAddr = new String(SimpleCryptLib.decrypt(encryptKey,  productOrderInfo[0].getProductOrder().getShippingAddress().getDetailedAddress()), StandardCharsets.UTF_8);
								}
							}

							rcpZipCode = productOrderInfo[0].getProductOrder().getShippingAddress().getZipCode().replaceAll("-", "");

							Order addr = new Order();
							addr.setOrdDtlNo(param.getOrdDtlNo());
							addr.setRecipNm(rcpNm);
							addr.setRecipPhnno(rcpTel);
							addr.setRecipZipcode(rcpZipCode);
							addr.setRecipBaseAddr(rcpFixAddr);
							addr.setRecipDtlAddr(rcpDtlAddr);
							addr.setDelvMemo(productOrderInfo[i].getProductOrder().getShippingMemo());

							naverPayDao.updateShippingAddressInfo(addr);
						}
					}
				} else {
					log.info("배송준비중 송신 에러");
					log.info("주문번호 ===> " + param.getOrdNo());
					log.info("네이버상품주문번호 ===> " + param.getNpayOrdDtlNo());
					log.info("Code : " + placeProductOrderResponse.getError().getCode());
					log.info("Message : " + placeProductOrderResponse.getError().getMessage());
					log.info("Detail : " + placeProductOrderResponse.getError().getDetail());

					Order fail = new Order();
					fail.setErrorReason("배송준비중 송신 에러");
					fail.setOptCd("sendNaverPayReadyDeliveryOrder");
					fail.setOrdNo(param.getOrdNo());
					fail.setNpayOrdDtlNo(param.getNpayOrdDtlNo());
					fail.setResultCd(placeProductOrderResponse.getError().getCode());
					fail.setResultMsg(placeProductOrderResponse.getError().getMessage());
					fail.setMallCd(param.getMallCd());
					fail.setAccessLicense(param.getAccessLicense());
					fail.setSecretKey(param.getSecretKey());
					fail.setRegNo(TsbConstants.REG_NO);
					try {
						coreOrderDao.createNaverPayErrorLog(fail);
					} catch(Exception e) {
						e.printStackTrace();
					}
				}
				i++;
			}
		} catch (Exception e) {
			log.error("placeProductOrder() error: {} \n {}", e.getMessage(), e);
			throw new IllegalStateException(e.getMessage(), e);
		}
		return result;
	}

	@Transactional("shopTxnManager")
	public Order recvReturnReqOrder(ChangedProductOrderInfo[] changedProductOrderList) {
		Order result = new Order();
		try {
			String[] productOrderIdList = new String[changedProductOrderList.length];
			for(int i = 0 ; i < changedProductOrderList.length ; i++) {
				productOrderIdList[i] = changedProductOrderList[i].getProductOrderID();
			}

			ProductOrderInfo[] productOrderInfo = productOrderInfoList(productOrderIdList);

			byte[] encryptKey = SimpleCryptLib.generateKey(timeStamp, env.getProperty("naverPay.secret.key"));

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

				log.info("CHECK NPAY_ORD_DTL_NO ::::: {}", order.getNpayOrdDtlNo());

				// ClaimDeliveryFeeProductOrderIds > 네이버 상품주문번호 반품묶음.
				if(orderInfo.getReturnInfo() != null && StringUtils.isNotBlank(orderInfo.getReturnInfo().getClaimDeliveryFeeProductOrderIds())) {
					order.setClaimNpayOrdDtlNos(orderInfo.getReturnInfo().getClaimDeliveryFeeProductOrderIds().replaceAll(" ", "").split(","));
				} else {
					String[] npayOrdDtlNos = {orderInfo.getProductOrder().getProductOrderID()};
					order.setClaimNpayOrdDtlNos(npayOrdDtlNos);
				}

				Collection<Order> list = naverPayDao.getNotReturnOrderInfoList(order);

				int[] ordDtlNoArr, cnclRtnReqQtyArr;
				int custNo = 0;
				String ordNm = "", ordPhnno = "";
				if(list != null && list.size() > 0) {
					ordDtlNoArr = new int[list.size()];
					cnclRtnReqQtyArr = new int[list.size()];

					int i = 0;
					for(Order item : list) {
						ordDtlNoArr[i] = item.getOrdDtlNo();
						cnclRtnReqQtyArr[i] = item.getOrdQty();
						ordNm = item.getOrdNm();
						ordPhnno = item.getOrdPhnno();
						custNo = item.getCustNo();
					}
				} else {
					continue;
				}

				OrderChange change = new OrderChange();
				String changeReasonCode 		= orderInfo.getReturnInfo().getReturnReason().getValue();
				String collectDeliveryMethod;		// 직접반송
				if(orderInfo.getReturnInfo().getCollectDeliveryMethod() != null && !"RETURN_INDIVIDUAL".equals(orderInfo.getReturnInfo().getCollectDeliveryMethod().toString())) {
					collectDeliveryMethod = orderInfo.getReturnInfo().getCollectDeliveryMethod().toString();
					change.setChgerNm(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getReturnInfo().getCollectAddress().getName()), StandardCharsets.UTF_8));
					change.setChgerBaseAddr(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getReturnInfo().getCollectAddress().getBaseAddress()), StandardCharsets.UTF_8));
					change.setChgerPhnno(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getReturnInfo().getCollectAddress().getTel1()), StandardCharsets.UTF_8));
					if (orderInfo.getReturnInfo().getCollectAddress().getZipCode() != null) {
						change.setChgerZipcode(orderInfo.getReturnInfo().getCollectAddress().getZipCode().replaceAll("-", ""));
					}
					if (orderInfo.getReturnInfo().getCollectAddress().getDetailedAddress() != null) {
						change.setChgerDtlAddr(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getReturnInfo().getCollectAddress().getDetailedAddress()), StandardCharsets.UTF_8));
					}
				} else {
					collectDeliveryMethod	= "RETURN_INDIVIDUAL";		// 직접반송
					change.setChgerNm(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getProductOrder().getShippingAddress().getName()), StandardCharsets.UTF_8));
					change.setChgerBaseAddr(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getProductOrder().getShippingAddress().getBaseAddress()), StandardCharsets.UTF_8));
					change.setChgerPhnno(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getProductOrder().getShippingAddress().getTel1()), StandardCharsets.UTF_8));
					if (orderInfo.getProductOrder().getShippingAddress().getZipCode() != null) {
						change.setChgerZipcode(orderInfo.getProductOrder().getShippingAddress().getZipCode().replaceAll("-", ""));
					}
					if(StringUtils.isNotBlank(orderInfo.getProductOrder().getShippingAddress().getDetailedAddress())) {
						change.setChgerDtlAddr(new String(SimpleCryptLib.decrypt(encryptKey, orderInfo.getProductOrder().getShippingAddress().getDetailedAddress()), StandardCharsets.UTF_8));
					}
				}

				change.setOrdNo(order.getOrdNo());
				change.setCustNo(custNo);
				change.setOrdNm(ordNm);
				change.setOrdPhnno(ordPhnno);
				change.setRegNo(TsbConstants.REG_NO);
				change.setUpdNo(TsbConstants.REG_NO);
				change.setPgGb(TscConstants.PgGb.NAVER_ORDER.value());
				change.setChgMemo(orderInfo.getReturnInfo().getReturnDetailedReason());
				change.setWdInvoiceNo(orderInfo.getReturnInfo().getCollectTrackingNumber());
				change.setOrdDtlNoArr(ordDtlNoArr);
				change.setCnclRtnReqQtyArr(cnclRtnReqQtyArr);
				change.setWdTargetYn("N");			// 네이버페이 자체 회수 지시함

				if(orderInfo.getReturnInfo().getClaimDeliveryFeeDemandAmount() != null) {
					change.setAddPayCost(orderInfo.getReturnInfo().getClaimDeliveryFeeDemandAmount());
				}

				// 회수구분
				if ("RETURN_DESIGNATED".equals(collectDeliveryMethod)
						|| "RETURN_DELIVERY".equals(collectDeliveryMethod)) {
					change.setWdGb("W");		// 회수지시
				} else {
					change.setWdGb("D");		// 직접배송
				}

				// 구매의사 취소
				if ("INTENT_CHANGED".equals(changeReasonCode)) {
					change.setIsCustomer(true);
					change.setChgReason(TscConstants.OrderReturnReason.CHANGE_MIND.value());
				}
				// 색상 및 사이즈변경
				else if ("COLOR_AND_SIZE".equals(changeReasonCode)) {
					change.setIsCustomer(true);
					change.setChgReason(TscConstants.OrderReturnReason.CHANGE_MIND.value());
				}
				// 다른 상품 잘못 주문
				else if ("WRONG_ORDER".equals(changeReasonCode)) {
					change.setIsCustomer(true);
					change.setChgReason(TscConstants.OrderReturnReason.CHANGE_MIND.value());
				}
				// 서비스 불만족
				else if ("PRODUCT_UNSATISFIED".equals(changeReasonCode)) {
					change.setIsCustomer(true);
					change.setChgReason(TscConstants.OrderReturnReason.CHANGE_MIND.value());
				}
				// 상품정보 상이
				else if ("INCORRECT_INFO".equals(changeReasonCode)) {
					change.setIsCustomer(false);
					change.setChgReason(TscConstants.OrderReturnReason.INCORRECT_OPTION.value());
				}
				// 상품파손
				else if ("BROKEN".equals(changeReasonCode)) {
					change.setIsCustomer(false);
					change.setChgReason(TscConstants.OrderReturnReason.BROKEN.value());
				}
				// 오배송
				else if ("WRONG_DELIVERY".equals(changeReasonCode)) {
					change.setIsCustomer(false);
					change.setChgReason(TscConstants.OrderReturnReason.INCORRECT_DELV.value());
				}
				// 색상 등 다른 상품잘못 배송
				else if ("WRONG_OPTION".equals(changeReasonCode)) {
					change.setIsCustomer(false);
					change.setChgReason(TscConstants.OrderReturnReason.INCORRECT_DELV.value());
				}
				// 배송지연
				else if ("DELAYED_DELIVERY".equals(changeReasonCode)) {
					change.setIsCustomer(false);
					change.setChgReason(TscConstants.OrderReturnReason.DELAY_DELV.value());
				}
				// 배송누락
				else if("DROPPED_DELIVERY".equals(changeReasonCode)){
					change.setIsCustomer(false);
					change.setChgReason(TscConstants.OrderReturnReason.NOT_DELV_ALL.value());
				}

				GagaMap map = coreOrderChangeService.returnReq(change);
			}
		} catch(Exception e) {
			e.printStackTrace();
			throw new IllegalStateException(e.getMessage(), e);
		}
		return result;
	}

	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;
	}
}
