package com.diaoyun.zion.chinafrica.service.impl;

import com.diaoyun.zion.chinafrica.constant.KeyConstant;
import com.diaoyun.zion.chinafrica.dao.*;
import com.diaoyun.zion.chinafrica.entity.TbCfFinanceEntity;
import com.diaoyun.zion.chinafrica.entity.TbCfItemOrderREntity;
import com.diaoyun.zion.chinafrica.entity.TbCfOrderEntity;
import com.diaoyun.zion.chinafrica.enums.DeliveryStatusEnum;
import com.diaoyun.zion.chinafrica.enums.OrderStatusEnum;
import com.diaoyun.zion.chinafrica.service.PayPalService;
import com.diaoyun.zion.chinafrica.vo.PayPalResult;
import com.diaoyun.zion.chinafrica.vo.TbCfFinanceVo;
import com.diaoyun.zion.chinafrica.vo.TbCfOrderVo;
import com.diaoyun.zion.master.base.Result;
import com.diaoyun.zion.master.common.RedisCache;
import com.diaoyun.zion.master.config.DomainProperties;
import com.diaoyun.zion.master.enums.ResultCodeEnum;
import com.diaoyun.zion.master.util.IdUtil;
import com.diaoyun.zion.master.util.JsoupUtil;
import com.egzosn.pay.common.api.PayService;
import com.egzosn.pay.common.bean.PayOrder;
import com.egzosn.pay.common.bean.RefundOrder;
import com.egzosn.pay.paypal.api.PayPalConfigStorage;
import com.egzosn.pay.paypal.api.PayPalPayService;
import com.egzosn.pay.paypal.bean.PayPalTransactionType;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

@Service("payPalService")
@Transactional
public class PayPalServiceImpl implements PayPalService {
    @Autowired
    private TbCfFinanceDao tbCfFinanceDao;
    @Autowired
    private DomainProperties domainProperties;
    @Resource
    private RedisCache<Object> orderRedisCache;
    private static Logger logger = LoggerFactory.getLogger(TbCfOrderServiceImpl.class);
    @Autowired
    private TbCfOrderDao tbCfOrderDao;
    @Autowired
    private TbCfIssueCouponDao tbCfIssueCouponDao;
    @Autowired
    private TbCfToiCouponDao tbCfToiCouponDao;
    @Autowired
    private TbCfItemOrderRDao tbCfItemOrderRDao;
    private String ORDER_ID = "";

    @Override
    public Result payForOrder(String orderId) {
        ORDER_ID = orderId;
        PayPalConfigStorage storage = new PayPalConfigStorage();
        Result result = new Result();
        storage.setClientID(domainProperties.getProperty("paypal.client.app"));
        storage.setClientSecret(domainProperties.getProperty("paypal.client.secret"));
        //发起付款后的页面转跳地址
        storage.setTest(true);
        storage.setReturnUrl(domainProperties.getProperty("paypal.success.url"));
        //取消按钮转跳地址,这里用异步通知地址的兼容的做法
        storage.setNotifyUrl(domainProperties.getProperty("paypal.cancel.url"));

        PayService service = new PayPalPayService(storage);
        TbCfOrderVo tbCfOrderVo = (TbCfOrderVo) orderRedisCache.get(KeyConstant.ORDER_DET + orderId);
        TbCfOrderEntity orderEntity = tbCfOrderDao.queryObject(orderId);
        //判断这个订单是否已支付
        if (orderEntity != null && OrderStatusEnum.PAID.getValue().equals(orderEntity.getPayStatus())) {
            result.setMessage("Order paid");
            result.setCode(ResultCodeEnum.ORDER_PAY_ERROR.getCode());
            return result;
        }
        try {
            if (tbCfOrderVo != null) {
                BigDecimal realityPay = tbCfOrderVo.getRealityPay();
                PayOrder order = new PayOrder("Order_payment:", "tbCfOrderVo.getUserName()+\"'s order,the total price is $\"+tbCfOrderVo.getRealityPay()", realityPay, UUID.randomUUID().toString().replace("-", ""), PayPalTransactionType.sale);
                Map orderInfo = service.orderInfo(order);
                Map<String, String> orderHref = JsoupUtil.getOrderHref(orderInfo.toString());
                System.out.println(orderHref.get("approval_url"));
                String url = orderHref.get("approval_url");
                PayPalResult palResult = new PayPalResult();
                palResult.setOrderId(orderId);
                palResult.setPayId((String) orderInfo.get("id"));
                palResult.setPaypalUrl(url);
                palResult.setOrderDesc(tbCfOrderVo.getUserName() + "'s order,the total price is $" + tbCfOrderVo.getRealityPay());
                result.setData(palResult);

            } else {
                result.setMessage("Order does not exist");
                result.setCode(ResultCodeEnum.ORDER_PAY_ERROR.getCode());
            }
        } catch (Exception e) {
            result.setCode(ResultCodeEnum.ORDER_PAY_ERROR.getCode()).setMessage(e.getMessage());
            logger.error(e.getMessage(), e);
            return result;
        }
        return result;
    }

