package com.style24.core.biz.service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

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 org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import com.style24.core.biz.dao.TscOrderDao;
import com.style24.core.biz.thirdparty.KakaoPayApi;
import com.style24.core.support.env.TscConstants;
import com.style24.core.support.message.TscMessageByLocale;
import com.style24.persistence.domain.KakaoPay;
import com.style24.persistence.domain.Order;
import com.style24.persistence.domain.Payment;

import lombok.extern.slf4j.Slf4j;

/**
 * 카카오페이 Service
 * 
 * @author card007
 * @since 2020. 03. 03
 */
@Service
@Slf4j
public class TscKakaoPayService {

	@Autowired
	private Environment env;

	@Autowired
	private TscMessageByLocale message;

	@Autowired
	private KakaoPayApi kakaoPayApi;

	@Autowired
	private TscOrderDao orderDao;

	/**
	 * 카카오페이 결제준비 처리
	 * 
	 * @param Order
	 * @return KakaoPay
	 * @author card007
	 * @since 2021. 03. 03
	 */
	@Transactional("shopTxnManager")
	public KakaoPay kakaoPaymentReady(Order order) {
		// API 전송 URL 설정
		String paymentReadyUrl = env.getProperty("kakao.paymentReadyUrl");

		// Redirect URL 설정
		String hasSsl = env.getProperty("has-ssl");
		String protocol;
		
		if ("true".equals(hasSsl)) {
			protocol = "https:";
		} else {
			protocol = "http:";
		}
		String approvalUrl = protocol + env.getProperty("domain.front") + env.getProperty("kakao.paymentRedirectUrl");
		String failUrl = protocol + env.getProperty("domain.front") + env.getProperty("kakao.paymentRedirectUrl");
		String cancelUrl = protocol + env.getProperty("domain.front") + env.getProperty("kakao.paymentRedirectUrl");

		if (!TscConstants.FrontGb.PC.value().equals(order.getFrontGb())) {
			failUrl = protocol + env.getProperty("domain.front") + "/order/payment/fail";
			cancelUrl = protocol + env.getProperty("domain.front") + "/order/payment/fail";
		}

		// API 파라메터 설정
		MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
		params.add("cid", env.getProperty("kakao.cid"));
		params.add("partner_order_id", order.getOrdNo()+"");
		params.add("partner_user_id", order.getCustNo()+"");
		params.add("item_name", order.getGoodsNm());
		params.add("quantity", order.getOrdGoodsQty()+"");
		params.add("total_amount", order.getPayAmt()+"");
		params.add("tax_free_amount", "0");
		params.add("approval_url", approvalUrl);
		params.add("fail_url", failUrl);
		params.add("cancel_url", cancelUrl);

		// 카카오페이 API 전송
		return kakaoPayApi.kakaoPaymentApi(params, paymentReadyUrl);
	}

	/**
	 * 카카오페이 승인 처리
	 *
	 * @param Payment
	 * @return Payment
	 * @author card007
	 * @since 2021. 03. 04
	 */
	@Transactional("shopTxnManager")
	public Payment approveKakaoPayment(Payment payment) {
		// API 전송 URL 설정
		String approvePaymentUrl = env.getProperty("kakao.approvePaymentUrl");

		// API 파라메터 설정
		MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
		params.add("cid", env.getProperty("kakao.cid"));
		params.add("tid", payment.getPgTid());
		params.add("partner_order_id", payment.getPartnerOrderId());
		params.add("partner_user_id", payment.getPartnerUserId());
		params.add("pg_token", payment.getPgToken());

		// 카카오페이 API 전송
		KakaoPay kakaoPay = kakaoPayApi.kakaoPaymentApi(params, approvePaymentUrl);

		// 카카오페이 API 전송 결과 처리
		int statusCode = kakaoPay.getStatusCode();

		// 승인 성공일때 200
		if (statusCode == 200) {
			payment.setPgTradeNo(kakaoPay.getAid());
			payment.setPgTid(kakaoPay.getTid());
			payment.setPgShopId(kakaoPay.getCid());
			payment.setPayDt(convertDateFormat(kakaoPay.getApproved_at()));
			payment.setPayStat(TscConstants.PaymentStat.PAYMENT_COMPLETE.value());
			payment.setOrdNo(Integer.parseInt(kakaoPay.getPartner_order_id()));
			payment.setCustNo(Integer.parseInt(kakaoPay.getPartner_user_id()));
			payment.setKakaoMethodType(kakaoPay.getPayment_method_type());
			payment.setPayAmt(kakaoPay.getAmount().getTotal());
			payment.setNpayPntAmt(kakaoPay.getAmount().getPoint());
			payment.setKakaoDiscount(kakaoPay.getAmount().getDiscount());

			// 카카오페이 카드결제 시 카드정보 설정
			if ("CARD".equals(kakaoPay.getPayment_method_type())) {
				payment.setCardKind(kakaoPay.getCard_info().getPurchase_corp());
				payment.setCardCd(kakaoPay.getCard_info().getIssuer_corp_code());
				payment.setCardNm(kakaoPay.getCard_info().getIssuer_corp());
				payment.setCardType("신용".equals(kakaoPay.getCard_info().getCard_type()) ? "N" : "Y");
				payment.setCardMips(kakaoPay.getCard_info().getInstall_month());
				payment.setPayMeans(TscConstants.PayMeans.CREDIT_CARD.value());
			} else if ("MONEY".equals(kakaoPay.getPayment_method_type())) {
				payment.setPayMeans(TscConstants.PayMeans.KAKAO_MONEY.value());
			}

			// 결제금액과 사용포인트금액이 같으면 카카오포인트 결제 처리
			if (kakaoPay.getAmount().getPoint() == kakaoPay.getAmount().getTotal()) {
				payment.setPayMeans(TscConstants.PayMeans.KAKAO_POINT.value());
			}

			payment.setResCd(String.valueOf(statusCode));
			payment.setResMsg("성공적으로 처리되었습니다.");
		} else {
			String resultMessage = kakaoPay.getExtras().getMethod_result_message();
			throw new IllegalStateException(resultMessage);
		}

		return payment;
	}

