package com.cpop.oam.web;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.base.enums.OrderSource;
import com.cpop.core.utils.SpringUtils;
import com.cpop.jambox.business.entity.*;
import com.cpop.jambox.business.service.*;
import com.cpop.pay.framewok.handler.wxPay.WxPayHandler;
import com.cpop.system.business.entity.Store;
import com.cpop.system.business.entity.WxPayScore;
import com.cpop.system.business.entity.WxPayScoreDetail;
import com.cpop.system.business.service.StoreService;
import com.cpop.system.business.service.WxPayScoreDetailService;
import com.cpop.system.business.service.WxPayScoreService;
import com.github.binarywang.wxpay.bean.payscore.PartnerUserSignPlanEntity;
import com.github.binarywang.wxpay.bean.payscore.PayScorePlanDetailResult;
import com.github.binarywang.wxpay.bean.payscore.WxPartnerPayScoreSignPlanResult;
import com.github.binarywang.wxpay.bean.profitsharing.result.ProfitSharingV3Result;
import com.github.binarywang.wxpay.bean.request.WxPayPartnerOrderQueryV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayPartnerOrderQueryV3Result;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.core.datasource.DataSourceKey;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.*;
import lombok.extern.slf4j.Slf4j;
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 java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.cpop.jambox.business.entity.table.EasyLearnOrderExtendTableDef.EASY_LEARN_ORDER_EXTEND;
import static com.cpop.jambox.business.entity.table.EasyLearnOrderTableDef.EASY_LEARN_ORDER;
import static com.cpop.jambox.business.entity.table.StoreExtendTableDef.STORE_EXTEND;
import static com.cpop.system.business.entity.table.StoreTableDef.STORE;
import static com.cpop.system.business.entity.table.WxPayScoreTableDef.WX_PAY_SCORE;

/**
 * 旧数据同步
 * @author DB
 * @version 1.0.0
 * @since 2024-01-11 17:28
 */
@Slf4j
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles(profiles = {"prod","core","pay"})
public class CpopOldDataSyncTests {

    @Autowired
    private WxPayHandler wxPayHandler;

    /**
     * 同步旧校区数据
     * @author DB
     * @since 2024/1/11
     */
    @Test
    public void syncOldStoreData(){
        List<Row> rowList = null;
        try {
            //查询旧表
            DataSourceKey.use("jambox");
            rowList = DbChain.table("t_mechanism_info")
                    .select("tmi.X as longitude")
                    .select("tmi.store_id as storeCloudId")
                    .select("tmi.Y as latitude")
                    .select("tmi.charge_phone as phone")
                    .select("tmi.address as storeAddr")
                    .select("tmi.charge_name as personCharge")
                    .from("t_mechanism_info").as("tmi")
                    .where("tmi.store_id is not null")
                    .list();
        } finally {
            DataSourceKey.clear();
        }
        //获取所有校区
        Map<String, String> storeMap = SpringUtils.getBean(StoreExtendService.class).list().stream().collect(Collectors.toMap(StoreExtend::getStoreCloudId, StoreExtend::getStoreId));
        rowList.forEach(item->{
            item.set("id",storeMap.get(item.getString("storeCloudId")));
        });
        List<Row> filterList = rowList.stream().filter(item -> StringUtils.isNotBlank(item.getString("id"))).collect(Collectors.toList());
        SpringUtils.getBean(StoreService.class).updateBatch(RowUtil.toEntityList(filterList, Store.class));
    }

