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

import com.diaoyun.zion.chinafrica.constant.KeyConstant;
import com.diaoyun.zion.chinafrica.dao.TbCfFinanceDao;
import com.diaoyun.zion.chinafrica.dao.TbCfIssueCouponDao;
import com.diaoyun.zion.chinafrica.dao.TbCfOrderDao;
import com.diaoyun.zion.chinafrica.entity.TbCfFinanceEntity;
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.FlutterWaveService;
import com.diaoyun.zion.chinafrica.vo.FlutterWaveCard;
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.HttpClientUtil;
import com.diaoyun.zion.master.util.IdUtil;
import com.github.theresasogunle.CardCharge;
import com.github.theresasogunle.Environment;
import com.github.theresasogunle.RaveConstant;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
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 java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Auther: wudepeng
 * @Date: 2019/11/09
 * @Description: FlutterWave支付
 */
@Service("flutterWaveService")
@Transactional
public class FlutterWaveServiceImpl implements FlutterWaveService {
    @Autowired
    private TbCfFinanceDao tbCfFinanceDao;
    @Autowired
    private TbCfOrderDao tbCfOrderDao;
    @Autowired
    private TbCfIssueCouponDao tbCfIssueCouponDao;
    @Autowired
    private DomainProperties domainProperties;
    @Resource
    private RedisCache<Object> orderRedisCache;
    private static Logger logger = LoggerFactory.getLogger(FlutterWaveServiceImpl.class);

    //退款API
    private String FLUTTERWAVE_REFUND_URL = "https://api.ravepay.co/gpx/merchant/transactions/refund";

