package com.sckw.payment.service;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.sckw.core.exception.BusinessException;
import com.sckw.core.utils.CollectionUtils;
import com.sckw.core.utils.OkHttpUtils;
import com.sckw.payment.api.model.constant.ChannelEnum;
import com.sckw.payment.api.model.dto.MemberDetail;
import com.sckw.payment.api.model.dto.WalletDto;
import com.sckw.payment.api.model.dto.common.R;
import com.sckw.payment.model.constant.PayCenterEnum;
import com.sckw.payment.model.dto.common.BusinessNo;
import com.sckw.payment.model.dto.common.Page;
import com.sckw.payment.model.dto.page.*;
import com.sckw.payment.model.dto.wallet.*;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 转发中台接口
 *
 * @author xucaiqin
 * @date 2023-07-21 17:45:51
 */
@Service
@Slf4j
@RefreshScope
public class PayCenterService {
    @Value("${payCenter.address}")
    private String payCenterAddr;

    private <T> R<List<T>> parseArray(String in, Class<T> t) {
        R<String> res = JSONObject.parseObject(in, new TypeReference<R<String>>() {
        });
        String data = res.getData();
        List<T> ts = JSONArray.parseArray(data, t);
        R<List<T>> ok = R.ok(ts);
        ok.setStatus(res.getStatus());
        ok.setMsg(res.getMsg());
        ok.setCode(res.getCode());
        return ok;
    }

    private String getHttp(PayCenterEnum payCenterEnum, Map<String, Object> para) {
        log.info("{}入参->{}", payCenterEnum.getDesc(), JSONObject.toJSONString(para));
        OkHttpUtils okHttpUtils = OkHttpUtils.builder().url(payCenterAddr + payCenterEnum.getAddr());
        if (!CollectionUtils.isEmpty(para)) {
            for (Map.Entry<String, Object> p : para.entrySet()) {
                //跳过非空参数
                Object v = p.getValue();
                String k = p.getKey();
                if (Objects.isNull(v)) {
                    continue;
                }
                if (v instanceof ChannelEnum channelEnum) {
                    okHttpUtils.addPara(k, channelEnum.getChannel());
                } else if (v instanceof Integer i) {
                    okHttpUtils.addPara(k, String.valueOf(i));
                } else if (v instanceof Long i) {
                    okHttpUtils.addPara(k, String.valueOf(i));
                } else if (v instanceof String i) {
                    okHttpUtils.addPara(k, i);
                } else if ((v.getClass().isArray()) && v instanceof String[] l) {
                    for (int i = 0; i < l.length; i++) {
                        okHttpUtils.addPara(k + "[" + i + "]", l[i]);
                    }
                } else {
                    okHttpUtils.addPara(k, v.toString());
                }

            }
        }
        String sync;
        try {
            sync = okHttpUtils.get().sync();
        } catch (Exception e) {
            log.error("中台服务异常", e.getCause());
            throw new RuntimeException("支付服务异常!");
        }
        log.info("{}返回值->{}", payCenterEnum.getDesc(), sync);
        return changeRes(sync);
    }

    private String postHttp(PayCenterEnum payCenterEnum, Map<String, Object> para) {
        log.info("{}入参->{}", payCenterEnum.getDesc(), JSONObject.toJSONString(para));
        OkHttpUtils okHttpUtils = OkHttpUtils.builder().url(payCenterAddr + payCenterEnum.getAddr());
        if (!CollectionUtils.isEmpty(para)) {
            for (Map.Entry<String, Object> p : para.entrySet()) {
                //跳过非空参数
                Object v = p.getValue();
                String k = p.getKey();
                if (Objects.isNull(v)) {
                    continue;
                }
                if (v instanceof ChannelEnum channelEnum) {
                    okHttpUtils.addBodyPara(k, channelEnum.getChannel());
                } else if (v instanceof Integer i) {
                    okHttpUtils.addBodyPara(k, String.valueOf(i));
                } else if (v instanceof Long i) {
                    okHttpUtils.addBodyPara(k, String.valueOf(i));
                } else if (v instanceof String i) {
                    okHttpUtils.addBodyPara(k, i);
                } else if ((v.getClass().isArray()) && v instanceof String[] l) {
                    for (int i = 0; i < l.length; i++) {
                        okHttpUtils.addPara(k + "[" + i + "]", l[i]);
                    }
                } else {
                    okHttpUtils.addBodyPara(k, JSONObject.toJSONString(v));
                }
            }
        }
        String sync;
        try {
            sync = okHttpUtils.post(true).sync();
        } catch (Exception e) {
            log.error("中台服务异常", e.getCause());
            throw new RuntimeException("支付服务异常!");
        }
        log.info("{}返回值->{}", payCenterEnum.getDesc(), sync);
        return changeRes(sync);
    }