    /**
     * 同步旧数据一次一次支付
     * @author DB
     * @since 2024/1/12
     */
    @Test
    public void syncOldEasyLearnPayScorePlanData()  {
        List<Row> rowList = null;
        try {
            //查询旧表
            DataSourceKey.use("jambox");
            rowList = DbChain.table("j_wechat_pay_plan")
                    .select("merchant_plan_no")
                    .select("sub_merch_id as subMchId")
                    .from("j_wechat_pay_plan")
                    .where("is_month = 0")
                    .list();
        } finally {
            DataSourceKey.clear();
        }
        WxPayService wxPayService = wxPayHandler.getWxPayService();
        WxPayScoreService wxPayScoreService = SpringUtils.getBean(WxPayScoreService.class);
        WxPayScoreDetailService wxPayScoreDetailService = SpringUtils.getBean(WxPayScoreDetailService.class);
        rowList.forEach(item -> {
            WxPartnerPayScoreSignPlanResult result = null;
            try {
                result = wxPayService.getPartnerPayScoreSignPlanService().queryPlans(item.getString("merchantPlanNo"), item.getString("subMchId"));
                WxPayScore wxPayScore = new WxPayScore();
                wxPayScore.setId(result.getMerchantPlanNo())
                        .setOutPlanId(result.getPlanId())
                        .setSignAccount(result.getSubMchid())
                        .setPlanName(result.getPlanName())
                        .setPlanDuration(Integer.valueOf(result.getPlanDuration()))
                        .setDeductionQuantity(Integer.valueOf(result.getDeductionQuantity()))
                        .setTotalActualPrice(result.getTotalActualPrice())
                        .setTotalOriginalPrice(result.getTotalActualPrice())
                        .setPlanSource(OrderSource.EASY_LEARN.toString());
                wxPayScoreService.save(wxPayScore);
                //计划详情
                List<PayScorePlanDetailResult> planDetailList = result.getPlanDetailList();
                List<WxPayScoreDetail> wxPayScoreDetails = new ArrayList<>();
                planDetailList.forEach(inner -> {
                    WxPayScoreDetail wxPayScoreDetail = new WxPayScoreDetail();
                    wxPayScoreDetail.setSysWxPayScoreId(wxPayScore.getId())
                            .setPlanDetailNo(inner.getPlanDetailNo())
                            .setOriginalPrice(inner.getOriginalPrice())
                            .setActualPrice(inner.getActualPrice())
                            .setPlanDiscountDescription(inner.getPlanDiscountDescription())
                            .setPlanDetailName(inner.getPlanDetailName());
                    wxPayScoreDetails.add(wxPayScoreDetail);
                });
                wxPayScoreDetailService.saveBatch(wxPayScoreDetails);
            } catch (WxPayException e) {
                throw new RuntimeException(e);
            }
        });
    }