    /**
     * 使用卡号支付
     *
     * @param orderId
     * @param flutterWaveCard
     * @return
     */
    @Override
    public Result payForOrder(String orderId, FlutterWaveCard flutterWaveCard) {
        RaveConstant.PUBLIC_KEY = domainProperties.getProperty("flutterwave.public.key");
        RaveConstant.SECRET_KEY = domainProperties.getProperty("flutterwave.secret.key");
        RaveConstant.ENVIRONMENT = Environment.STAGING; //or live
        Result result = new Result();
        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;
        }
        if (tbCfOrderVo != null) {
            try {
                String orderPrice = tbCfOrderVo.getRealityPay().toString();
                CardCharge ch = new CardCharge();
                ch.setCardno(flutterWaveCard.getCard())
                        .setCvv(flutterWaveCard.getCvv())
                        .setCurrency("USD")
                        .setCountry("NG")
                        .setAmount(orderPrice)
                        .setExpiryyear(flutterWaveCard.getYear())
                        .setExpirymonth(flutterWaveCard.getMonth())
                        .setEmail(flutterWaveCard.getEmail())
                        .setTxRef("Afri-shop" + new Date().getTime());
                JSONObject chargevisa = ch.chargeVisaAndIntl();
                //if timeout, poll
                //JSONObject pollvisa = ch.chargeVisaAndIntl(true);
                System.out.println("======>>>>"+chargevisa);
                net.sf.json.JSONObject object = net.sf.json.JSONObject.fromObject(chargevisa.toString());
                String status = object.getString("status");
                //System.out.println("========>>>" + status);
                if ("success".equals(status)) {
                    net.sf.json.JSONObject data = object.getJSONObject("data");
                    String paymentId = data.getString("paymentId");
                    String authurl = data.getString("authurl");
                    String url = authurl.split(". ")[0];
                    changeOrderState(paymentId, tbCfOrderVo);
                    //修改优惠券状态
                    if (tbCfOrderVo.getCouponId() != null && tbCfOrderVo.getPayStatus() == 20) {
                        tbCfIssueCouponDao.changeCoupnStatus(tbCfOrderVo.getUserId(), tbCfOrderVo.getCouponId());
                    }
                    //生成支付流水
                    TbCfFinanceEntity finance = createFinance(paymentId, url, tbCfOrderVo);
                    TbCfFinanceVo tbCfFinanceVo = new TbCfFinanceVo();
                    BeanUtils.copyProperties(finance, tbCfFinanceVo);
                    result.setData(chargevisa).setMessage("Pay for success!");
                    logger.info(tbCfOrderVo.getUserName() + ":Pay for success! The order number is:" + tbCfOrderVo.getOrderId());
                    //清除订单
                    removeRedisCache(tbCfOrderVo);
                } else {
                    result.setCode(ResultCodeEnum.ORDER_PAY_ERROR.getCode()).setMessage("payment failure!");
                    logger.error(tbCfOrderVo.getUserName() + ":payment failure! The order number is:" + tbCfOrderVo.getOrderId());
                }
            } catch (Exception e) {
                result.setCode(ResultCodeEnum.ORDER_PAY_ERROR.getCode()).setMessage(e.getMessage());
                logger.error(e.getMessage(), e);
                return result;
            }
        } else {
            result.setMessage("Order does not exist!");
            result.setCode(ResultCodeEnum.ORDER_PAY_ERROR.getCode());
        }
        return result;
    }

    /**
     * 退款
     *
     * @param flutterWaveCard
     * @return
     */
    @Override
    public Result refund(FlutterWaveCard flutterWaveCard) {
        Result result = new Result();
        RaveConstant.SECRET_KEY = domainProperties.getProperty("flutterwave.secret.key");
        Map<String, Object> params = new HashMap<>();
        params.put("ref", flutterWaveCard.getRef());
        params.put("seckey", RaveConstant.SECRET_KEY);
        if (flutterWaveCard.getAmount() != null) {
            params.put("amount", flutterWaveCard.getAmount());
        }
        try {
            String post = HttpClientUtil.sendPostWithBodyParameter(FLUTTERWAVE_REFUND_URL, params);
            net.sf.json.JSONObject object = net.sf.json.JSONObject.fromObject(post);
            System.out.println(object.getString("status"));
            String status = object.getString("status");
            if ("success".equals(status)) {
                result.setData(object).setMessage("Refund success!");
                logger.info("Refund success!");
            } else {
                result.setCode(ResultCodeEnum.REFUND_PAY_ERROR.getCode()).setMessage("Refund failure!");
            }
        } catch (IOException e) {
            result.setCode(ResultCodeEnum.REFUND_PAY_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) {
        //更改订单状态
        TbCfOrderEntity tbCfOrder = new TbCfOrderEntity();
        tbCfOrder.setOrderId(oldOrder.getOrderId());
        tbCfOrder.setUpdateTime(new Date());
        tbCfOrder.setDealTime(new Date());
        tbCfOrder.setOrderStatus(OrderStatusEnum.PAID.getValue());
        tbCfOrder.setDeliveryFlag(DeliveryStatusEnum.PROCESSING.getValue());
        tbCfOrder.setPayId(payId);
        tbCfOrder.setPayStatus(OrderStatusEnum.PAID.getValue());
        tbCfOrderDao.update(tbCfOrder);
    }

    /**
     * 记录财务流水
     *
     * @param
     * @param tbCfOrderVo
     */
    private TbCfFinanceEntity createFinance(String paymentId, String url, TbCfOrderVo tbCfOrderVo) {
        TbCfFinanceEntity tbCfFinance = new TbCfFinanceEntity();
        tbCfFinance.setOrderId(tbCfOrderVo.getOrderId());
        tbCfFinance.setFinaceId(IdUtil.createIdbyUUID());
        tbCfFinance.setPayAccount(tbCfOrderVo.getRealityPay());
        tbCfFinance.setPayId(paymentId);
        tbCfFinance.setPayTime(new Date());
        tbCfFinance.setReceiptUrl(url);
        tbCfFinance.setPayWayCode("flutterwave");
        tbCfFinance.setUserId(tbCfOrderVo.getUserId());
        tbCfFinanceDao.save(tbCfFinance);
        return tbCfFinance;
    }
}
