package com.cpop.oam.web;

import cn.binarywang.wx.miniapp.api.WxMaQrcodeService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import com.alibaba.fastjson.JSONObject;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.base.enums.OrderSource;
import com.cpop.core.base.exception.ServiceException;
import com.cpop.core.handler.TencentCosHandler;
import com.cpop.core.utils.SpringUtils;
import com.cpop.core.utils.file.FileUtils;
import com.cpop.jambox.business.entity.EasyLearnOrder;
import com.cpop.jambox.business.entity.StoreExtend;
import com.cpop.jambox.business.service.EasyLearnOrderService;
import com.cpop.jambox.business.service.StoreExtendService;
import com.cpop.jambox.framework.constant.JamboxCloudUrl;
import com.cpop.pay.framewok.config.wxPay.WxPayProperties;
import com.cpop.pay.framewok.handler.wxPay.WxPayHandler;
import com.github.binarywang.wxpay.bean.payscore.*;
import com.github.binarywang.wxpay.bean.profitsharing.request.ProfitSharingBillV3Request;
import com.github.binarywang.wxpay.bean.profitsharing.request.ProfitSharingReceiverRequest;
import com.github.binarywang.wxpay.bean.profitsharing.request.ProfitSharingRequest;
import com.github.binarywang.wxpay.bean.profitsharing.result.ProfitSharingBillV3Result;
import com.github.binarywang.wxpay.bean.profitsharing.result.ProfitSharingOrderAmountQueryV3Result;
import com.github.binarywang.wxpay.bean.profitsharing.result.ProfitSharingResult;
import com.github.binarywang.wxpay.bean.profitsharing.result.ProfitSharingV3Result;
import com.github.binarywang.wxpay.bean.request.WxPayApplyTradeBillV3Request;
import com.github.binarywang.wxpay.bean.request.WxPayOrderQueryRequest;
import com.github.binarywang.wxpay.bean.request.WxPayOrderQueryV3Request;
import com.github.binarywang.wxpay.bean.request.WxPayPartnerOrderCloseV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayApplyBillV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.PartnerPayScoreSignPlanService;
import com.github.binarywang.wxpay.service.ProfitSharingService;
import com.github.binarywang.wxpay.service.WxPayService;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.Db;
import com.mybatisflex.core.row.DbChain;
import com.mybatisflex.core.row.Row;
import com.mybatisflex.core.row.RowKey;
import com.qcloud.cos.model.UploadResult;
import me.chanjar.weixin.common.error.WxErrorException;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.cpop.jambox.business.entity.table.EasyLearnOrderTableDef.EASY_LEARN_ORDER;
import static com.cpop.jambox.business.entity.table.StoreExtendTableDef.STORE_EXTEND;

/**
 * @author DB
 * @version 1.0.0
 * @since 2023-12-29 9:50
 */
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles({"dev", "core", "jambox", "pay"})
public class CpopEasyLearnTest {

    @Autowired
    private WxPayService wxPayService;

    @Autowired
    private WxPayProperties wxPayProperties;

    @Autowired
    private WxPayHandler wxPayHandler;

    /**
     * 关闭订单一次性支付
     * @author DB
     * @since 2023/12/29
     */
    @Test
    public void finishOncePay() throws WxPayException {
        String outTradeNo = "97973645262987264";
        /*String transactionId = "4200002093202312282215936862";
        ProfitSharingFinishRequest profitSharingFinishRequest = new ProfitSharingFinishRequest();
        profitSharingFinishRequest.setTransactionId(transactionId);
        profitSharingFinishRequest.setOutOrderNo(outTradeNo);
        profitSharingFinishRequest.setDescription("结束分账");
        profitSharingFinishRequest.setSubMchId("1661323640");
        //结束分账
        wxPayService.getProfitSharingService().profitSharingFinish(profitSharingFinishRequest);*/
        //完结订单
        WxPayConfig wxPayConfig = wxPayService.getConfig();
        wxPayConfig.setSubMchId("1661323640");
        wxPayService.setConfig(wxPayConfig);
        wxPayService.closeOrder(outTradeNo);
    }

