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

import com.alibaba.fastjson.JSON;
import com.diaoyun.zion.chinafrica.constant.KeyConstant;
import com.diaoyun.zion.chinafrica.dao.TbCfFinanceDao;
import com.diaoyun.zion.chinafrica.dao.TbCfItemOrderRDao;
import com.diaoyun.zion.chinafrica.dao.TbCfOrderDao;
import com.diaoyun.zion.chinafrica.dao.TbCfToiCouponDao;
import com.diaoyun.zion.chinafrica.entity.*;
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.service.TbCfUserInfoService;
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.*;

/**
 * @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 TbCfToiCouponDao tbCfToiCouponDao;
    @Autowired
    private TbCfItemOrderRDao tbCfItemOrderRDao;

    @Autowired
    private TbCfUserInfoService tbCfUserInfoService;
    @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";

    //校验API
    private String VERIFY_PAY_URL = "https://api.ravepay.co/flwv3-pug/getpaidx/api/v2/verify";
    //测试API
    //private String VERIFY_PAY_URL = "https://ravesandboxapi.flutterwave.com/flwv3-pug/getpaidx/api/v2/verify";

    /**
     * 使用卡号支付(预支付)
     *
     * @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.LIVE; //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(orderId);
                JSONObject chargevisa = ch.chargeVisaAndIntl();
                result.setData(chargevisa);
            } 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 orderId
     * @return
     */
    @Override
    public Result verifyPay(String orderId) {
        Result result = new Result();
        try {
            TbCfOrderVo tbCfOrderVo = (TbCfOrderVo) orderRedisCache.get(KeyConstant.ORDER_DET + orderId);
            Map<String, Object> map = new HashMap<>();
            map.put("txref", orderId);
            map.put("SECKEY", domainProperties.getProperty("flutterwave.secret.key"));
            String data = HttpClientUtil.sendPostWithBodyParameter(VERIFY_PAY_URL, map);
            com.alibaba.fastjson.JSONObject object = JSON.parseObject(data);
            String statusFlag = object.getString("status");
            com.alibaba.fastjson.JSONObject results = object.getJSONObject("data");
            String status = results.getString("status");
            String paymentid = results.getString("paymentid");
            String authurl = results.getString("authurl");
            if ("success".equalsIgnoreCase(statusFlag) && "successful".equalsIgnoreCase(status)) {
                //支付成功
                if (tbCfOrderVo != null) {
                    changeOrderState(paymentid, tbCfOrderVo);
                    //修改优惠券状态
                    if (tbCfOrderVo.getCouponId() != null && OrderStatusEnum.PAID.getValue().equals(tbCfOrderVo.getOrderStatus())) {
                        tbCfToiCouponDao.changeCoupnStatus(tbCfOrderVo.getUserId(), tbCfOrderVo.getCouponId());
                    }
                    //生成支付流水
                    TbCfFinanceEntity finance = createFinance(paymentid, authurl, tbCfOrderVo);
                    TbCfFinanceVo tbCfFinanceVo = new TbCfFinanceVo();
                    BeanUtils.copyProperties(finance, tbCfFinanceVo);

                    //清空订单
                    removeRedisCache(tbCfOrderVo);
                }
                result.setData(JSON.parseObject(data));
                result.setCode(ResultCodeEnum.SUCCESS.getCode()).setMessage("payment success!");
                logger.info(tbCfOrderVo.getUserName() + ":Pay for success! The order number is:" + tbCfOrderVo.getOrderId());
            } else {
                result.setData(JSON.parseObject(data));
                //支付失败
                result.setCode(ResultCodeEnum.ORDER_PAY_ERROR.getCode()).setMessage("payment failure!");
                logger.error(tbCfOrderVo.getUserName() + ":Pay for success! The order number is:" + tbCfOrderVo.getOrderId());
            }
        } catch (Exception e) {
            result.setCode(ResultCodeEnum.VALIDATE_ERROR.getCode()).setMessage(e.getMessage());
            logger.error(e.getMessage(), e);
            return result;
        }
        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);
            com.alibaba.fastjson.JSONObject object = JSON.parseObject(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;
    }

    @Override
    public Result queryParams(String userId) {
        Result result = new Result();
        List<TbCfUserInfoEntity> list = new ArrayList<>();
        FlutterKey key = new FlutterKey();
        String public_key = domainProperties.getProperty("flutterwave.public.key");
        TbCfUserInfoEntity userInfo = tbCfUserInfoService.queryObject(userId);
        list.add(userInfo);
        key.setPublic_key(public_key);
        key.setUserInfo(list);
        result.setData(key).setMessage(ResultCodeEnum.SUCCESS.getDesc());
        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 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;
    }
}
