package com.zhongshu.card.server.core.service.payment;

import cn.hutool.json.JSONObject;
import com.github.microservice.net.ResultContent;
import com.github.microservice.pay.client.model.ledger.TransactionLogModel;
import com.github.microservice.pay.client.ret.ResultState;
import com.github.microservice.types.OrderState;
import com.github.microservice.types.payment.PaymentType;
import com.zhongshu.card.client.model.operLogs.OperationLogsAddParam;
import com.zhongshu.card.client.model.pay.SatInfoModel;
import com.zhongshu.card.client.model.payment.ExpenseRefundParam;
import com.zhongshu.card.client.type.LogsLevel;
import com.zhongshu.card.client.type.MessageType;
import com.zhongshu.card.client.type.RefundState;
import com.zhongshu.card.client.type.payment.OrderNoType;
import com.zhongshu.card.client.type.payment.SettlementState;
import com.zhongshu.card.client.utils.DateUtils;
import com.zhongshu.card.client.utils.PayExceptionToShowUtil;
import com.zhongshu.card.server.core.dao.payment.ExpenseFlowDao;
import com.zhongshu.card.server.core.dao.payment.PaymentProcessDao;
import com.zhongshu.card.server.core.domain.org.Organization;
import com.zhongshu.card.server.core.domain.paySetting.ProjectMainPaySetting;
import com.zhongshu.card.server.core.domain.paySetting.ProjectOrgPaySettingInfo;
import com.zhongshu.card.server.core.domain.payment.ExpenseFlow;
import com.zhongshu.card.server.core.domain.payment.PaymentProcess;
import com.zhongshu.card.server.core.domain.payment.RefundRecord;
import com.zhongshu.card.server.core.domain.schedule.ScheduleTaskConfig;
import com.zhongshu.card.server.core.model.pay.UnionFrictionlessPayFinishModel;
import com.zhongshu.card.server.core.service.base.CommonService;
import com.zhongshu.card.server.core.service.base.SuperService;
import com.zhongshu.card.server.core.service.orgManager.ProjectBindOrgServiceImpl;
import com.zhongshu.card.server.core.service.pay.BalancePayService;
import com.zhongshu.card.server.core.service.pay.ChinaumsSenselessPayService;
import com.zhongshu.card.server.core.service.pay.SettleService;
import com.zhongshu.card.server.core.service.paySetting.PayOrderSettingService;
import com.zhongshu.card.server.core.service.paySetting.ProjectMainPaySettingService;
import com.zhongshu.card.server.core.service.user.OperationLogsService;
import com.zhongshu.card.server.core.util.NextNoUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author TRX
 * @date 2024/10/24
 */
@Service
@Slf4j
public class PayCallService extends SuperService {

    @Autowired
    private OperationLogsService operationLogsService;

    @Autowired
    private BalancePayService balancePayService;

    @Autowired
    ExpenseFlowDao expenseFlowDao;

    @Autowired
    private PaymentProcessDao paymentProcessDao;

    @Autowired
    private ProjectBindOrgServiceImpl projectBindOrgService;

    @Autowired
    private SettleService settleService;

    @Autowired
    private PayOrderSettingService payOrderSettingService;

    @Autowired
    private ChinaumsSenselessPayService chinaumsSenselessPayService;

    @Autowired
    private CommonService commonService;

    @Autowired
    private OrderNoInfoService orderNoInfoService;

    @Autowired
    private RefundRecordService refundRecordService;

    @Autowired
    private ProjectMainPaySettingService projectMainPaySettingService;