	private String convertDateFormat(String date) {
		String result = "";
		try {
			SimpleDateFormat parseSdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
			SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
			Date parseDate = parseSdf.parse(date);
			result = sdf.format(parseDate);
		} catch (ParseException e) {
			e.printStackTrace();
		}

		return result;
	}

	/**
	 * 카카오페이 주문 조회
	 *
	 * @param Payment
	 * @return KakaoPay
	 * @author card007
	 * @since 2021. 03. 04
	 */
	@Transactional("shopTxnManager")
	public KakaoPay getKakaoPaymentOrder(Payment payment) {
		// API 전송 URL 설정
		String paymentOrderUrl = env.getProperty("kakao.paymentOrderUrl");

		// API 파라메터 설정
		MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
		params.add("cid", env.getProperty("kakao.cid"));
		params.add("tid", payment.getPgTid());

		// 카카오페이 API 전송
		KakaoPay pay = kakaoPayApi.kakaoPaymentApi(params, paymentOrderUrl);

		return pay;
	}

	/**
	 * 카카오페이 결제 취소
	 *
	 * @param Payment
	 * @return Payment
	 * @author card007
	 * @since 2021. 03. 05
	 */
	@Transactional("shopTxnManager")
	public Payment cancelKakaoPayment(Payment payment) {
		// API 전송 URL 설정
		String cancelPaymentUrl = env.getProperty("kakao.cancelPaymentUrl");

		// API 파라메터 설정
		MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
		params.add("cid", env.getProperty("kakao.cid"));
		params.add("tid", payment.getPgTid());
		params.add("cancel_amount", String.valueOf(payment.getPayAmt()));
		params.add("cancel_tax_free_amount", "0");
		params.add("cancel_available_amount", String.valueOf(payment.getLeftAmt()));

		// 카카오페이 API 전송
		KakaoPay kakaoPay = kakaoPayApi.kakaoPaymentApi(params, cancelPaymentUrl);

		// 카카오페이 API 전송 결과 처리
		int statusCode = kakaoPay.getStatusCode();

		// 승인 성공일때 200
		if (statusCode == 200) {
			payment.setPgTradeNo(kakaoPay.getAid());
			payment.setPgTid(kakaoPay.getTid());
			payment.setPgShopId(kakaoPay.getCid());
			payment.setStatus(kakaoPay.getStatus());
			payment.setOrdNo(Integer.parseInt(kakaoPay.getPartner_order_id()));
			payment.setCustNo(Integer.parseInt(kakaoPay.getPartner_user_id()));
			payment.setKakaoMethodType(kakaoPay.getPayment_method_type());
			payment.setPayAmt(kakaoPay.getApproved_cancel_amount().getTotal() * -1);
			payment.setNpayPntAmt(kakaoPay.getApproved_cancel_amount().getPoint() * -1);
			payment.setResCd(String.valueOf(statusCode));
			payment.setResMsg("성공적으로 처리되었습니다.");

			// orderDao.insertPayment(payment);
			orderDao.insertPaymentCancel(payment);
		} else {
			// int code = Integer.parseInt(kakaoPay.getCode());
			// String msg = kakaoPay.getMsg();
			// String resultCode = kakaoPay.getExtras().getMethod_result_code();
			String resultMessage = kakaoPay.getExtras().getMethod_result_message();

			throw new IllegalStateException(resultMessage);
			// payment.setResCd(String.valueOf(code));
			// payment.setResMsg(resultMessage);
		}

		return payment;
	}

	/**
	 * 카카오페이 결제 데이터 생성
	 *
	 * @param KakaoPay, Order
	 * @return Payment
	 * @author card007
	 * @since 2021. 03. 09
	 */
	public Payment setKakaoOrderData(KakaoPay kakaoPay, Order order) {
		Payment payment = new Payment();
		payment.setPgTid(kakaoPay.getTid());
		payment.setPartnerOrderId(String.valueOf(order.getOrdNo()));
		payment.setPartnerUserId(String.valueOf(order.getCustNo()));
		payment.setNextRedirectAppUrl(kakaoPay.getNext_redirect_app_url());
		payment.setNextRedirectMobileUrl(kakaoPay.getNext_redirect_mobile_url());
		payment.setNextRedirectPcUrl(kakaoPay.getNext_redirect_pc_url());
		payment.setAndroidAppScheme(kakaoPay.getAndroid_app_scheme());
		payment.setIosAppScheme(kakaoPay.getIos_app_scheme());

		return payment;
	}

	/**
	 * 카카오페이 결제 처리 후 로직 진행 중 에러 발생으로 인한 취소처리
	 * 
	 * @param Payment
	 * @author card007
	 * @since 2021. 04. 09
	 */
	public void kakaoPayRollBack(Payment payment) {
		payment.setPayStat(TscConstants.PaymentStat.DB_FAIL.value());
		payment.setPayGb("E");

		cancelKakaoPayment(payment);
	}
}