    private String jsonHttp(PayCenterEnum payCenterEnum, Object object) {
        String para = object instanceof JSONObject jsonObject ? jsonObject.toJSONString() : JSONObject.toJSONString(object);
        log.info("{}入参->{}", payCenterEnum.getDesc(), para);
        OkHttpUtils okHttpUtils = OkHttpUtils.builder().url(payCenterAddr + payCenterEnum.getAddr());
        okHttpUtils.addBodyJsonStr(para);
        String sync;
        try {
            sync = okHttpUtils.post(true).sync();
        } catch (Exception e) {
            log.error("中台服务异常", e.getCause());
            throw new RuntimeException("支付服务异常!");
        }
        log.info("{}返回值->{}", payCenterEnum.getDesc(), sync);
        return changeRes(sync);
    }

    private String changeRes(String sync) {
        JSONObject jsonObject = JSONObject.parseObject(sync);
        //我的泛型是对象 返回值有可能 是对象或数组 {} []
        //data:[]->转换成 data:null 进入if
        Object data = jsonObject.get("data");
        if (Objects.nonNull(data) && data instanceof JSONArray d && d.isEmpty()) {
            jsonObject.put("data", null);
            sync = jsonObject.toJSONString();
        }
        return sync;
    }

    /**
     * 会员详情
     *
     * @param uid
     * @param channel
     * @return
     */
    public R<MemberDetail> memberDetail(String uid, @NotNull(message = "渠道类型不能为空") ChannelEnum channel) {
        String sync = getHttp(PayCenterEnum.MEMBER_DETAIL, new HashMap<>() {{
            put("uid", uid);
            put("channel", channel);
            put("channels", "xinwang");
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }


    /**
     * 总览信息
     *
     * @param uid
     * @return
     */
    public R<WalletOverview> general(String uid) {
        String sync = getHttp(PayCenterEnum.MEMBER_GENERAL, new HashMap<>() {{
            put("uid", uid);
            put("channels", "xinwang");
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 会员注册信息
     *
     * @param uid
     * @return
     */
    public R<JSONObject> user(String uid, ChannelEnum channelEnum) {
        String sync = getHttp(PayCenterEnum.USER, new HashMap<>() {{
            put("uid", uid);
            put("channel", channelEnum);
            put("channels", "xinwang");
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 钱包清单
     *
     * @param uid     付款人uid
     * @param channel 支付渠道
     * @param filter  收款方uid
     * @return
     */
    public R<List<WalletDto>> wallet(@NotNull String uid, ChannelEnum channel, String filter) {
        if (StringUtils.isBlank(uid)) {
            throw new BusinessException("提现用户不能为空");
        }
        String sync = getHttp(PayCenterEnum.MEMBER_WALLET, new HashMap<>() {{
            put("uid", uid);
            put("channel", Objects.isNull(channel) ? "" : channel);
            put("filter", filter);
        }});
        return parseArray(sync, WalletDto.class);
    }

    /**
     * 钱包清单 v2
     *
     * @param uid
     * @param channel
     * @param filter
     * @return
     */
    public R<Wallet> walletSum(@NotNull String uid, ChannelEnum channel, String filter) {
//        if (StringUtils.isBlank(uid)) {
//            throw new BusinessException("提现用户不能为空");
//        }
        String sync = getHttp(PayCenterEnum.MEMBER_WALLET_V2, new HashMap<>() {{
            put("uid", uid);
            put("channel", Objects.isNull(channel) ? "" : channel);
            put("filter", filter);
            put("channels", "xinwang");
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 提现详情
     *
     * @param uid
     * @param orderNo
     * @return
     */
    public R<CashDetail> withdrawDetail(String uid, String orderNo) {
        if (StringUtils.isBlank(uid)) {
            throw new BusinessException("提现用户不能为空");
        }
        if (StringUtils.isBlank(orderNo)) {
            throw new BusinessException("订单编号不能为空");
        }
        String sync = getHttp(PayCenterEnum.WITHDRAW_DETAIL, new HashMap<>() {{
            put("uid", uid);
            put("order_no", orderNo);
            put("channels", "xinwang");
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 提现清单
     *
     * @param uid
     * @param channel
     * @param page
     * @param pageSize
     * @return
     */
    public R<CashPage> withdrawIndex(String uid, ChannelEnum channel, String status, Integer page, Integer pageSize) {
        if (StringUtils.isBlank(uid)) {
            throw new BusinessException("用户不能为空");
        }
        if (Objects.isNull(page)) {
            page = 1;
        }
        if (Objects.isNull(pageSize)) {
            pageSize = 5;
        }
        Integer finalPage = page;
        Integer finalPageSize = pageSize;
        String sync = getHttp(PayCenterEnum.WITHDRAW_INDEX, new HashMap<>() {{
            put("uid", uid);
            put("channel", channel);
            put("page", finalPage);
            put("pageSize", finalPageSize);
            put("status", status);
            put("channels", "xinwang");
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 提现类型分类统计
     *
     * @param uid
     * @return
     */
    public R<List<CashCount>> withdrawCategory(String uid, ChannelEnum channel) {
        if (StringUtils.isBlank(uid)) {
            throw new BusinessException("用户不能为空");
        }
        String sync = getHttp(PayCenterEnum.WITHDRAW_CATEGORY, new HashMap<>() {{
            put("uid", uid);
            put("channel", channel);
            put("channels", "xinwang");
        }});
        return parseArray(sync, CashCount.class);
    }

    /**
     * 订单状态
     *
     * @param type
     * @return
     */
    public R<Map<String, String>> withdrawStatus(String type) {
        if (StringUtils.isBlank(type)) {
            type = "order";
        }
        String finalType = type;
        String sync = getHttp(PayCenterEnum.WITHDRAW_STATUS, new HashMap<>() {{
            put("type", finalType);
            put("channels", "xinwang");
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 取消提现
     *
     * @param uid
     * @param orderNo
     * @return
     */
    public R<Object> withdrawCancel(String uid, String orderNo) {
        if (StringUtils.isBlank(uid)) {
            throw new BusinessException("用户不能为空");
        }
        if (StringUtils.isBlank(orderNo)) {
            throw new BusinessException("提现订单不能为空");
        }
        String sync = postHttp(PayCenterEnum.WITHDRAW_CANCEL, new HashMap<>() {{
            put("uid", uid);
            put("order_no", orderNo);
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 申请提现
     *
     * @param uid
     * @param channel
     * @param money
     * @param remarks
     * @return
     */
    public R<Order> withdrawTake(String uid, @NotBlank(message = "渠道不能为空") ChannelEnum channel, Long money, String remarks) {
        if (StringUtils.isBlank(uid)) {
            throw new BusinessException("提现用户不能为空");
        }
        if (Objects.isNull(channel)) {
            throw new BusinessException("提现渠道不能为空");
        }
        if (Objects.isNull(money)) {
            throw new BusinessException("提现金额不能为空");
        }
        String sync = postHttp(PayCenterEnum.WITHDRAW_TAKE, new HashMap<>() {{
            put("uid", uid);
            put("channel", channel);
            put("money", money);
            put("remarks", remarks);
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 统计信息
     *
     * @param uid
     * @param channel
     * @param filter
     * @return
     */
    public R<WalletInfo> totalInfo(String uid, ChannelEnum channel, String filter) {
        if (StringUtils.isBlank(uid)) {
            throw new BusinessException("提现用户不能为空");
        }
        if (Objects.isNull(channel)) {
            throw new BusinessException("提现渠道不能为空");
        }
        if (StringUtils.isBlank(filter)) {
            throw new BusinessException("乙方用户不能为空");
        }
        String sync = getHttp(PayCenterEnum.TOTAL_INFO, new HashMap<>() {{
            put("uid", uid);
            put("channel", channel);
            put("filter", filter);
            put("channels", "xinwang");
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 操作记录-下载
     *
     * @param uid
     * @param channel
     * @param filter
     * @return
     */
    public R<OperateDown> operateDownload(String uid, ChannelEnum channel, String filter) {
        if (StringUtils.isBlank(uid)) {
            throw new BusinessException("提现用户不能为空");
        }
        if (Objects.isNull(channel)) {
            throw new BusinessException("提现渠道不能为空");
        }
        if (StringUtils.isBlank(filter)) {
            throw new BusinessException("乙方用户不能为空");
        }
        String sync = getHttp(PayCenterEnum.OPERATE_DOWNLOAD, new HashMap<>() {{
            put("uid", uid);
            put("channel", channel);
            put("filter", filter);
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 操作记录-分类
     *
     * @return
     */
    public R<Map<String, String>> operateCategory() {
        String sync = getHttp(PayCenterEnum.OPERATE_CATEGORY, new HashMap<>());
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 操作记录
     *
     * @param uid
     * @param channel
     * @param page
     * @param pageSize
     * @return
     */
    public R<OperatePage> operateIndex(String uid, String channel, Integer page, Integer pageSize,String type, String[] createTime) {
        if (Objects.isNull(page)) {
            page = 1;
        }
        if (Objects.isNull(pageSize)) {
            pageSize = 5;
        }
        Integer finalPage = page;
        Integer finalPageSize = pageSize;
        String sync = getHttp(PayCenterEnum.OPERATE_INDEX, new HashMap<>() {{
            put("uid", uid);
            put("channel", channel);
            put("page", finalPage);
            put("pageSize", finalPageSize);
            put("create_time", createTime);
            put("type", type);
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 钱包日志类型
     *
     * @return
     */
    public R<Map<String, String>> logCategory() {
        String sync = getHttp(PayCenterEnum.LOG_CATEGORY, new HashMap<>());
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 获取钱包使用明细
     *
     * @param uid
     * @param filter
     * @param page
     * @param pageSize
     * @return
     */
    public R<RecordPage> record(String uid, String filter, Integer page, Integer pageSize) {
        String sync = getHttp(PayCenterEnum.RECORD, new HashMap<>() {{
            put("uid", uid);
            put("filter", filter);
            put("page", page);
            put("pageSize", pageSize);
            put("channels", "xinwang");
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 余额转出
     * 中台逻辑：
     * 从uid的money到filter的money,通过清分接口实现。
     *
     * @param uid
     * @param channel
     * @param money
     * @param filter
     * @return
     */
    public R<Object> transfer(String uid, String filter, ChannelEnum channel, Long money) {
        String sync = postHttp(PayCenterEnum.TRANSFER, new HashMap<>() {{
            put("uid", uid);
            put("channel", channel);
            put("money", money);
            put("filter", filter);
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 预付订单详情
     *
     * @param orderNo
     * @return
     */
    public R<CashDetail> advancePayDetail(String orderNo) {
        String sync = getHttp(PayCenterEnum.ADVANCE_PAY_DETAIL, new HashMap<>() {{
            put("order_no", orderNo);
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 发起预付
     *
     * @param uid     乙方uid
     * @param channel 渠道
     * @param filter  甲方uid
     * @param money   金额，分
     * @return
     */
    public R<Order> advancePayApply(String uid, ChannelEnum channel, String filter, Long money) {
        String sync = postHttp(PayCenterEnum.ADVANCE_PAY_APPLY, new HashMap<>() {{
            put("uid", uid);
            put("channel", channel);
            put("money", money);
            put("filter", filter);
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /***
     * 预付订单清单
     * @param uid
     * @param channel
     * @param filter
     * @param page
     * @param pageSize
     * @return
     */
    public R<PrePayIndexPage> advancePayIndex(String uid, ChannelEnum channel, String filter, Integer page, Integer pageSize) {
        String sync = getHttp(PayCenterEnum.ADVANCE_PAY_INDEX, new HashMap<>() {{
            put("uid", uid);
            put("channel", channel);
            put("filter", filter);
            put("page", page);
            put("pageSize", pageSize);
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 预付订单清单
     *
     * @param uid
     * @param channel
     * @param filter
     * @param page
     * @param pageSize
     * @return
     */
    public R<Page<PrePayIndex2>> advancePayIndex2(String uid, ChannelEnum channel, String filter, Integer page, Integer pageSize, String keyword) {
        String sync = getHttp(PayCenterEnum.ADVANCE_PAY_INDEX2, new HashMap<>() {{
            put("uid", uid);
            put("channel", channel);
            put("filter", filter);
            put("page", page);
            put("pageSize", pageSize);
            put("keyword", keyword);
            put("channels", "xinwang");
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 钱包预付统计列表
     *
     * @param uid
     * @param channel
     * @param filter
     * @param page
     * @param pageSize
     * @return
     */
    public R<PrePayWalletPage> advancePayWALLET(String uid, ChannelEnum channel, String filter, Integer page, Integer pageSize) {
        String sync = getHttp(PayCenterEnum.ADVANCE_PAY_WALLETS, new HashMap<>() {{
            put("uid", uid);
            put("channel", channel);
            put("filter", filter);
            put("page", page);
            put("pageSize", pageSize);
            put("channels", "xinwang");
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 钱包预付通道统计
     *
     * @param uid
     * @param filter
     * @return
     */
    public R<List<ChannelStatistics>> advancePayWalletChannels(String uid, String filter) {
        String sync = getHttp(PayCenterEnum.ADVANCE_PAY_PAY_CHANNELS, new HashMap<>() {{
            put("uid", uid);
            put("filter", filter);
            put("channels", "xinwang");
        }});
        return parseArray(sync, ChannelStatistics.class);
    }

    /**
     * 钱包预收列表
     *
     * @param uid
     * @param channel
     * @param filter
     * @param page
     * @param pageSize
     * @return
     */
    public R<PrePayWalletPage> advancePayReceive(String uid, ChannelEnum channel, String filter, Integer page, Integer pageSize) {
        String sync = getHttp(PayCenterEnum.ADVANCE_PAY_RECEIVE, new HashMap<>() {{
            put("uid", uid);
            put("channel", channel);
            put("filter", filter);
            put("page", page);
            put("pageSize", pageSize);
            put("channels", "xinwang");
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 预付支出记录
     *
     * @param uid
     * @param channel
     * @param filter
     * @param orderNo
     * @param startDate
     * @param endDate
     * @param page
     * @param pageSize
     * @return
     */
    public R<PrePayLogsPage> advancePayLogs(String uid, ChannelEnum channel, String filter, String orderNo, String startDate, String endDate, Integer page, Integer pageSize) {
        String sync = getHttp(PayCenterEnum.ADVANCE_PAY_LOGS, new HashMap<>() {{
            put("uid", uid);
            put("channel", channel);
            put("filter", filter);
            put("orderNo", orderNo);
            put("startDate", startDate);
            put("endDate", endDate);
            put("page", page);
            put("pageSize", pageSize);
            put("channels", "xinwang");
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 钱包预收通道统计
     *
     * @param uid
     * @param filter
     * @return
     */
    public R<List<ChannelStatistics>> advancePayReceiveChannels(String uid, String filter) {
        String sync = getHttp(PayCenterEnum.ADVANCE_PAY_RECEIVE_CHANNELS, new HashMap<>() {{
            put("uid", uid);
            put("filter", filter);
        }});
        return parseArray(sync, ChannelStatistics.class);
    }

    /**
     * 预付订单状态
     *
     * @return
     */
    public R<List<String>> advancePayStatus() {
        String sync = getHttp(PayCenterEnum.ADVANCE_PAY_STATUS, new HashMap<>());
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 获取通道清单
     *
     * @return
     */
    public R<List<Channel>> index() {
        String sync = getHttp(PayCenterEnum.INDEX, new HashMap<>());
        return parseArray(sync, Channel.class);
    }

    /**
     * 订单记录
     *
     * @param uid
     * @param channel
     * @param filter
     * @param page
     * @param pageSize
     * @return
     */
    public R<PayRecordPage> memberPayIndex(String uid, ChannelEnum channel, String filter, Integer page, Integer pageSize) {
        String sync = getHttp(PayCenterEnum.MEMBER_PAY_INDEX, new HashMap<>() {{
            put("uid", uid);
            put("channel", channel);
            put("filter", filter);
            put("page", page);
            put("pageSize", pageSize);
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 清分结果查询
     *
     * @param uid
     * @param channel
     * @param businessNo
     * @return
     */
    public R<List<SplitDto>> agentPayQuery(String uid, ChannelEnum channel, String businessNo) {
        String sync = getHttp(PayCenterEnum.AGENT_PAY_QUERY, new HashMap<>() {{
            put("uid", uid);
            put("channel", channel);
            put("business_no", businessNo);
            put("channels", "xinwang");
        }});
        return parseArray(sync, SplitDto.class);
    }

    /**
     * 充值订单详情
     *
     * @param uid
     * @param startDate
     * @param endDate
     * @param keyword
     * @param page
     * @param pageSize
     * @return
     */
    public R<RechargePage> rechargeOrder(String uid, String filter, ChannelEnum channelEnum, String startDate, String endDate, String keyword, Integer page, Integer pageSize) {
        if (Objects.isNull(page)) {
            page = 1;
        }
        if (Objects.isNull(pageSize)) {
            pageSize = 5;
        }
        Integer finalPage = page;
        Integer finalPageSize = pageSize;
        String sync = getHttp(PayCenterEnum.RECHARGE_ORDER, new HashMap<>() {{
            put("uid", uid);
            put("filter", filter);
            put("channel", channelEnum);
            put("keyword", keyword);
            put("startDate", startDate);
            put("endDate", endDate);
            put("page", finalPage);
            put("pageSize", finalPageSize);
            put("channels", "xinwang");
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 创建/更新账户
     *
     * @param memberCreate
     * @return
     */
    public R<MemberRes> memberIndex(MemberCreate memberCreate) {

        String sync = jsonHttp(PayCenterEnum.MEMBER_INDEX, memberCreate);
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 在线充值
     *
     * @param buyUid  付款方/乙方/买货方 账户
     * @param sellUid 收款方/甲方/供货方 账户
     * @param channel 渠道方
     * @param money   金额，单位分
     * @return
     */
    public R<PayIndex> payIndex(String buyUid, String sellUid, ChannelEnum channel, Long money) {
        String sync = postHttp(PayCenterEnum.PAY_INDEX, new HashMap<>() {{
            put("buy_uid", buyUid);
            put("sell_uid", sellUid);
            put("channel", channel);
            put("money", money);
        }});

        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 转出，在提现
     *
     * @param uid
     * @param filter
     * @param channel
     * @param money
     * @return
     */
    public R<Order> withdrawTransfer(String uid, String filter, ChannelEnum channel, Long money) {
        String sync = postHttp(PayCenterEnum.WITHDRAW_TRANSFER, new HashMap<>() {{
            put("uid", uid);
            put("filter", filter);
            put("channel", channel);
            put("money", money);
        }});

        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 冻结资金
     * 中台逻辑：
     * 先判断预付金额是否足够，足够就冻结预付金额。
     * 不够则进行追加预付操作，在进行冻结
     *
     * @param uid        付款方uid
     * @param channel    支付通道
     * @param money      冻结金额，单位分
     * @param filter     收款方uid
     * @param businessNo 流水号
     * @return
     */
    public R<Freeze> walletFreeze(String uid, ChannelEnum channel, String filter, Long money, String businessNo) {
        String sync = postHttp(PayCenterEnum.WALLET_FREEZE, new HashMap<>() {{
            put("uid", uid);
            put("filter", filter);
            put("channel", channel);
            put("money", money);
            put("business_no", businessNo);
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 解冻金额
     *
     * @param businessNo
     * @return
     */
    public R<BusinessNo> walletUnFreeze(String businessNo) {
        String sync = postHttp(PayCenterEnum.WALLET_UNFREEZE, new HashMap<>() {{
            put("business_no", businessNo);
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 清分
     * 中台逻辑：
     * 先从预付金额中进行扣除，然后金额不够的情况下在调用三方接口进行清分，然后进行记账
     * 因为预付业务实际就是真实的清分业务，所以先判断预付金额是否足够
     *
     * @param buyUid
     * @param sellUid
     * @param channel
     * @param money
     * @param batchPayList
     * @param businessNo
     * @return
     */
    public R<BusinessNo> payAgentPay(String buyUid, String sellUid, ChannelEnum channel, Long money, List<PatchPay> batchPayList, String businessNo) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("buy_uid", buyUid);
        jsonObject.put("sell_uid", sellUid);
        jsonObject.put("channel", channel.getChannel());
        jsonObject.put("money", money);
        jsonObject.put("batch_pay_list", batchPayList);
        jsonObject.put("business_no", businessNo);
        String sync = jsonHttp(PayCenterEnum.PAY_AGENT_PAY, jsonObject);
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 清分
     *
     * @param buyUid       付款方uid
     * @param sellUid      收款方
     * @param channel      渠道
     * @param money        总清分金额
     * @param batchPayList 收款方集合
     * @param businessNo   流水号
     * @param payType      支付类型 0-默认 1-仅预付支付 2-仅余额支付
     * @return
     */
    public R<BusinessNo> payAgentPayV2(String buyUid, String sellUid, ChannelEnum channel, Long money, List<PatchPay> batchPayList, String businessNo, String payType) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("buy_uid", buyUid);
        jsonObject.put("sell_uid", sellUid);
        jsonObject.put("channel", Objects.nonNull(channel) ? channel.getChannel() : "");
        jsonObject.put("money", money);
        jsonObject.put("batch_pay_list", batchPayList);
        jsonObject.put("business_no", businessNo);
        jsonObject.put("pay_type", payType);
        String sync = jsonHttp(PayCenterEnum.PAY_AGENT_PAY_V2, jsonObject);
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 创建钱包
     *
     * @param uid
     * @param channel
     * @param filter
     * @param nickname
     * @return
     */
    public R<Object> walletIndex(@NotBlank(message = "uid不能为空") String uid, @NotNull(message = "支付渠道不能为空") ChannelEnum channel, @NotBlank(message = "filter不能为空") String filter, String nickname) {
        String sync = postHttp(PayCenterEnum.WALLET_INDEX, new HashMap<>() {{
            put("uid", uid);
            put("channel", channel);
            put("filter", filter);
            put("nickname", nickname);
        }});
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }

    /**
     * 充值订单退款
     *
     * @param uid
     * @param filter
     * @param channel
     * @param money
     * @return
     */
    public R<BusinessNo> refundApply(String uid, String filter, ChannelEnum channel, Long money) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("uid", uid);
        jsonObject.put("filter", filter);
        jsonObject.put("channel", Objects.nonNull(channel) ? channel.getChannel() : "");
        jsonObject.put("money", money);
        String sync = jsonHttp(PayCenterEnum.REFUND_APPLY, jsonObject);
        return JSONObject.parseObject(sync, new TypeReference<>() {
        });
    }
}