    @Override
    public Result payForSuccess(HttpServletRequest request) {
        TbCfOrderVo tbCfOrderVo = (TbCfOrderVo) orderRedisCache.get(KeyConstant.ORDER_DET + ORDER_ID);
        Result result = new Result();
        PayPalConfigStorage storage = new PayPalConfigStorage();
        storage.setClientID(domainProperties.getProperty("paypal.client.app"));
        storage.setClientSecret(domainProperties.getProperty("paypal.client.secret"));
        storage.setTest(true);
        PayService service = new PayPalPayService(storage);
        Map<String, Object> params = null;

        try {
            params = service.getParameter2Map(request.getParameterMap(), request.getInputStream());
            String payerID = (String) params.get("PayerID");
            String paymentId = (String) params.get("paymentId");
            String token = (String) params.get("token");
            if (service.verify(params)) {
                System.out.println("pay success");
                result.setMessage("pay success");
                logger.info(tbCfOrderVo.getUserName() + ":Pay for success! The order number is:" + tbCfOrderVo.getOrderId());
            } else {
                result.setCode(ResultCodeEnum.ORDER_PAY_ERROR.getCode()).setMessage("Payment Failed");
                logger.error(tbCfOrderVo.getUserName() + ":payment failure! The order number is:" + tbCfOrderVo.getOrderId());
            }
            if (ORDER_ID != null) {

                if (tbCfOrderVo != null) {
                    //修改订单状态
                    changeOrderState(paymentId, tbCfOrderVo);
                    //修改优惠券状态
                    if (tbCfOrderVo.getCouponId() != null && "20".equals(tbCfOrderVo.getPayStatus())) {
                        tbCfToiCouponDao.changeCoupnStatus(tbCfOrderVo.getUserId(), tbCfOrderVo.getCouponId());
                    }
                    //生成支付流水
                    TbCfFinanceEntity finance = createFinance(paymentId, token, payerID, tbCfOrderVo);
                    TbCfFinanceVo tbCfFinanceVo = new TbCfFinanceVo();
                    BeanUtils.copyProperties(finance, tbCfFinanceVo);
                    //清除订单
                    removeRedisCache(tbCfOrderVo);
                }
            }

        } catch (IOException e) {
            result.setCode(ResultCodeEnum.ORDER_PAY_ERROR.getCode()).setMessage(e.getMessage());
            logger.error(e.getMessage(), e);
            return result;
        }
        return result;

    }

