package com.cpop.pay.framewok.task;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cpop.api.tencent.wxWork.handler.WebHookSendHandler;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.base.enums.OrderSource;
import com.cpop.core.base.exception.ServiceException;
import com.cpop.core.service.RedisService;
import com.cpop.core.utils.SpringUtils;
import com.cpop.pay.framewok.config.wxPay.WxPayProperties;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.profitsharing.request.ProfitSharingRequest;
import com.github.binarywang.wxpay.bean.profitsharing.result.ProfitSharingResult;
import com.github.binarywang.wxpay.exception.WxPayException;
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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @author DB
 * @createTime 2023/11/03 11:13
 * @description 微信支付异步处理类
 */
@Component
public class WxPayAsyncTask {

    @Autowired
    private WxPayProperties wxPayProperties;

    /**
     * @descriptions 异步分账
     * @author DB
     * @date 2023/11/03 11:14
     * @param orderId 订单id
     * @param notifyResult 通知结果
     * @param wxPayService 微信支付处理类
     * @return: void
     */
    @Async("customAsyncThreadPool")
    public void asyncWxPayProfitSharing(String orderId, WxPayOrderNotifyResult notifyResult, WxPayService wxPayService, OrderSource orderSource) {
        ProfitSharingRequest profitSharingRequest = buildProfitSharingRequest(orderId, notifyResult, orderSource);
        try {
            Thread.sleep(5000);
            wxPayProfitSharing(profitSharingRequest, wxPayService, 0, orderSource);
        } catch (InterruptedException e) {
            throw new ServiceException(e.getMessage());
        }
    }

    @Async("customAsyncThreadPool")
    public void asyncWxPayProfitSharing(String orderId, WxPayOrderNotifyResult notifyResult, WxPayService wxPayService, OrderSource orderSource, Double rate) {
        ProfitSharingRequest profitSharingRequest = buildProfitSharingRequest(orderId, notifyResult, orderSource, rate);
        try {
            Thread.sleep(5000);
            wxPayProfitSharing(profitSharingRequest, wxPayService, 0, orderSource);
        } catch (InterruptedException e) {
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * 构建分账请求参数
     * @author DB
     * @since 2023/12/28
     * @param orderId 订单号
     * @param notifyResult 通知结果
     * @param orderSource 订单来源
     * @return ProfitSharingRequest
     */
    private ProfitSharingRequest buildProfitSharingRequest(String orderId, WxPayOrderNotifyResult notifyResult, OrderSource orderSource) {
        return buildProfitSharingRequest(orderId, notifyResult, orderSource, orderSource.getRate());
    }

    /**
     * 构建分账请求参数
     * @author DB
     * @since 2023/12/28
     * @param orderId 订单号
     * @param notifyResult 通知结果
     * @param orderSource 订单来源
     * @param rate 分账比例
     * @return ProfitSharingRequest
     */
    private ProfitSharingRequest buildProfitSharingRequest(String orderId, WxPayOrderNotifyResult notifyResult, OrderSource orderSource, Double rate) {
        LocalDateTime now = LocalDateTime.now();
        Double ceil = Math.ceil(notifyResult.getTotalFee() * rate);
        Row row = Row.ofKey(RowKey.SNOW_FLAKE_ID)
                .set("order_id", orderId)
                .set("profit_sharing_status", 0)
                .set("amount", ceil.longValue())
                .set("pay_account", notifyResult.getSubMchId())
                .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(notifyResult.getTransactionId());
        profitSharingRequest.setSubMchId(notifyResult.getSubMchId());
        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();
                //发送通知到财务群
                List<String> phoneList = new ArrayList<String>();
                // 获取审核管理员手机号
                RedisService redisService = SpringUtils.getBean(RedisService.class);
                String auditStaffPhone = redisService.getCacheObject("sysConfig:oam:OamCancelAfterVerificationStaffPhone");
                phoneList.add(auditStaffPhone);
                try {
                    //获取订单信息
                    Row order = Db.selectOneByQuery("cp_j_easy_learn_order", QueryWrapper.create()
                            .select("cjelo.id", "cjelo.order_content", "cjelo.out_order_no", "cjelo.order_type", "cjelo.customer_name", "cjelo.customer_phone", "cjelo.total_pay_amount","cjelo.create_time")
                            .select("csb.brand_name")
                            .select("css.store_name")
                            .from("cp_j_easy_learn_order").as("cjelo")
                            .leftJoin("cp_sys_brand").as("csb").on("csb.id= cjelo.brand_id")
                            .leftJoin("cp_sys_store").as("css").on("css.id= cjelo.store_id")
                            .where("cjelo.id = ?", profitSharingResult.getOutOrderNo()));
                    JSONObject receiver = JSONObject.parseArray(profitSharingRequest.getReceivers()).getJSONObject(0);
                    SpringUtils.getBean(WebHookSendHandler.class).webHookSendText("a885058b-2478-4df8-bdb7-2bb94a08c1f5", phoneList,
                            "==========用户订单分账到账==========" +
                                    "\n订单创建时间:" + order.getLocalDateTime("createTime").format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) +
                                    "\n品牌:" + order.getString("brandName") +
                                    "\n校区:" + order.getString("storeName") +
                                    "\n订单类型:" + order.getInt("orderType") +
                                    "\n受益人:" + order.getInt("customerName") +
                                    "\n电话:" + order.getInt("customerPhone") +
                                    "\n订单金额:" + order.getBigDecimal("totalPayAmount") +
                                    "\n分账金额:" + receiver.get("amount") +
                                    "\n微信订单号:" + profitSharingRequest.getTransactionId() +
                                    "\n商户号:" + profitSharingRequest.getSubMchId() +
                                    "\n到账商户号:" + wxPayProperties.getSharingAccount(),
                            false);
                } catch (IOException e) {
                    throw new ServiceException("发送任务通知失败!");
                }
            } else {
                throw new ServiceException(profitSharingResult.getReturnMsg());
            }
        } catch (WxPayException e) {
            if (flag > 2) {
                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);
            }
        }
    }
}