    /**
     * 放心学一次性支付
     * @author DB
     * @since 2023/12/29
     */
    @Test
    public void easyLearnOncePay(){
        String orderId = "97976926051770368";
        //获取订单信息
        EasyLearnOrderService easyLearnOrderService = SpringUtils.getBean(EasyLearnOrderService.class);
        EasyLearnOrder easyLearnOrder = easyLearnOrderService.getById(orderId);
        //需要分账
        String subMchId = wxPayHandler.getSubMchId(easyLearnOrder.getBrandId(), easyLearnOrder.getStoreId());
        String transactionId = "4200002127202312282719627535";
        //课卡信息
        JSONObject jsonBody = new JSONObject();
        jsonBody.put("_type", "addPeriod");
        //办卡实收金额
        jsonBody.put("money", easyLearnOrder.getTotalPayAmount());
        //获取云校区id
        StoreExtend storeExtend = SpringUtils.getBean(StoreExtendService.class).getOne(QueryWrapper.create().where(STORE_EXTEND.STORE_ID.eq(easyLearnOrder.getStoreId())));
        //店铺/校区
        jsonBody.put("storeId", storeExtend.getStoreCloudId());
        //手机号
        jsonBody.put("phone", easyLearnOrder.getCustomerPhone());
        //客户名称
        jsonBody.put("customerName", easyLearnOrder.getCustomerName());
        //模板id
        jsonBody.put("templateId", easyLearnOrder.getOrderCloudId());
        //订单来源
        jsonBody.put("orderSource", OrderSource.EASY_LEARN.toString());
        //订单来源
        jsonBody.put("subMchId", subMchId);
        //获取课卡信息
        JSONObject result = SpringUtils.getBean(RestTemplate.class).postForObject(JamboxCloudUrl.COMMON_CARD_URL, jsonBody, JSONObject.class);
        if (result == null){
            throw new ServiceException("放心学一次性支付办卡失败!");
        }
        easyLearnOrderService.updateChain().set(EASY_LEARN_ORDER.OUT_ORDER_NO, transactionId)
                .set(EASY_LEARN_ORDER.PRODUCT_ID, result.getString("data"))
                .set(EASY_LEARN_ORDER.ORDER_STATUS, 1)
                .where(EASY_LEARN_ORDER.ID.eq(orderId)).update();
    }

    /**
     * 构建分账请求参数
     * @author DB
     * @since 2023/12/28
     * @param orderId 订单号
     * @param orderSource 订单来源
     * @return ProfitSharingRequest
     */
    private ProfitSharingRequest buildProfitSharingRequest(String orderId, OrderSource orderSource, Integer totalFee, String subMchId, String transactionId) {
        LocalDateTime now = LocalDateTime.now();
        Double ceil = Math.ceil(totalFee * orderSource.getRate());
        Row row = Row.ofKey(RowKey.SNOW_FLAKE_ID)
                .set("order_id", orderId)
                .set("profit_sharing_status", 0)
                .set("amount", ceil.longValue())
                .set("pay_account", subMchId)
                .set("order_source",orderSource.toString())
                .set("create_time", now)
                .set("update_time", now)
                .set("create_user_id", "1")
                .set("update_user_id", "1");
        Db.insert("cp_sys_profit_sharing", row);
        //固定商户信息
        Map<String, Object> mapReceiver = new HashMap<>(4);
        mapReceiver.put("type", "MERCHANT_ID");
        mapReceiver.put("account", wxPayProperties.getSharingAccount());
        mapReceiver.put("amount", ceil.longValue());
        mapReceiver.put("description","分账到服务商");
        List<Map<String, Object>> receivers = new ArrayList<>();
        receivers.add(mapReceiver);
        //分账请求参数
        ProfitSharingRequest profitSharingRequest = new ProfitSharingRequest();
        profitSharingRequest.setReceivers(JSONObject.toJSONString(receivers));
        profitSharingRequest.setOutOrderNo(row.getString("id"));
        profitSharingRequest.setTransactionId(transactionId);
        profitSharingRequest.setSubMchId(subMchId);
        return profitSharingRequest;
    }

    /**
     * 微信支付分账
     * @author DB
     * @since 2023/11/03 11:09
     * @param profitSharingRequest 请求参数
     * @param wxPayService 微信服务类
     * @param flag 标记
     */
    private void wxPayProfitSharing(ProfitSharingRequest profitSharingRequest, WxPayService wxPayService, Integer flag, OrderSource orderSource) {
        try {
            ProfitSharingResult profitSharingResult = wxPayService.getProfitSharingService().profitSharing(profitSharingRequest);
            if (StringUtils.equals(profitSharingResult.getResultCode(), "SUCCESS")) {
                //存入系统
                DbChain.table("cp_sys_profit_sharing")
                        .set("out_profit_sharing_id", profitSharingResult.getOrderId())
                        .set("profit_sharing_status", 1)
                        .where("id = ?", profitSharingResult.getOutOrderNo())
                        .update();
            } else {
                throw new ServiceException(profitSharingResult.getReturnMsg());
            }
        } catch (WxPayException e) {
            if (flag > 5) {
                if (OrderSource.MALL == orderSource) {
                    //关闭商城支付
                    DbChain.table("cp_sys_brand")
                            .set("is_open_sharing", false)
                            .where("wx_mch_id = ?", wxPayService.getConfig().getSubMchId())
                            .update();
                }
                throw new ServiceException(e.getMessage());
            } else {
                //重复调用
                flag = flag + 1;
                wxPayProfitSharing(profitSharingRequest, wxPayService, flag, orderSource);
            }
        }
    }