    @Test
    public void syncOldEasyLearnSignPayScorePlanData() throws WxPayException {
        List<Row> rowList = null;
        try {
            //查询旧表
            DataSourceKey.use("jambox");
            rowList = DbChain.table("j_commodity_ticket")
                    .select("jct.wx_order_id as orderId")
                    .select("jct.name as customerName")
                    .select("jct.phone as customerPhone")
                    .select("jct.store_id as storeCloudId")
                    .select("jct.card_no as productId")
                    .select("jwpp.merchant_plan_no")
                    .select("jwpp.sub_merch_id as subMchId")
                    .from("j_commodity_ticket").as("jct")
                    .leftJoin("j_wechat_pay_plan").as("jwpp").on("jwpp.template_id = jct.commodity_id")
                    .where("jwpp.is_month = 0")
                    .and("jct.deleted = 1")
                    .and("jct.ticket_type = 1")
                    .and("jct.pay_status = 'PAY'")
                    .and("jct.deleted = 1")
                    .and("jct.card_no is not null")
                    .and("jct.creation_time >= ?", LocalDateTime.of(2024, 1, 12, 16, 42))
                    .list();
        } finally {
            DataSourceKey.clear();
        }
        Map<String, Row> storeMap = Db.selectListByQuery(QueryWrapper.create()
                        .select(STORE.ID, STORE.BRAND_ID, STORE_EXTEND.STORE_CLOUD_ID)
                        .from(STORE)
                        .leftJoin(STORE_EXTEND).on(STORE_EXTEND.STORE_ID.eq(STORE.ID))
                        .where(STORE_EXTEND.STORE_CLOUD_ID.in(rowList.stream().map(item -> item.getString("storeCloudId")).collect(Collectors.toList()))))
                .stream().collect(Collectors.toMap(item -> item.getString("storeCloudId"), item -> item));
        WxPayService wxPayService = wxPayHandler.getWxPayService();
        WxPayScoreService wxPayScoreService = SpringUtils.getBean(WxPayScoreService.class);
        List<WxPayScore> payScoreList = wxPayScoreService.list();
        Map<String, WxPayScore> wxPayScoreMap = payScoreList.stream().collect(Collectors.toMap(WxPayScore::getOutPlanId, item -> item));
        List<EasyLearnOrderDetail> easyLearnOrderDetails = new ArrayList<>();
        List<EasyLearnOrderExtend> easyLearnOrderExtends = new ArrayList<>();
        List<EasyLearnOrder> easyLearnOrders = new ArrayList<>();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX");
        rowList.forEach(item->{
            try {
                PartnerUserSignPlanEntity partnerUserSignPlanEntity = wxPayService.getPartnerPayScoreSignPlanService()
                        .queryUserSignPlans(item.getString("orderId"), item.getString("subMchId"));
                EasyLearnOrder easyLearnOrder = new EasyLearnOrder();
                String storeCloudId = item.getString("storeCloudId");
                Integer extendStatus = changeStatus(partnerUserSignPlanEntity.getSignState());
                partnerUserSignPlanEntity.getSignedDetailList().forEach(inner->{
                    EasyLearnOrderDetail easyLearnOrderDetail = new EasyLearnOrderDetail();
                    BigDecimal payPrice = BigDecimal.valueOf(inner.getActualPayPrice()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
                    easyLearnOrderDetail.setId(inner.getMerchantPlanDetailNo())
                            .setOrderId(partnerUserSignPlanEntity.getMerchantSignPlanNo())
                            .setOutOrderNo(inner.getOrderId())
                            .setAmount(BigDecimal.valueOf(inner.getActualPrice()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP))
                            .setActualPrice(payPrice)
                            .setPeriodNo(inner.getPlanDetailNo())
                            .setDetailDesc(inner.getPlanDiscountDescription())
                            .setDetailName(inner.getPlanDetailName())
                            .setDetailStatus(changeDetailStatus(inner.getPlanDetailState()))
                            .setCreateTime(LocalDateTime.now());
                    if (StringUtils.isNotBlank(inner.getUseTime())){
                        easyLearnOrderDetail.setPayTime(LocalDateTime.parse(inner.getUseTime(),dateTimeFormatter));
                    }
                    if (inner.getPlanDetailState().equals("FINISHED")) {
                        if (easyLearnOrder.getTotalPayAmount() == null) {
                            easyLearnOrder.setTotalPayAmount(payPrice);
                        } else {
                            easyLearnOrder.setTotalPayAmount(easyLearnOrder.getTotalPayAmount().add(payPrice));
                        }
                    }
                    easyLearnOrderDetails.add(easyLearnOrderDetail);
                });
                easyLearnOrder.setId(partnerUserSignPlanEntity.getMerchantSignPlanNo())
                        .setOrderContent(partnerUserSignPlanEntity.getPlanName())
                        .setOrderStatus(1)
                        .setOutOrderNo(partnerUserSignPlanEntity.getSignPlanId())
                        .setBrandId(storeMap.get(storeCloudId).getString("brandId"))
                        .setStoreId(storeMap.get(storeCloudId).getString("id"))
                        .setCustomerName(item.getString("customerName"))
                        .setCustomerPhone(item.getString("customerPhone"))
                        .setTotalAmount(BigDecimal.valueOf(partnerUserSignPlanEntity.getTotalActualPrice()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP))
                        .setTotalPayAmount(BigDecimal.ZERO)
                        .setOrderType(0)
                        .setRate(OrderSource.EASY_LEARN.getRate())
                        .setProductId(item.getString("productId"))
                        .setCreateTime(LocalDateTime.parse(partnerUserSignPlanEntity.getSignTime(),dateTimeFormatter));
                easyLearnOrders.add(easyLearnOrder);
                EasyLearnOrderExtend easyLearnOrderExtend = new EasyLearnOrderExtend();
                easyLearnOrderExtend.setOrderId(partnerUserSignPlanEntity.getMerchantSignPlanNo())
                        .setGoingDetailNo(partnerUserSignPlanEntity.getGoingDetailNo())
                        .setPlanId(wxPayScoreMap.get(partnerUserSignPlanEntity.getPlanId()).getId())
                        .setSignPlanId(partnerUserSignPlanEntity.getSignPlanId())
                        .setSubMchId(partnerUserSignPlanEntity.getSubMchid())
                        .setExtendStatus(extendStatus)
                        .setExtendCancelType(changeCancelType(partnerUserSignPlanEntity.getCancelSignType()))
                        .setCancelReason(partnerUserSignPlanEntity.getCancelReason())
                        .setCreateTime(LocalDateTime.parse(partnerUserSignPlanEntity.getSignTime(),dateTimeFormatter));
                if (StringUtils.isNotBlank(partnerUserSignPlanEntity.getCancelSignTime())){
                    easyLearnOrderExtend.setCancelTime(LocalDateTime.parse(partnerUserSignPlanEntity.getCancelSignTime(),dateTimeFormatter));
                }
                easyLearnOrderExtends.add(easyLearnOrderExtend);
            } catch (WxPayException e) {
                throw new RuntimeException(e);
            }
        });
        SpringUtils.getBean(EasyLearnOrderService.class).saveBatch(easyLearnOrders);
        SpringUtils.getBean(EasyLearnOrderExtendService.class).saveBatch(easyLearnOrderExtends);
        SpringUtils.getBean(EasyLearnOrderDetailService.class).saveBatch(easyLearnOrderDetails);
    }

    private Integer changeStatus(String signStatus) {
        switch (signStatus) {
            case "UNSIGNED":
                return 0;
            case "SIGNED":
                return 1;
            case "SIGN_PLAN_CANCEL":
                return 2;
            case "COMPLETE":
                return 3;
            default:
                return 4;
        }
    }

    private Integer changeCancelType(String cancelType) {
        switch (cancelType) {
            case "NOT_CANCEL":
                return 0;
            case "USER":
                return 1;
            case "MERCHANT":
                return 2;
            default:
                return 3;
        }
    }

    private Integer changeDetailStatus(String detailStatus){
        switch (detailStatus) {
            case "NOT_USED":
                return 0;
            case "USING":
                return 1;
            case "USED":
                return 2;
            default:
                return 3;
        }
    }

    /**
     * 导入到旧库,已核销的数据
     * @author DB
     * @since 2024/1/12
     */
    @Test
    public void importEasyLearnDataToOldDataBase(){
        List<Row> brandList = null;
        List<Row> storeList = null;
        List<Row> ticketList = null;
        List<EasyLearnOrderExtend> list = SpringUtils.getBean(EasyLearnOrderExtendService.class).queryChain().where(EASY_LEARN_ORDER_EXTEND.EXTEND_STATUS.in(2, 3)).list();
        try {
            //查询旧表
            DataSourceKey.use("jambox");
            brandList = DbChain.table("t_brand_info")
                    .select("id")
                    .select("brand_id as brandCloudId")
                    .from("t_brand_info").as("jct")
                    .where("deleted = 1")
                    .list();
            storeList = DbChain.table("t_mechanism_info")
                    .select("mechanism_id as id")
                    .select("store_id as storeCloudId")
                    .from("t_mechanism_info")
                    .where("deleted = 1")
                    .list();
            List<String> collect = list.stream().map(EasyLearnOrderExtend::getOrderId).collect(Collectors.toList());
            ticketList = DbChain.table("j_commodity_ticket")
                    .select("user_id")
                    .select("wx_order_id")
                    .from("j_commodity_ticket")
                    .in("wx_order_id", collect)
                    .list();
        } finally {
            DataSourceKey.clear();
        }
        Map<String, String> brandMap = brandList.stream().collect(Collectors.toMap(item -> item.getString("brandCloudId"), item -> item.getString("id")));
        Map<String, String> storeMap = storeList.stream().collect(Collectors.toMap(item -> item.getString("storeCloudId"), item -> item.getString("id")));
        Map<String, String> brandCloudMap = SpringUtils.getBean(BrandExtendService.class).list().stream().collect(Collectors.toMap(BrandExtend::getBrandId, BrandExtend::getBrandCloudId));
        Map<String, String> storeCloudMap = SpringUtils.getBean(StoreExtendService.class).list().stream().collect(Collectors.toMap(StoreExtend::getStoreId, StoreExtend::getStoreCloudId));
        Map<String, EasyLearnOrder> orderMap = SpringUtils.getBean(EasyLearnOrderService.class).queryChain()
                .where(EASY_LEARN_ORDER.ID.in(list.stream().map(EasyLearnOrderExtend::getOrderId).collect(Collectors.toSet())))
                .list()
                .stream().collect(Collectors.toMap(EasyLearnOrder::getId, item -> item));
        Map<String, String> wxOrderMap = ticketList.stream().collect(Collectors.toMap(item -> item.getString("wxOrderId"), item -> item.getString("userId")));
        //获取签约计划
        Map<String, WxPayScore> wxPayScoreMap = SpringUtils.getBean(WxPayScoreService.class).queryChain()
                .where(WX_PAY_SCORE.ID.in(list.stream().map(EasyLearnOrderExtend::getPlanId).collect(Collectors.toSet())))
                .list().stream().collect(Collectors.toMap(WxPayScore::getId, item -> item));
        List<Row> rows = new ArrayList<>();
        list.forEach(item -> {
            EasyLearnOrder easyLearnOrder = orderMap.get(item.getOrderId());
            Row row = Row.ofKey(RowKey.of("refund_id", KeyType.Auto));
            row.set("brand_id", brandMap.get(brandCloudMap.get(easyLearnOrder.getBrandId())));
            row.set("mechanism_id", storeMap.get(storeCloudMap.get(easyLearnOrder.getStoreId())));
            row.set("type", "先学后付次付");
            row.set("type_id",item.getOrderId());
            row.set("name", easyLearnOrder.getCustomerName());
            row.set("phone", easyLearnOrder.getCustomerPhone());
            row.set("product_name",easyLearnOrder.getOrderContent());
            row.set("reason",item.getCancelReason());
            WxPayScore wxPayScore = wxPayScoreMap.get(item.getPlanId());
            BigDecimal bigDecimal = BigDecimal.valueOf(wxPayScore.getTotalOriginalPrice());
            BigDecimal oncePrice = bigDecimal.divide(BigDecimal.valueOf(wxPayScore.getDeductionQuantity()), 2, RoundingMode.HALF_UP);
            row.set("price",oncePrice.multiply(BigDecimal.valueOf(item.getGoingDetailNo())));
            row.set("wx_order_id",item.getOrderId());
            row.set("ticket_time",item.getCancelTime());
            row.set("refund_name",easyLearnOrder.getCustomerName());
            row.set("creation_time",item.getCancelTime());
            row.set("last_modification_date",item.getCancelTime());
            row.set("creation_by",wxOrderMap.get(item.getOrderId()));
            row.set("last_modified",wxOrderMap.get(item.getOrderId()));
            rows.add(row);
        });
        try {
            //查询旧表
            DataSourceKey.use("jambox");
            Db.insertBatch("j_contract_refund",rows);
        } finally {
            DataSourceKey.clear();
        }
    }

    @Test
    public void getSharingData() throws WxPayException {
        List<Row> rowList = null;
        try {
            //查询旧表
            DataSourceKey.use("jambox");
            rowList = DbChain.table("j_wx_pay_profit_sharing")
                    .select("id")
                    .select("sub_mch_id")
                    .select("out_order_no")
                    .select("transaction_id")
                    .list();
        } finally {
            DataSourceKey.clear();
        }
        WxPayService wxPayService = wxPayHandler.getWxPayService();
        List<Row> rows = new ArrayList<>();
        rowList.forEach(item->{
            try {
                ProfitSharingV3Result profitSharingV3Result = wxPayService.getProfitSharingService().profitSharingQueryV3(item.getString("outOrderNo"),
                        item.getString("transactionId"),item.getString("subMchId"));
                //查询原订单
                WxPayPartnerOrderQueryV3Request wxPayOrderQueryV3Request = new WxPayPartnerOrderQueryV3Request();
                wxPayOrderQueryV3Request.setSubMchId(item.getString("subMchId"));
                wxPayOrderQueryV3Request.setTransactionId(item.getString("transactionId"));
                WxPayPartnerOrderQueryV3Result wxPayPartnerOrderQueryV3Result = wxPayService.queryPartnerOrderV3(wxPayOrderQueryV3Request);
                Row row = new Row();
                String[] split = wxPayPartnerOrderQueryV3Result.getAttach().split("\\|");
                row.set("aaa",profitSharingV3Result.getOutOrderNo());
                row.set("bbb",split[1]);
                rows.add(row);
            } catch (WxPayException e) {
                throw new RuntimeException(e);
            }
        });
        try {
            //查询旧表
            DataSourceKey.use("jambox");
            Db.insertBatch("asds", rows);
        } finally {
            DataSourceKey.clear();
        }

    }

    @Test
    public void getWxPayPlanDetail() {
        WxPayService wxPayService = wxPayHandler.getWxPayService(null,"1661323640");
        PartnerUserSignPlanEntity result = null;
        try {
            WxPayOrderQueryResult wxPayOrderQueryResult = wxPayService.queryOrder("4200002115202402010692134851", null);
            System.out.println(JSONObject.toJSONString(wxPayOrderQueryResult));
        } catch (WxPayException e) {
            throw new RuntimeException(e);
        }
    }

}