    /**
     * 退款
     *
     * @param orderId
     * @param payId
     * @return
     */
    @Override
    public Result refund(String payId, String orderId) {
        Result result = new Result();
        PayPalConfigStorage storage = new PayPalConfigStorage();
        storage.setClientID(domainProperties.getProperty("paypal.client.app"));
        storage.setClientSecret(domainProperties.getProperty("paypal.client.secret"));
        storage.setTest(true);

        try {
            PayService service = new PayPalPayService(storage);
            TbCfOrderEntity tbCfOrderEntity = tbCfOrderDao.queryObject(orderId);
            RefundOrder order = new RefundOrder();
            order.setDescription("退款");
            order.setTradeNo(payId);
            order.setRefundAmount(tbCfOrderEntity.getTotalPrice());
            Map resultMap = service.refund(order);
            result.setData(resultMap).setCode(1).setMessage("退款成功");
        } catch (Exception e) {
            result.setCode(ResultCodeEnum.SERVICE_ERROR.getCode()).setMessage(e.getMessage());
            logger.error(e.getMessage(), e);
            return result;
        }
        return result;
    }

    /**
     * 清空订单缓存
     *
     * @param tbCfOrderVo
     */
    private void removeRedisCache(TbCfOrderVo tbCfOrderVo) {
        orderRedisCache.delete(KeyConstant.ORDER_DET + tbCfOrderVo.getOrderId());
        String couponId = "";
        if (StringUtils.isNotBlank(tbCfOrderVo.getCouponId())) {
            couponId = tbCfOrderVo.getCouponId();
        }
        String orderIdAndCouponId = tbCfOrderVo.getOrderId() + ":" + tbCfOrderVo.getUserId() + ":" + couponId;
        orderRedisCache.delete(KeyConstant.ORDER_EXP + orderIdAndCouponId);
    }

    /**
     * 修改订单状态
     *
     * @param payId
     * @param oldOrder
     */
    private void changeOrderState(String payId, TbCfOrderVo oldOrder) {
        //更改订单状态
        TbCfItemOrderREntity itemOrderR = new TbCfItemOrderREntity();
        itemOrderR.setOrderId(oldOrder.getOrderId());
        itemOrderR.setUpdateTime(new Date());
        itemOrderR.setOrderStatus(OrderStatusEnum.PAID.getValue());
        itemOrderR.setDeliveryFlag(DeliveryStatusEnum.PROCESSING.getValue());
        tbCfItemOrderRDao.updates(itemOrderR);
        TbCfOrderEntity tbCfOrder = new TbCfOrderEntity();
        tbCfOrder.setOrderId(oldOrder.getOrderId());
        tbCfOrder.setUpdateTime(new Date());
        tbCfOrder.setDealTime(new Date());
        tbCfOrder.setPayId(payId);
        tbCfOrder.setOrderStatus(OrderStatusEnum.PAID.getValue());
        tbCfOrder.setPayStatus(OrderStatusEnum.PAID.getValue());
        tbCfOrderDao.update(tbCfOrder);
    }

    /**
     * 记录财务流水
     *
     * @param
     * @param tbCfOrderVo
     */
    private TbCfFinanceEntity createFinance(String paymentId, String token, String payerId, TbCfOrderVo tbCfOrderVo) {
        TbCfFinanceEntity tbCfFinance = new TbCfFinanceEntity();
        String successUrl = domainProperties.getProperty("paypal.success.url");
        String receiptUrl = successUrl + "?paymentId=" + paymentId + "&token=" + token + "&PayerID=" + payerId;
        tbCfFinance.setOrderId(tbCfOrderVo.getOrderId());
        tbCfFinance.setFinaceId(IdUtil.createIdbyUUID());
        tbCfFinance.setPayAccount(tbCfOrderVo.getRealityPay());
        tbCfFinance.setPayId(paymentId);
        tbCfFinance.setPayTime(new Date());
        tbCfFinance.setReceiptUrl(receiptUrl);
        tbCfFinance.setPayWayCode("paypal");
        tbCfFinance.setUserId(tbCfOrderVo.getUserId());
        tbCfFinanceDao.save(tbCfFinance);
        return tbCfFinance;
    }
}
