package com.jsowell.pile.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.google.common.collect.Lists;
import com.jsowell.adapay.vo.PaymentInfo;
import com.jsowell.common.constant.CacheConstants;
import com.jsowell.common.constant.Constants;
import com.jsowell.common.core.redis.RedisCache;
import com.jsowell.common.core.text.Convert;
import com.jsowell.common.enums.ykc.OrderPayModeEnum;
import com.jsowell.common.enums.ykc.OrderPayRecordEnum;
import com.jsowell.common.enums.ykc.PaymentInstitutionsEnum;
import com.jsowell.common.util.DateUtils;
import com.jsowell.common.util.StringUtils;
import com.jsowell.pile.domain.AdapayCallbackRecord;
import com.jsowell.pile.domain.OrderBasicInfo;
import com.jsowell.pile.domain.OrderPayRecord;
import com.jsowell.pile.domain.WxpayCallbackRecord;
import com.jsowell.pile.mapper.OrderPayRecordMapper;
import com.jsowell.pile.service.*;
import com.jsowell.pile.vo.web.OrderDetailInfoVO;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class OrderPayRecordServiceImpl implements OrderPayRecordService {

    @Resource
    private OrderPayRecordMapper orderPayRecordMapper;

    @Autowired
    private WxpayCallbackRecordService wxpayCallbackRecordService;

    @Autowired
    private AdapayCallbackRecordService adapayCallbackRecordService;

    @Autowired
    private MemberTransactionRecordService memberTransactionRecordService;

    @Autowired
    private OrderBasicInfoService orderBasicInfoService;

    @Autowired
    private RedisCache redisCache;


    @Override
    public int updateByPrimaryKeySelective(OrderPayRecord record) {
        return orderPayRecordMapper.updateByPrimaryKeySelective(record);
    }


    @Override
    public int batchInsert(List<OrderPayRecord> payRecordList) {
        if (CollectionUtils.isEmpty(payRecordList)) {
            return 0;
        }
        payRecordList = payRecordList.stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        for (OrderPayRecord orderPayRecord : payRecordList) {
            orderPayRecord.setCreateTime(new Date());
        }
        return orderPayRecordMapper.batchInsert(payRecordList);
    }

    @Override
    public List<OrderPayRecord> getOrderPayRecordList(String orderCode) {
        return orderPayRecordMapper.getOrderPayRecordList(orderCode);
    }

    @Override
    public List<PaymentInfo> queryPaymentInfosByOrderCode(String orderCode) {
        List<PaymentInfo> resultList = Lists.newArrayList();
        List<OrderPayRecord> orderPayRecordList = getOrderPayRecordList(orderCode);
        if (CollectionUtils.isNotEmpty(orderPayRecordList)) {
            for (OrderPayRecord orderPayRecord : orderPayRecordList) {
                List<PaymentInfo> paymentInfos = this.parseDeductionRecord(orderPayRecord.getDeductionRecord());
                resultList.addAll(paymentInfos);
            }
        }
        return resultList;
    }

    /**
     * 查询订单支付信息
     * 加缓存
     *
     * @param orderCode
     * @return
     */
    @Override
    public List<OrderDetailInfoVO.PayRecord> selectOrderPayInfoList(String orderCode) {
        // 缓存
        String redisKey = CacheConstants.SELECT_ORDER_PAY_INFO_LIST + orderCode;
        List<OrderDetailInfoVO.PayRecord> resultList = redisCache.getCacheList(redisKey);
        if (CollectionUtils.isNotEmpty(resultList)) {
            return resultList;
        }

        // 订单信息
        OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode);
        if (orderBasicInfo == null) {
            return Lists.newArrayList();
        }
        // 支付流水
        List<OrderPayRecord> orderPayRecordList = getOrderPayRecordList(orderCode);
        if (CollectionUtils.isEmpty(orderPayRecordList)) {
            return Lists.newArrayList();
        }
        List<OrderDetailInfoVO.PayRecord> payRecordList = Lists.newArrayList();
        for (OrderPayRecord orderPayRecord : orderPayRecordList) {
            OrderDetailInfoVO.PayRecord payInfo = new OrderDetailInfoVO.PayRecord();

            payInfo.setPayAmount(Convert.toStr(orderPayRecord.getPayAmount(), Constants.ZERO));
            payInfo.setPayStatus(orderBasicInfo.getPayStatus());
            // 支付时间取订单支付记录中的值，在创建时间和更新事件中取不为null并且最大的（注意历史数据有可能两个时间都为null）
            Date payTime = DateUtils.getMaxDate(orderPayRecord.getCreateTime(), orderPayRecord.getUpdateTime());
            if (Objects.isNull(payTime)) {
                payTime = orderBasicInfo.getPayTime();
            }
            payInfo.setPayTime(DateUtils.formatDateTime(payTime));
            payInfo.setRefundAmount(Convert.toStr(orderPayRecord.getRefundAmount(), Constants.ZERO));

            // 支付方式（1-本金余额支付；2-赠送余额支付；3-白名单支付；4-微信支付；5-支付宝支付）
            String payMode = orderPayRecord.getPayMode();
            if (StringUtils.equals(payMode, OrderPayRecordEnum.PRINCIPAL_BALANCE_PAYMENT.getValue())
                    || StringUtils.equals(payMode, OrderPayRecordEnum.GIFT_BALANCE_PAYMENT.getValue())) {
                // 使用余额支付
                payInfo.setPayMode(OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue());
                String payModeDesc = null;
                if (StringUtils.isNotBlank(OrderPayRecordEnum.getPayModeDescription(payMode))) {
                    payModeDesc = OrderPayRecordEnum.getPayModeDescription(payMode);
                } else {
                    payModeDesc = OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue();
                }
                payInfo.setPayModeDesc(payModeDesc);
            } else if (StringUtils.equals(payMode, OrderPayRecordEnum.WECHATPAY_PAYMENT.getValue())) {
                // 使用微信支付
                payInfo.setPayMode(OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue());
                payInfo.setPayModeDesc(OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getLabel());

                // 判断是微信支付还是汇付支付
                String paymentInstitutions = orderPayRecord.getAcquirer();
                if (StringUtils.equals(paymentInstitutions, PaymentInstitutionsEnum.WECHAT_PAY.getValue())) {
                    // 查微信支付回调记录
                    WxpayCallbackRecord wxpayCallbackRecord = wxpayCallbackRecordService.selectByOrderCode(orderCode);
                    if (wxpayCallbackRecord != null) {
                        payInfo.setOutTradeNo(wxpayCallbackRecord.getOutTradeNo());
                        payInfo.setTransactionId(wxpayCallbackRecord.getTransactionId());
                    }
                } else if (StringUtils.equals(paymentInstitutions, PaymentInstitutionsEnum.ADAPAY.getValue())) {
                    List<PaymentInfo> paymentInfos = parseDeductionRecord(orderPayRecord.getDeductionRecord());
                    // 查询汇付支付回调
                    // AdapayCallbackRecord adapayCallbackRecord = adapayCallbackRecordService.selectByOrderCode(orderCode);
                    AdapayCallbackRecord adapayCallbackRecord = adapayCallbackRecordService.selectByPaymentId(paymentInfos.get(0).getPaymentId());
                    if (adapayCallbackRecord != null) {
                        payInfo.setOutTradeNo(adapayCallbackRecord.getPaymentId());
                        payInfo.setTransactionId(adapayCallbackRecord.getOutTransId());
                    }
                }
            } else if (StringUtils.equals(payMode, OrderPayRecordEnum.WHITELIST_PAYMENT.getValue())) {
                // 使用白名单支付
                payInfo.setPayMode(OrderPayModeEnum.PAYMENT_OF_WHITELIST.getValue());
                payInfo.setPayModeDesc(OrderPayModeEnum.PAYMENT_OF_WHITELIST.getLabel());
            }
            payRecordList.add(payInfo);
        }
        redisCache.setCacheList(redisKey, payRecordList);
        redisCache.expire(redisKey, CacheConstants.cache_expire_time_1d);
        return payRecordList;
    }

    /**
     * 解析deductionRecord
     * 【公共方法】
     */
    @Override
    public List<PaymentInfo> parseDeductionRecord(String deductionRecord) {
        List<PaymentInfo> resultList = Lists.newArrayList();
        if (StringUtils.isBlank(deductionRecord)) {
            return resultList;
        }
        Object object = JSON.parse(deductionRecord);

        // 都放入list里
        String s = JSON.toJSONString(object);
        if (object instanceof JSONArray) {
            List<PaymentInfo> paymentInfos = JSON.parseArray(s, PaymentInfo.class);
            resultList.addAll(paymentInfos);
        } else {
            PaymentInfo paymentInfo = JSON.parseObject(s, PaymentInfo.class);
            resultList.add(paymentInfo);
        }
        return resultList;
    }

    @Override
    public List<String> parsePaymentIdByDeductionRecord(String deductionRecord) {
        List<String> resultList = Lists.newArrayList();
        List<PaymentInfo> paymentInfos = parseDeductionRecord(deductionRecord);
        if (CollectionUtils.isNotEmpty(paymentInfos)) {
            resultList = paymentInfos.stream().map(PaymentInfo::getPaymentId).collect(Collectors.toList());
        }
        return resultList;
    }

    @Override
    public void updateRefundAmount(String orderCode, String paymentId, BigDecimal refundAmt) {
        List<OrderPayRecord> orderPayRecordList = getOrderPayRecordList(orderCode);
        for (OrderPayRecord orderPayRecord : orderPayRecordList) {
            List<PaymentInfo> paymentInfos = parseDeductionRecord(orderPayRecord.getDeductionRecord());
            for (PaymentInfo paymentInfo : paymentInfos) {
                if (StringUtils.equals(paymentId, paymentInfo.getPaymentId())) {
                    orderPayRecord.setRefundAmount(refundAmt);
                    updateByPrimaryKeySelective(orderPayRecord);
                }
            }
        }
    }

    @Override
    public int insertSelective(OrderPayRecord record) {
        return orderPayRecordMapper.insertSelective(record);
    }

    @Override
    public OrderPayRecord selectByPrimaryKey(Integer id) {
        return orderPayRecordMapper.selectByPrimaryKey(id);
    }

    @Override
    public int updateBatch(List<OrderPayRecord> list) {
        return orderPayRecordMapper.updateBatch(list);
    }

    @Override
    public int insertOrUpdate(OrderPayRecord record) {
        return orderPayRecordMapper.insertOrUpdate(record);
    }

    @Override
    public int insertOrUpdateSelective(OrderPayRecord record) {
        return orderPayRecordMapper.insertOrUpdateSelective(record);
    }
}