    /**
     * 关闭服务商订单
     * @author DB
     * @since 2024/1/12
     */
    @Test
    public void closePartnerOrderV3() throws WxPayException {
        WxPayService wxPayService= wxPayHandler.getWxPayService();
        WxPayPartnerOrderCloseV3Request wxPayPartnerOrderCloseV3Request = new WxPayPartnerOrderCloseV3Request();
        wxPayPartnerOrderCloseV3Request.setSubMchId("1661323640");
        wxPayPartnerOrderCloseV3Request.setOutTradeNo("1745820005743910912");
        wxPayService.closePartnerOrderV3(wxPayPartnerOrderCloseV3Request);
    }

    /**
     * 查询未完结订单
     * @author DB
     * @since 2024/1/19
     */
    @Test
    public void downloadBill() throws WxPayException {
        WxPayService wxPayService = wxPayHandler.getWxPayService(null, "1663310469");
        ProfitSharingService profitSharingService = wxPayService.getProfitSharingService();
        ProfitSharingBillV3Request profitSharingBillV3Request = new ProfitSharingBillV3Request();
        profitSharingBillV3Request.setSubMchId("1663310469");
        String date = "2024-01-17";
        profitSharingBillV3Request.setBillDate(date);
        WxPayApplyTradeBillV3Request wxPayApplyTradeBillV3Request = new WxPayApplyTradeBillV3Request();
        wxPayApplyTradeBillV3Request.setBillDate(date);
        wxPayApplyTradeBillV3Request.setBillType("ALL");
        WxPayApplyBillV3Result wxPayApplyBillV3Result = wxPayService.applyTradeBill(wxPayApplyTradeBillV3Request);
        //ProfitSharingBillV3Result profitSharingBillV3Result = profitSharingService.profitSharingBill(profitSharingBillV3Request);
        InputStream inputStream = wxPayService.downloadBill(wxPayApplyBillV3Result.getDownloadUrl());
        new File("");
        // 创建输出文件的路径
        String filePath = "D:\\Lost\\下载\\" + date + ".txt";
        // 将输入流中的内容写入文件
        try (OutputStream outputStream = Files.newOutputStream(Paths.get(filePath))) {
            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            System.out.println("内容成功写入文件");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void queryOrderAndSharing() throws WxPayException {
        WxPayService wxPayService = wxPayHandler.getWxPayService(null, "1661323640");
        WxPayOrderQueryRequest wxPayOrderQueryRequest = new WxPayOrderQueryRequest();
        WxPayConfig config = wxPayService.getConfig();
        config.setAppId("wx1eb0e5fb7dac3c05");
        wxPayService.setConfig(config);
        wxPayOrderQueryRequest.setTransactionId("4200002096202402199975156147");
        WxPayOrderQueryResult wxPayOrderQueryResult = wxPayService.queryOrder(wxPayOrderQueryRequest);
        //ProfitSharingService profitSharingService = wxPayService.getProfitSharingService();
        //ProfitSharingV3Result profitSharingV3Result = profitSharingService.profitSharingQueryV3("1752967538354028544", "4200002116202402013721924373", "1661323640");
        System.out.println(JSONObject.toJSONString(wxPayOrderQueryResult));
        //System.out.println(JSONObject.toJSONString(profitSharingV3Result));
    }

    @Test
    public void queryServiceOrder() throws WxPayException {
        WxPayService wxPayService = wxPayHandler.getWxPayService();
        WxPartnerPayScoreResult wxPartnerPayScoreResult = wxPayService.getPartnerPayScoreService().queryServiceOrder("00003053000000169450961228104460", "1650816616", "1000000000202310231164117852485", null);
        System.out.println(JSONObject.toJSONString(wxPartnerPayScoreResult));
    }

    @Test
    public void completeOrder() throws WxPayException {
        WxPayService wxPayService = wxPayHandler.getWxPayService();
        WxPartnerPayScoreRequest wxPayScoreRequest = new WxPartnerPayScoreRequest();
        PostPayment postPayment = new PostPayment();
        List<PostPayment> postPayments = new ArrayList<>();
        postPayment.setAmount(8400);
        postPayment.setName("成人hiphop（基础）-课程核销");
        postPayments.add(postPayment);
        wxPayScoreRequest.setOutOrderNo("1736679801829396489").setPostPayments(postPayments).setTotalAmount(8400);
        TimeRange timeRange = new TimeRange();
        timeRange.setStartTime("20240130235313");
        timeRange.setEndTime("20240130235422");
        wxPayScoreRequest.setTimeRange(timeRange);
        wxPayScoreRequest.setSubMchid("1661323640");
        wxPayScoreRequest.setServiceId("00003053000000169450961228104460");
        wxPayService.getPartnerPayScoreService().completeServiceOrder(wxPayScoreRequest);
    }

    @Test
    public void getWxPayPlan() {
        WxPayService wxPayService = wxPayHandler.getWxPayService(null,"1650816616");
        PartnerUserSignPlanEntity result = null;
        try {
            result = wxPayService.getPartnerPayScoreSignPlanService().queryUserSignPlans("1716417300529303582", "1650816616");
            System.out.println(JSONObject.toJSONString(result));
        } catch (WxPayException e) {
            throw new RuntimeException(e);
        }
    }

    @Test
    public void queryOrder() throws WxPayException {
        WxPayService wxPayService = wxPayHandler.getWxPayService(null, "1666928264");
        WxPayOrderQueryResult wxPayOrderQueryResult = wxPayService.queryOrder("4200002130202402224927801847",null);
        System.out.println(JSONObject.toJSONString(wxPayOrderQueryResult));

    }

    @Test
    public void orderProfitSharing() throws WxPayException {
        //固定商户信息
        Map<String, Object> mapReceiver = new HashMap<>(4);
        mapReceiver.put("type", "MERCHANT_ID");
        mapReceiver.put("account", wxPayProperties.getSharingAccount());
        mapReceiver.put("amount", 900);
        mapReceiver.put("description","分账到服务商");
        List<Map<String, Object>> receivers = new ArrayList<>();
        receivers.add(mapReceiver);
        //分账请求参数
        ProfitSharingRequest profitSharingRequest = new ProfitSharingRequest();
        profitSharingRequest.setReceivers(JSONObject.toJSONString(receivers));
        profitSharingRequest.setOutOrderNo("105490200209170432");
        profitSharingRequest.setTransactionId("4200002126202401189482541307");
        profitSharingRequest.setSubMchId("1663310469");
        ProfitSharingResult profitSharingResult = wxPayService.getProfitSharingService().profitSharing(profitSharingRequest);
        if (StringUtils.equals(profitSharingResult.getResultCode(), "SUCCESS")) {
            //存入系统
            DbChain.table("cp_sys_profit_sharing")
                    .set("out_profit_sharing_id", profitSharingResult.getOrderId())
                    .set("profit_sharing_status", 1)
                    .where("id = ?", profitSharingResult.getOutOrderNo())
                    .update();
        }
    }

    /**
     * 创建微信太阳码
     * @author DB
     * @since 2024/1/23
     */
    @Test
    public void createMiniQrCode() throws WxErrorException, IOException {
        // 获取当前执行环境
        String active = SpringUtils.getActiveProfile();
        WxMaQrcodeService qrcodeService = SpringUtils.getBean(WxMaService.class).getQrcodeService();
        File qrCode = qrcodeService.createWxaCodeUnlimit("105525473294344192", "pages/pay/pay", false, StringUtils.equals(active, "prod") ? "release" : "trial", 430,
                true, null, false);
        MultipartFile multipartFile = FileUtils.getInstance().getMultipartFile(qrCode);
        TencentCosHandler tencentCosHandler = SpringUtils.getBean(TencentCosHandler.class);
        UploadResult uploadResult = tencentCosHandler.cdnUpload(multipartFile);
        System.out.println("https://" + uploadResult.getBucketName() + tencentCosHandler.getCdnUrl() + uploadResult.getKey());
    }

    @Test
    public void subSpecialCharacter(){
        String serviceIntroduction = "排课000\uD83C\uDF3F\uD83C\uDF8B\uD83C\uDF15\uD83C\uDF44\uD83D\uDC1A";
        String newServiceIntroduction = "";
        //特殊字符过滤
        if (StringUtils.isBlank(serviceIntroduction)) {
            newServiceIntroduction = serviceIntroduction;
        }
        StringBuilder buf = null;
        int len = serviceIntroduction.length();
        for (int i = 0; i < len; i++) {
            char codePoint = serviceIntroduction.charAt(i);
            if (isEmojiCharacter(codePoint)) {
                if (buf == null) {
                    buf = new StringBuilder(serviceIntroduction.length());
                }
                buf.append(codePoint);
            }
        }
        if (buf == null) {
            newServiceIntroduction = serviceIntroduction;
        } else {
            if (buf.length() == len) {
                buf = null;
                newServiceIntroduction = serviceIntroduction;
            } else {
                newServiceIntroduction = buf.toString();
            }
        }
        System.out.println(newServiceIntroduction);
    }

    private  boolean isEmojiCharacter(char codePoint) {
        return (codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA)
                || (codePoint == 0xD)
                || ((codePoint >= 0x20) && (codePoint <= 0xD7FF))
                || ((codePoint >= 0xE000) && (codePoint <= 0xFFFD))
                || ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF));
    }


}