    /**
     * 统一调用支付服务
     *
     * @param entity
     * @return
     */
    public ResultContent payOrder(ExpenseFlow entity) {
        OrderState orderType = entity.getOrderState();
        if (orderType != OrderState.WAIT_PAYMENT) {
            return ResultContent.buildFail(String.format("订单不能支付：%s", orderType.getRemark()));
        }

        StopWatch stopWatch = new StopWatch();
        stopWatch.start("1");
        // 得到用户所有的支付渠道，依次尝试扣款
        ResultContent<List<PaymentType>> resultContent = payOrderSettingService.getUserPayment(entity.getUserId(), entity.getProjectOid());
        if (resultContent.isFailed()) {
            String msg = resultContent.getMsg();
            entity.setPayFailed(msg);
            expenseFlowDao.save(entity);
            return ResultContent.buildFail(msg);
        }
        stopWatch.stop();


        List<PaymentType> paymentTypes = resultContent.getContent();
        if (ObjectUtils.isEmpty(paymentTypes)) {
            String msg = "用户暂无开启支付渠道";
            entity.setPayFailed(msg);
            expenseFlowDao.save(entity);
            return ResultContent.buildFail(msg);
        }

        String paymentNo = entity.getPaymentNo();
        log.info("开始时间：{}", DateUtils.paresTime(System.currentTimeMillis(), DateUtils.patternyyyySSS));
        log.info("渠道： {} {}", paymentTypes, paymentNo);

        String payError = "支付失败";
        int maxTime = 5 * 1000;
        int stepTime = 110;
        boolean b = false;
        for (PaymentType paymentType : paymentTypes) {
            entity = expenseFlowDao.findTopById(entity.getId());
            entity.setPaymentType(paymentType);
            if (paymentType == PaymentType.UserWallet) {
                // 钱包支付
                stopWatch.start("钱包支付");
                balancePay(entity);
                stopWatch.stop();
            } else if (paymentType == PaymentType.UnionFrictionlessPay) {
                // 银联云闪付
                unionFrictionlessPay(entity);
            }

            if (paymentType.isPayIsAsync()) {
                AtomicInteger atomicInteger = new AtomicInteger(0);
                while (atomicInteger.get() <= maxTime) {
                    boolean isPaying = orderIsPaying(paymentNo, paymentType);
                    log.info("等待：{} 支付中：{} {}", atomicInteger.get(), isPaying, paymentType);
                    if (!isPaying) {
                        entity = expenseFlowDao.findTopById(entity.getId());
                        break;
                    }
                    try {
                        TimeUnit.MILLISECONDS.sleep(stepTime);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    atomicInteger.addAndGet(stepTime);
                }
            }

            // 支付成功
            if (entity.getIsPaySuccess() != null && entity.getIsPaySuccess()) {
                b = true;
                break;
            }
        }

        log.info("支付： {}", b);
        // 所有的渠道都支付失败
        if (!b && paymentTypes.size() > 1) {
            entity.setPaymentStatus("支付失败");
            entity.setIsPaySuccess(Boolean.FALSE);
            entity.setPayRemark(payError);
            entity.setOrderState(OrderState.PAID_ERROR);
            entity.setIsPaid(Boolean.TRUE);
            expenseFlowDao.save(entity);
        }
        log.info("支付过程： {}", stopWatch.prettyPrint());
        return ResultContent.buildSuccess();
    }

    /**
     * 钱包支付
     *
     * @param entity
     * @return
     */
    public ResultContent balancePay(ExpenseFlow entity) {
        log.info("开始钱包支付");
        String desc = "消费";
        // 日志
        OperationLogsAddParam logsAddParam = initLog(entity.getUserId());
        logsAddParam.setTitle(desc);
        logsAddParam.setDataId(entity.getPaymentNo());

        // 支付记录
        PaymentProcess paymentProcess = new PaymentProcess();
        paymentProcess.setPaymentNo(entity.getPaymentNo());
        paymentProcess.setExpenseFlow(entity);
        paymentProcess.setPaymentType(PaymentType.UserWallet);
        paymentProcess.setPayStartTime(System.currentTimeMillis());

        entity.setPayStartTime(System.currentTimeMillis());
        // 封装分账信息

        com.github.microservice.pay.client.ret.ResultContent<List<TransactionLogModel>> resultContent = balancePayService.balancePay(entity.getProjectOid(), entity.getShopOid(), entity.getUserId(), entity.getPayAmount(), entity.getPaymentNo(), entity.getRemark());
        if (resultContent.getState() == com.github.microservice.pay.client.ret.ResultState.Success) {
            // 关联参数
            String msg = "支付成功";
            List<TransactionLogModel> list = resultContent.getContent();
            entity.setTransactionIds(list);
            entity.setPaymentStatus(msg);
            entity.setIsPaySuccess(Boolean.TRUE);
            entity.setPayRemark(msg);
            entity.setOrderState(OrderState.HAVE_PAID);

            // 日志
            logsAddParam.setMessageType(MessageType.Info);
            logsAddParam.setLevel(LogsLevel.Low);
            logsAddParam.setContent(msg);

            // 支付记录
            paymentProcess.setIsPaySuccess(Boolean.TRUE);
            paymentProcess.setPayRemark(msg);
            paymentProcess.setPayEndTime(System.currentTimeMillis());
            paymentProcess.setPayMillis(paymentProcess.getPayEndTime() - paymentProcess.getPayStartTime());
            paymentProcess.setTimeStr(DateUtils.paresTime(System.currentTimeMillis(), DateUtils.FORMAT_LONG));

            // 记录订单的现在支付类型
            orderNoInfoService.saveInfo(entity.getPaymentNo(), OrderNoType.Pay, entity.getPaymentType());
        } else {
            String msg = resultContent.getMsg();
            if (StringUtils.isNotEmpty(msg) && msg.contains("Connection reset")) {
                msg = "调用支付中心失败";
            } else if (resultContent.getException() != null) {
                String cls = resultContent.getException().getCls();
                msg = PayExceptionToShowUtil.convertException(cls);
                if (cls.contains("UncategorizedMongoDbException") && entity.getRepeatTime() <= 1) {
                    // 如果是并发引起的问题，则重复一次
                    entity.setRepeatTime(entity.getRepeatTime() + 1);
                    paymentProcess.setIsPaySuccess(Boolean.FALSE);
                    paymentProcess.setPayRemark(msg);
                    paymentProcess.setPayEndTime(System.currentTimeMillis());
                    paymentProcess.setPayMillis(paymentProcess.getPayEndTime() - paymentProcess.getPayStartTime());
                    paymentProcess.setTimeStr(DateUtils.paresTime(System.currentTimeMillis(), DateUtils.FORMAT_LONG));
                    paymentProcessDao.save(paymentProcess);
                    return balancePay(entity);
                }
            }
            if (StringUtils.isEmpty(msg)) {
                msg = "支付中心调用失败";
            }
            entity.setPaymentStatus(msg);
            entity.setIsPaySuccess(Boolean.FALSE);
            entity.setPayRemark(msg);
            entity.setOrderState(OrderState.PAID_ERROR);

            // 支付记录流程
            paymentProcess.setIsPaySuccess(Boolean.FALSE);
            paymentProcess.setPayRemark(msg);
            paymentProcess.setPayEndTime(System.currentTimeMillis());

            // 日志
            logsAddParam.setMessageType(MessageType.Warn);
            logsAddParam.setLevel(LogsLevel.Middle);
            logsAddParam.setContent(msg);
        }
        // 保存日志
        operationLogsService.addLog(logsAddParam);

        entity.setPayEndTime(System.currentTimeMillis());
        entity.setPayMillis(entity.getPayEndTime() - entity.getPayStartTime());
        expenseFlowDao.save(entity);

        paymentProcess.setIsPaying(Boolean.FALSE);
        paymentProcess.setPayMillis(paymentProcess.getPayEndTime() - paymentProcess.getPayStartTime());
        paymentProcess.setTimeStr(DateUtils.paresTime(System.currentTimeMillis(), DateUtils.FORMAT_LONG));
        paymentProcessDao.save(paymentProcess);
        return ResultContent.buildSuccess();
    }

    /**
     * 银联 云闪付
     *
     * @param entity
     * @return
     */
    public ResultContent unionFrictionlessPay(ExpenseFlow entity) {
        log.info("开始云闪付支付");

        // 记录当前订单类型
        orderNoInfoService.saveInfo(entity.getPaymentNo(), OrderNoType.Pay, entity.getPaymentType());

        String desc = "消费";
        OperationLogsAddParam logsAddParam = initLog(entity.getUserId());
        logsAddParam.setTitle(desc);
        logsAddParam.setDataId(entity.getPaymentNo());

        PaymentProcess paymentProcess = new PaymentProcess();
        paymentProcess.setPaymentNo(entity.getPaymentNo());
        paymentProcess.setExpenseFlow(entity);
        paymentProcess.setPaymentType(PaymentType.UnionFrictionlessPay);
        paymentProcess.setPayStartTime(System.currentTimeMillis());
        paymentProcess.setIsPaying(Boolean.TRUE); // 支付中

        entity.setPayStartTime(System.currentTimeMillis());
        BigDecimal payAmount = entity.getPayAmount();
        payAmount = payAmount.stripTrailingZeros();

        log.info("开始支付时间：{}", DateUtils.paresTime(System.currentTimeMillis(), DateUtils.patternyyyySSS));
        List<SatInfoModel> satInfoModel = buildShare(entity, paymentProcess.getPaymentType());
        com.github.microservice.net.ResultContent resultContent = chinaumsSenselessPayService.senselessPay(
                entity.getProjectOid(), entity.getShopOid(), entity.getUserId(),
                payAmount, entity.getPaymentNo(), entity.getRemark(), satInfoModel);
        if (resultContent.getState() == com.github.microservice.net.ResultState.Success) {
            // 关联参数
            String msg = "支付中";
            entity.setPaymentStatus(msg);
            entity.setPayRemark(msg);
            entity.setOrderState(OrderState.PAY_IN_PROGRESS);

            // 日志
            logsAddParam.setMessageType(MessageType.Info);
            logsAddParam.setLevel(LogsLevel.Low);
            logsAddParam.setContent(msg);
        } else {
            String msg = resultContent.getMsg();
            if (StringUtils.isNotEmpty(msg) && msg.contains("Connection reset")) {
                msg = "调用支付中心失败";
            } else {
                if (resultContent.getException() != null) {
                    String cls = resultContent.getException().getCls();
                    msg = PayExceptionToShowUtil.convertException(cls);
                }
            }
            if (StringUtils.isEmpty(msg)) {
                msg = "支付中心失败";
            }
            entity.setPaymentStatus(msg);
            entity.setIsPaySuccess(Boolean.FALSE);
            entity.setPayRemark(msg);
            entity.setOrderState(OrderState.PAID_ERROR);

            // 日志
            logsAddParam.setMessageType(MessageType.Warn);
            logsAddParam.setLevel(LogsLevel.Middle);
            logsAddParam.setContent(msg);

            // 支付记录
            paymentProcess.setIsPaySuccess(Boolean.FALSE);
            paymentProcess.setPayRemark(msg);
            paymentProcess.setIsPaying(Boolean.FALSE);
            log.info("支付失败： {}", msg);
        }
        // 保存日志
        operationLogsService.addLog(logsAddParam);

        entity.setPayEndTime(System.currentTimeMillis());
        entity.setPayMillis(entity.getPayEndTime() - entity.getPayStartTime());
        expenseFlowDao.save(entity);

        // 支付产品日志
        paymentProcess.setPayEndTime(System.currentTimeMillis());
        paymentProcess.setPayMillis(paymentProcess.getPayEndTime() - paymentProcess.getPayStartTime());
        paymentProcess.setTimeStr(DateUtils.paresTime(System.currentTimeMillis(), DateUtils.FORMAT_LONG));
        paymentProcessDao.save(paymentProcess);
        return ResultContent.buildSuccess();
    }

    /**
     * 银联云闪付支付完成
     *
     * @param param
     * @return
     */
    public ResultContent unionFrictionlessPayFinish(UnionFrictionlessPayFinishModel param) {
        log.info("支付回调时间：{}", DateUtils.paresTime(System.currentTimeMillis(), DateUtils.patternyyyySSS));
        String paymentNo = param.getMerOrderId();
        com.github.microservice.pay.client.ret.ResultContent<List<TransactionLogModel>> resultContent = param.getTransactionLogModelList();
        String state = param.getStatus();
        String targetOrderId = param.getTargetOrderId();

        if (StringUtils.isEmpty(paymentNo)) {
            return ResultContent.buildFail("paymentNo为空");
        }
        orderNoInfoService.markSuccess(paymentNo);
        log.info("云闪付支付回调： {}", paymentNo);
        ExpenseFlow entity = expenseFlowDao.findTopByPaymentNo(paymentNo);
        PaymentProcess paymentProcess = paymentProcessDao.findTopByPaymentNoAndPaymentTypeOrderByCreateTimeDesc(paymentNo, PaymentType.UnionFrictionlessPay);
        if (ObjectUtils.isNotEmpty(entity)) {
            if (state.equals("TRADE_SUCCESS")) {
                entity.setOrderState(OrderState.HAVE_PAID);
                entity.setIsPaySuccess(Boolean.TRUE);
                entity.setPayRemark("支付成功");
                entity.setPaymentStatus("支付成功");
                entity.setIsPaid(Boolean.TRUE);
                JSONObject payResult = new JSONObject();
                payResult.set("targetOrderId", targetOrderId);
                entity.setPayResult(payResult);

                paymentProcess.setIsPaySuccess(Boolean.TRUE);
                paymentProcess.setPayRemark("支付成功");
                paymentProcess.setIsPaying(Boolean.FALSE);
                if (resultContent.getState() == ResultState.Success) {
                    List<TransactionLogModel> list = resultContent.getContent();
                    entity.setTransactionIds(list);
                }
            } else {
                entity.setOrderState(OrderState.PAID_ERROR);
                entity.setIsPaySuccess(Boolean.FALSE);
                entity.setPayRemark("支付失败");
                entity.setPaymentStatus("支付失败");

                paymentProcess.setIsPaySuccess(Boolean.FALSE);
                paymentProcess.setPayRemark("支付失败");
                paymentProcess.setIsPaying(Boolean.FALSE);
            }
            // 订单数据
            expenseFlowDao.save(entity);
            // 订单支付流程数据
            paymentProcessDao.save(paymentProcess);
        }
        return ResultContent.buildSuccess();
    }

    /**
     * 订单是否在支付中
     *
     * @param paymentNo
     * @param paymentType
     * @return
     */
    public boolean orderIsPaying(String paymentNo, PaymentType paymentType) {
        PaymentProcess paymentProcess = paymentProcessDao.findTopByPaymentNoAndPaymentTypeOrderByCreateTimeDesc(paymentNo, paymentType);
        if (ObjectUtils.isNotEmpty(paymentProcess) && paymentProcess.getIsPaying() != null && paymentProcess.getIsPaying()) {
            return true;
        }
        return false;
    }

    /**
     * 查询余额
     *
     * @param entity
     * @return
     */
    public BigDecimal queryBalance(ExpenseFlow entity) {
        BigDecimal balance = BigDecimal.ZERO;
        if (entity.getPaymentType() == null || entity.getPaymentType() == PaymentType.UserWallet) {
            com.github.microservice.pay.client.ret.ResultContent<Long> resultContent = balancePayService.queryUserBalance(entity.getProjectOid(), entity.getUserId());
            if (resultContent.getState() == com.github.microservice.pay.client.ret.ResultState.Success) {
                long number = resultContent.getContent();
                balance = BigDecimal.valueOf(number);
            } else {
                log.info("查询余额queryBalance失败： {}", resultContent.getMsg());
            }
        }
        return balance;
    }

    /**
     * 退款
     *
     * @param entity
     * @return
     */
    public ResultContent refund(ExpenseFlow entity, ExpenseRefundParam param) {
        if (ObjectUtils.isEmpty(entity)) {
            return ResultContent.buildFail("数据为空");
        }

        if (entity.getPaymentType() == PaymentType.UserWallet) {
            // 钱包退款
            return walletRefund(entity, param);
        } else if (entity.getPaymentType() == PaymentType.UnionFrictionlessPay) {
            // 云闪付退款
            return unionFrictionlessPayRefund(entity, param);
        }
        return ResultContent.buildFail("不支持退款");
    }

    /**
     * 钱包退款
     *
     * @param entity
     * @return
     */
    public ResultContent walletRefund(ExpenseFlow entity, ExpenseRefundParam param) {
        String refundNo = NextNoUtil.getNextPaymentNo("RE");
        entity.setRefundNo(refundNo);
        orderNoInfoService.saveInfo(refundNo, OrderNoType.Refund, entity.getPaymentType());

        // 退款记录
        RefundRecord refundRecord = new RefundRecord();
        refundRecord.setPaymentNo(entity.getPaymentNo());
        // 申请人
        refundRecord.setApplicant(getCurrentUserId());
        BigDecimal payAmount = entity.getPayAmount();
        refundRecord.setRefundAMount(payAmount);
        refundRecord.setRefundTime(System.currentTimeMillis());
        refundRecord.setRefundRemark(param.getRemark());
        refundRecord.setRefundNo(refundNo);
        refundRecord.setProjectOid(entity.getProjectOid());
        refundRecord.setPaymentType(entity.getPaymentType());

        com.github.microservice.pay.client.ret.ResultContent<List<TransactionLogModel>> resultContent = balancePayService.refund(entity.getProjectOid(), entity.getShopOid(), entity.getUserId(), refundNo, payAmount, param.getRemark());
        if (resultContent.getState() == com.github.microservice.pay.client.ret.ResultState.Success) {
            entity.setIsRefund(Boolean.TRUE);
            entity.setRefundRemark(param.getRemark());
            entity.setRefundTime(System.currentTimeMillis());

            List<TransactionLogModel> list = resultContent.getContent();
            if (ObjectUtils.isNotEmpty(list)) {
                entity.setRefundTransactionIds(list);
            }
            // 申请人
            entity.setApplicant(getCurrentUserId());
            // 退款人
            entity.setRefundUserId(getCurrentUserId());
            // 退款金额
            entity.setRefundAMount(entity.getPayAmount());
            // 订单状态
            entity.setOrderState(OrderState.REFUNDED);
            // 退款状态
            entity.setRefundState(RefundState.Refunded);
            entity.setRefuseRemark("退款成功");
            expenseFlowDao.save(entity);

            // 保存退款记录
            refundRecord.setRefundUserId(getCurrentUserId());
            refundRecord.setExamineTime(System.currentTimeMillis());
            refundRecord.setRefuseRemark("退款成功");
            refundRecord.setRefundState(RefundState.Refunded);
            refundRecord.setRefundTransactionIds(list);
            refundRecordService.saveEntity(refundRecord);
            return ResultContent.buildSuccess();
        } else {
            refundRecord.setRefundUserId(getCurrentUserId());
            refundRecord.setExamineTime(System.currentTimeMillis());
            refundRecord.setRefuseRemark(resultContent.getMsg());
            refundRecord.setRefundState(RefundState.Fail);
            refundRecordService.saveEntity(refundRecord);
            return ResultContent.buildFail(String.format("退款失败：%s", resultContent.getMsg()));
        }
    }

    /**
     * 云闪付开始退款
     *
     * @param entity
     * @param param
     * @return
     */
    public ResultContent unionFrictionlessPayRefund(ExpenseFlow entity, ExpenseRefundParam param) {
        String refundNo = NextNoUtil.getNextPaymentNo("RE");
        entity.setRefundNo(refundNo);
        String paymentNo = entity.getPaymentNo();
        log.info("支付清单号：{} 退款：{}", paymentNo, refundNo);
        orderNoInfoService.saveInfo(paymentNo, OrderNoType.Refund, entity.getPaymentType());
        JSONObject payResult = entity.getPayResult();
        String targetOrderId = payResult.getStr("targetOrderId");

        BigDecimal payAmount = entity.getPayAmount();
        payAmount = payAmount.stripTrailingZeros();
        ResultContent<UnionFrictionlessPayFinishModel> resultContent = chinaumsSenselessPayService.refund(entity.getProjectOid(), entity.getShopOid(), entity.getUserId(), payAmount, paymentNo, refundNo, param.getRemark(), targetOrderId);

        // 退款记录
        RefundRecord refundRecord = new RefundRecord();
        refundRecord.setPaymentNo(entity.getPaymentNo());
        // 申请人
        refundRecord.setApplicant(getCurrentUserId());
        refundRecord.setRefundAMount(payAmount);
        refundRecord.setRefundTime(System.currentTimeMillis());
        refundRecord.setRefundRemark(param.getRemark());
        refundRecord.setRefundNo(refundNo);
        refundRecord.setProjectOid(entity.getProjectOid());
        refundRecord.setPaymentType(entity.getPaymentType());

        if (resultContent.isSuccess()) {
            UnionFrictionlessPayFinishModel model = resultContent.getContent();
            String refundStatus = "PROCESSING";
            if (ObjectUtils.isNotEmpty(model)) {
                refundStatus = model.getRefundStatus();
            }

            if ("SUCCESS".equals(refundStatus)) {
                // 成功
                entity.setIsRefund(Boolean.TRUE);
                entity.setRefundState(RefundState.Refunded);
                entity.setRefuseRemark("退款成功");
                entity.setOrderState(OrderState.REFUNDED);
                if (model.getTransactionLogModelList() != null) {
                    entity.setRefundTransactionIds(model.getTransactionLogModelList().getContent());
                    refundRecord.setRefundTransactionIds(model.getTransactionLogModelList().getContent());
                }

                refundRecord.setRefuseRemark("退款成功");
                refundRecord.setRefundState(RefundState.Refunded);
            } else if ("PROCESSING".equals(refundStatus)) {
                // 进行中
                entity.setIsRefund(Boolean.FALSE);
                entity.setRefundState(RefundState.Refunding);
                entity.setRefuseRemark("退款中");

                refundRecord.setRefuseRemark("退款中");
                refundRecord.setRefundState(RefundState.Refunding);
            } else if ("FAIL".equals(refundStatus)) {
                // 失败
                entity.setIsRefund(Boolean.FALSE);
                entity.setRefundState(RefundState.Fail);
                entity.setRefuseRemark("退款失败");

                refundRecord.setRefuseRemark("退款失败");
                refundRecord.setRefundState(RefundState.Fail);
            }

            entity.setRefundRemark(param.getRemark());
            entity.setRefundTime(System.currentTimeMillis());
            // 申请人
            entity.setApplicant(getCurrentUserId());
            // 退款人
            entity.setRefundUserId(getCurrentUserId());
            // 退款金额
            entity.setRefundAMount(payAmount);
            expenseFlowDao.save(entity);

            // 保存退款记录
            refundRecord.setRefundUserId(getCurrentUserId());
            refundRecord.setExamineTime(System.currentTimeMillis());
            refundRecordService.saveEntity(refundRecord);

            return ResultContent.buildSuccess(resultContent.getContent());
        } else {
            // 失败
            refundRecord.setRefundUserId(getCurrentUserId());
            refundRecord.setExamineTime(System.currentTimeMillis());
            refundRecord.setRefuseRemark(resultContent.getMsg());
            refundRecord.setRefundState(RefundState.Fail);
            refundRecordService.saveEntity(refundRecord);
            return ResultContent.buildFail(String.format("退款失败：%s", resultContent.getMsg()));
        }
    }

    /**
     * 银联云闪付 退款回调
     *
     * @param param state
     *              NEW_ORDER 新订单" +
     *              "UNKNOWN 不明确的交易状态" +
     *              "TRADE_CLOSED 在指定时间段内未支付时关闭的交易；在交易完成撤销成功时关闭的交易；支付失败的交易;TRADE_CLOSED的交易不允许进行任何操作" +
     *              "WAIT_BUYER_PAY 交易创建，等待买家付款" +
     *              "TRADE_SUCCESS 支付成功" +
     *              "TRADE_REFUND 订单转入退货流程,退货可能是部分也可能是全部"
     * @return
     */
    public ResultContent unionFrictionlessPayRefundFinish(UnionFrictionlessPayFinishModel param) {
        log.info("回调云闪付退款回调: {}", param.getRefundOrderId());
        String paymentNo = param.getMerOrderId();
        com.github.microservice.pay.client.ret.ResultContent<List<TransactionLogModel>> resultContent = param.getTransactionLogModelList();
        String state = param.getStatus();
        String refundStatus = param.getRefundStatus();

        // 退款完成
        ExpenseFlow expenseFlow = expenseFlowDao.findTopByPaymentNo(paymentNo);

        if (ObjectUtils.isNotEmpty(expenseFlow)) {
            if (state.equals("TRADE_SUCCESS") && refundStatus.equals("SUCCESS")) {
                orderNoInfoService.markSuccess(paymentNo);
                // 退款流程 成功
                expenseFlow.setIsRefund(Boolean.TRUE);
                expenseFlow.setRefundState(RefundState.Refunded);
                expenseFlow.setRefuseRemark("退款成功");
                expenseFlow.setOrderState(OrderState.REFUNDED);

                if (resultContent.getState() == ResultState.Success) {
                    expenseFlow.setRefundTransactionIds(resultContent.getContent());
                }
                refundRecordService.markState(param.getRefundOrderId(), RefundState.Refunded, resultContent.getContent());
            } else if (refundStatus.equals("FAIL")) {
                orderNoInfoService.markSuccess(paymentNo);
                // 退款失败
                expenseFlow.setIsRefund(Boolean.TRUE);
                expenseFlow.setRefundState(RefundState.Fail);
                expenseFlow.setRefuseRemark("退款失败");
                refundRecordService.markState(param.getRefundOrderId(), RefundState.Fail);
            }
            expenseFlowDao.save(expenseFlow);
        }
        return ResultContent.buildSuccess();
    }

    /**
     * 结算
     *
     * @param taskConfig
     * @return
     */
    public ResultContent settlement(ScheduleTaskConfig taskConfig) {
        HashMap<String, Object> data = taskConfig.getData();
        String projectOid = data.get("projectOid").toString();
        PaymentType paymentType = PaymentType.valueOf(data.get("channelType").toString());
        if (StringUtils.isNotEmpty(projectOid) && paymentType != null) {
            paymentType = turnPaymentType(paymentType);
            String remark = "定时结算";
            Long endTime = projectMainPaySettingService.getCurrentRunTime(projectOid, paymentType);
//            Long endTime = System.currentTimeMillis();

            // 项目包含的机构列表
            List<Organization> list = projectBindOrgService.getProjectBindOrgs(projectOid);
            if (ObjectUtils.isNotEmpty(list)) {
                for (Organization organization : list) {
                    com.github.microservice.pay.client.ret.ResultContent resultContent = settleService.settle(projectOid, organization.getOid(), endTime, remark, paymentType);
                    //TODO 标记订单已结算
                    if (resultContent.getState() == ResultState.Success) {
                        Object object = resultContent.getContent();
                        if (object != null) {
                            Set<String> orderNoSet = (Set<String>) object;
                            //  标记订单已结算
                            markOrderSettlement(orderNoSet);
                        }
                    }
                }
            }
        }
        return ResultContent.buildSuccess();
    }

    /**
     * 标记订单已结算
     *
     * @param orderNoSet
     */
    public void markOrderSettlement(Set<String> orderNoSet) {
        log.info("orderNoSet: {}", orderNoSet);
        if (orderNoSet != null && !orderNoSet.isEmpty()) {
            List<String> orderNoList = new ArrayList<>(orderNoSet);
            Map<String, Object> where = new HashMap<>();
            where.put("paymentNo", orderNoList);

            Map<String, Object> standardData = new HashMap<>();
            standardData.put("settlementState", SettlementState.AlreadySettled);
            standardData.put("settlementTime", System.currentTimeMillis());

            // 消费订单
            commonService.updateData(where, standardData, ExpenseFlow.class.getSimpleName());

            Map<String, Object> refundWhere = new HashMap<>();
            refundWhere.put("refundNo", orderNoList);
            // 退款已结算
            commonService.updateData(refundWhere, standardData, ExpenseFlow.class.getSimpleName());
        }
    }

    /**
     * 支付类型转换，主要是：WeChat -> UserWallet
     *
     * @param paymentType
     * @return
     */
    public PaymentType turnPaymentType(PaymentType paymentType) {
        if (paymentType != null && paymentType == PaymentType.WeChat) {
            return PaymentType.UserWallet;
        }
        return paymentType;
    }

    /**
     * 组装分账的数据
     *
     * @param entity
     */
    public List<SatInfoModel> buildShare(ExpenseFlow entity, PaymentType paymentType) {
        List<SatInfoModel> satInfoModel = new ArrayList<>();
        ProjectMainPaySetting paySetting = projectMainPaySettingService.getProjectMainPaySetting(entity.getProjectOid(), paymentType);
        if (ObjectUtils.isNotEmpty(paySetting)) {
            // 消费的金额
            BigDecimal payAmount = entity.getPayAmount();
            Long minSharing = paySetting.getMinSharing();
            if (minSharing != null && minSharing > 0 && BigDecimal.valueOf(minSharing).compareTo(payAmount) <= 0) {
                ProjectOrgPaySettingInfo childPaySettingInfo = paySetting.getChildPaySettingInfo();
                if (ObjectUtils.isNotEmpty(childPaySettingInfo)) {
                    String mainOid = childPaySettingInfo.getBelongOig();
                    String shopOid = entity.getShopOid();

                    BigDecimal projectScale = paySetting.getProjectScale();
                    if (projectScale != null) {
                        BigDecimal orgScale = paySetting.getOrgScale();
                        SatInfoModel plat = new SatInfoModel();
                        plat.setOid(mainOid);
                        plat.setRatio(projectScale);

                        SatInfoModel shop = new SatInfoModel();
                        shop.setOid(shopOid);
                        shop.setRatio(orgScale);

                        satInfoModel.add(plat);
                        satInfoModel.add(shop);
                    }
                }
            }
        }
        return satInfoModel;
    }

}
