package com.tmerclub.cloud.systemtest.test.order;

import com.alibaba.fastjson2.JSON;
import com.tmerclub.cloud.api.delivery.dto.DeliveryOrderDTO;
import com.tmerclub.cloud.api.delivery.vo.DeliveryOrderFeignVO;
import com.tmerclub.cloud.common.product.vo.app.CategoryAppVO;
import com.moyuer.cloud.systemtest.api.amount.CategoryApi;
import com.moyuer.cloud.systemtest.api.amount.PayApi;
import com.moyuer.cloud.systemtest.api.amount.ProductApi;
import com.moyuer.cloud.systemtest.api.order.*;
import com.moyuer.cloud.systemtest.api.store.SameCityApi;
import com.moyuer.cloud.systemtest.api.store.ShopWalletApi;
import com.moyuer.cloud.systemtest.data.amount.PreSaleSpuData;
import com.moyuer.cloud.systemtest.data.order.*;
import com.moyuer.cloud.systemtest.data.platform.CategoryDtoData;
import com.moyuer.cloud.systemtest.data.store.DeliveryData;
import com.moyuer.cloud.systemtest.data.store.SameCityDtoData;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author lpj
 */
public class PreSaleOrderTest {
    private List<Long> getCategoryId() {
        List<CategoryAppVO> categoryAppVOList = CategoryApi.listShopCategory(true);
        Long shopCategoryId = categoryAppVOList.get(categoryAppVOList.size() - 1).getCategoryId();
        Long categoryId = CategoryApi.listSigningCategory(true).get(0).getCategoryId();
        CategoryApi.update(CategoryDtoData.getCategoryDTO(categoryId));
        return Stream.of(categoryId, shopCategoryId).collect(Collectors.toList());
    }

    @DataProvider(name = "depositPreSaleProduct")
    private Object[][] depositPreSaleProduct() {
        List<Long> categoryIds = getCategoryId();
        Long transportId = DeliveryData.getFreeFeeDelivery(true);
        Long productId = ProductApi.createProduct(PreSaleSpuData.getDepositPreSaleSpu(categoryIds.get(0), categoryIds.get(1), transportId, 8800L), true);
        return new Object[][]{{productId}};
    }

    @DataProvider(name = "fullPreSaleProduct")
    private Object[][] fullPreSaleProduct() {
        List<Long> categoryIds = getCategoryId();
        Long transportId = DeliveryData.getFreeFeeDelivery(true);
        Long productId = ProductApi.createProduct(PreSaleSpuData.getFullPreSaleSpu(categoryIds.get(0), categoryIds.get(1), transportId, 8800L), true);
        return new Object[][]{{productId}};
    }

    @Test(description = "JK_59,定金预售订单取消删除", dataProvider = "depositPreSaleProduct")
    public void preSaleOrderCancel(Long productId) {
        MyOrderApi.confirm(OrderDtoData.getOrderDtoData(productId, 1));
        Long orderNum = MyOrderApi.submit(SubmitOrderDtoData.getSubmitOrderDtoData(productId)).get(0);
        MyOrderApi.cancel(orderNum);
        ProductApi.delete(productId, true);
        MyOrderApi.delete(orderNum);
    }

    @Test(description = "JK_60,定金预售订单发货完整流程", dataProvider = "depositPreSaleProduct")
    public void depositPreSaleOrderDeliveryTestCase(Long productId) throws InterruptedException {
        MyOrderApi.confirm(OrderDtoData.getOrderDtoData(productId, 1));
        Long orderNum = MyOrderApi.submit(SubmitOrderDtoData.getSubmitOrderDtoData(productId)).get(0);
        PayApi.orderPay(orderNum);
        TimeUnit.SECONDS.sleep(2L);
        PayApi.orderPayBalance(orderNum);
        TimeUnit.SECONDS.sleep(2L);
        OrderApi.delivery(DeliveryOrderDtoData.getDeliveryOrderDtoData(orderNum));
        MyOrderApi.receipt(orderNum);
        CommentApi.addComment(SpuCommDtoData.getSpuCommDtoData(OrderApi.getOrderItemAndAddress(orderNum).getOrderItems().get(0).getOrderItemId()));
        ProductApi.delete(productId, true);

        //验证运行后数据是否正确
        Assert.assertEquals(ShopWalletApi.getMongoShopWalletLogBO(orderNum, true).size(), 1);
        Assert.assertEquals(ShopWalletApi.getOrderDetailVO(orderNum, true).getOrderItemDetailList().get(0).getActualTotal(), 7800);
        Assert.assertEquals(ShopWalletApi.getOrderDetailVO(orderNum, true).getOrderItemDetailList().get(0).getPlatformCommission(), 155);
    }

    @Test(description = "JK_61,修改定金预售订单金额、用户收货信息和物流信息完整流程", dataProvider = "depositPreSaleProduct")
    public void depositPreSaleOrderChangeAmountDeliveryTestCase(Long productId) throws InterruptedException {
        MyOrderApi.confirm(OrderDtoData.getOrderDtoData(productId, 1));
        Long orderNum = MyOrderApi.submit(SubmitOrderDtoData.getSubmitOrderDtoData(productId)).get(0);

        OrderApi.infoOrder(orderNum);
        OrderApi.changeOrderAmount(OrderAdminDtoData.getOrderAdminDto(orderNum, 50L, 0L));

        OrderApi.infoOrderAddr(orderNum);
        OrderApi.changeOrderAddrCheck(orderNum);
        OrderApi.changeOrderAddr(OrderAddrDtoData.getChangeOrderAddrDTO(orderNum));
        PayApi.orderPay(orderNum);
        TimeUnit.SECONDS.sleep(2L);
        PayApi.orderPayBalance(orderNum);
        TimeUnit.SECONDS.sleep(2L);
        OrderApi.delivery(DeliveryOrderDtoData.getDeliveryOrderDtoData(orderNum));
        List<DeliveryOrderFeignVO> delivery = OrderApi.infoOrderDelivery(orderNum);

        List<DeliveryOrderDTO> deliveryOrderDtos = JSON.parseArray(JSON.toJSONString(delivery), DeliveryOrderDTO.class);
        deliveryOrderDtos.forEach(s -> s.setDeliveryNo("xgh123123123123"));
        OrderApi.updateOrderDelivery(deliveryOrderDtos);
        MyOrderApi.receipt(orderNum);
        CommentApi.addComment(SpuCommDtoData.getSpuCommDtoData(OrderApi.getOrderItemAndAddress(orderNum).getOrderItems().get(0).getOrderItemId()));
        ProductApi.delete(productId, true);

        //验证运行后数据是否正确
        Assert.assertEquals(ShopWalletApi.getMongoShopWalletLogBO(orderNum, true).size(), 1);
        Assert.assertEquals(ShopWalletApi.getOrderDetailVO(orderNum, true).getOrderItemDetailList().get(0).getActualTotal(), 850);
        Assert.assertEquals(ShopWalletApi.getOrderDetailVO(orderNum, true).getOrderItemDetailList().get(0).getPlatformCommission(), 17);
    }

    @Test(description = "JK_62,无需快递发货定金预售订单完整流程", dataProvider = "depositPreSaleProduct")
    public void noDeliveryDepositPreSaleOrderTestCase(Long productId) throws InterruptedException {
        MyOrderApi.confirm(OrderDtoData.getOrderDtoData(productId, 1));
        Long orderNum = MyOrderApi.submit(SubmitOrderDtoData.getSubmitOrderDtoData(productId)).get(0);
        PayApi.orderPay(orderNum);
        TimeUnit.SECONDS.sleep(2L);
        PayApi.orderPayBalance(orderNum);
        TimeUnit.SECONDS.sleep(2L);
        OrderApi.delivery(DeliveryOrderDtoData.getNoDeliveryOrderDtoData(orderNum));
        MyOrderApi.receipt(orderNum);
        CommentApi.addComment(SpuCommDtoData.getSpuCommDtoData(OrderApi.getOrderItemAndAddress(orderNum).getOrderItems().get(0).getOrderItemId()));
        ProductApi.delete(productId, true);

        //验证运行后数据是否正确
        Assert.assertEquals(ShopWalletApi.getMongoShopWalletLogBO(orderNum, true).size(), 1);
        Assert.assertEquals(ShopWalletApi.getOrderDetailVO(orderNum, true).getOrderItemDetailList().get(0).getActualTotal(), 7800);
        Assert.assertEquals(ShopWalletApi.getOrderDetailVO(orderNum, true).getOrderItemDetailList().get(0).getPlatformCommission(), 155);
    }

    @Test(description = "JK_63,未发货退货成功定金预售订单", dataProvider = "depositPreSaleProduct")
    public void refundDepositPreSaleOrderTestCase(Long productId) throws InterruptedException {
        MyOrderApi.confirm(OrderDtoData.getOrderDtoData(productId, 1));
        Long orderNum = MyOrderApi.submit(SubmitOrderDtoData.getSubmitOrderDtoData(productId)).get(0);
        PayApi.orderPay(orderNum);
        TimeUnit.SECONDS.sleep(2L);
        PayApi.orderPayBalance(orderNum);
        //申请第一次退款，部分退款 等待保存
        TimeUnit.SECONDS.sleep(2L);
        Long refundId = OrderRefundApi.apply(OrderRefundDtoData.getOrderRefundDTO(orderNum,0L));
        ShopOrderRefundApi.infoByRefundSn(refundId);
        ShopOrderRefundApi.processRefundOrder(ShopOrderRefundDtoData.getReceiveRefundDTO(refundId));
        ProductApi.delete(productId, true);

        //验证运行后数据是否正确
        Assert.assertEquals(ShopWalletApi.getMongoShopWalletLogBO(orderNum, true).size(), 2);
        Assert.assertEquals(ShopWalletApi.getOrderDetailVO(orderNum, true).getOrderItemDetailList().get(0).getActualTotal(), 7800);
        Assert.assertEquals(ShopWalletApi.getOrderDetailVO(orderNum, refundId, true).getOrderItemDetailList().get(0).getRefundAmount(), 7800);
        Assert.assertEquals(ShopWalletApi.getOrderDetailVO(orderNum, true).getOrderItemDetailList().get(0).getPlatformCommission(), 155);
    }

    @Test(description = "JK_64,多次退款失败，退货成功定金预售订单", dataProvider = "depositPreSaleProduct")
    public void multiRefundDepositPreSaleOrderTestCase(Long productId) throws InterruptedException {
        MyOrderApi.confirm(OrderDtoData.getOrderDtoData(productId, 1));
        Long orderNum = MyOrderApi.submit(SubmitOrderDtoData.getSubmitOrderDtoData(productId)).get(0);
        PayApi.orderPay(orderNum);
        TimeUnit.SECONDS.sleep(2L);
        PayApi.orderPayBalance(orderNum);
        //申请第一次退款，部分退款 等待保存
        TimeUnit.SECONDS.sleep(2L);
        Long refundIdFirst= OrderRefundApi.apply(OrderRefundDtoData.getOrderRefundDTO(orderNum,0L));
        ShopOrderRefundApi.infoByRefundSn(refundIdFirst);
        ShopOrderRefundApi.processRefundOrder(ShopOrderRefundDtoData.getRufuseOrderRefundDTO(refundIdFirst));

        //申请第二次退款，整单退款
        TimeUnit.SECONDS.sleep(2L);
        Long refundIdSec= OrderRefundApi.apply(OrderRefundDtoData.getAllOrderRefundDTO(orderNum));
        ShopOrderRefundApi.infoByRefundSn(refundIdSec);
        ShopOrderRefundApi.processRefundOrder(ShopOrderRefundDtoData.getRufuseOrderRefundDTO(refundIdSec));
        //发货后对订单进行部分退款仅退款 & 整单退货退款：先同意退款申请，发货后拒绝退款
        OrderApi.delivery(DeliveryOrderDtoData.getNoDeliveryOrderDtoData(orderNum));
        TimeUnit.SECONDS.sleep(2L);
        Long refundIdTir= OrderRefundApi.apply(OrderRefundDtoData.getOrderRefundDTO(orderNum,0L));
        ShopOrderRefundApi.infoByRefundSn(refundIdTir);
        ShopOrderRefundApi.processRefundOrder(ShopOrderRefundDtoData.getRufuseOrderRefundDTO(refundIdTir));

        TimeUnit.SECONDS.sleep(2L);
        Long refundIdFourth= OrderRefundApi.apply(OrderRefundDtoData.getAllOrderRefundDeliveryDTO(orderNum));
        ShopOrderRefundApi.infoByRefundSn(refundIdFourth);
        ShopOrderRefundApi.processRefundOrder(ShopOrderRefundDtoData.getReceiveRefundDTO(refundIdFourth));
        OrderRefundApi.submitExpress(OrderRefundDeliveryDtoData.getOrderRefundDeliveryDTO(refundIdFourth));
        TimeUnit.SECONDS.sleep(1L);
        ShopOrderRefundApi.returnMoney(ShopOrderRefundDtoData.getRefuseDeliveryRefundDTO(refundIdFourth));
        //确认收货后，对订单进行部分退款仅退款 & 整单退货退款且同意
        MyOrderApi.receipt(orderNum);
        TimeUnit.SECONDS.sleep(2L);
        Long refundIdFirth= OrderRefundApi.apply(OrderRefundDtoData.getOrderRefundDTO(orderNum,0L));
        ShopOrderRefundApi.infoByRefundSn(refundIdFirth);
        ShopOrderRefundApi.processRefundOrder(ShopOrderRefundDtoData.getRufuseOrderRefundDTO(refundIdFirth));

        TimeUnit.SECONDS.sleep(2L);
        Long refundIdSixth= OrderRefundApi.apply(OrderRefundDtoData.getAllOrderRefundDeliveryDTO(orderNum));
        ShopOrderRefundApi.infoByRefundSn(refundIdSixth);
        ShopOrderRefundApi.processRefundOrder(ShopOrderRefundDtoData.getReceiveRefundDTO(refundIdSixth));
        OrderRefundApi.submitExpress(OrderRefundDeliveryDtoData.getOrderRefundDeliveryDTO(refundIdSixth));
        ShopOrderRefundApi.returnMoney(ShopOrderRefundDtoData.getReceiveDeliveryRefundDTO(refundIdSixth));

        ProductApi.delete(productId, true);

        //验证运行后数据是否正确
        TimeUnit.SECONDS.sleep(2L);
        Assert.assertEquals(ShopOrderRefundApi.getEsOrderRefundVO(orderNum).size(), 6);
        Assert.assertEquals(ShopWalletApi.getMongoShopWalletLogBO(orderNum, true).size(), 2);
        Assert.assertEquals(ShopWalletApi.getOrderDetailVO(orderNum, true).getOrderItemDetailList().get(0).getActualTotal(), 7800);
        Assert.assertEquals(ShopWalletApi.getOrderDetailVO(orderNum, refundIdSixth, true).getOrderItemDetailList().get(0).getRefundAmount(), 7800);
        Assert.assertEquals(ShopWalletApi.getOrderDetailVO(orderNum, true).getOrderItemDetailList().get(0).getPlatformCommission(), 155);
    }

    @Test(description = "JK_65, 门店提货自提定金预售订单", dataProvider = "depositPreSaleProduct")
    public static void stationPickUpAdminDepositPreSaleOrder(Long productId) throws InterruptedException {
        MyOrderApi.confirm(OrderDtoData.getPickUpOrderDtoData(productId, 1));
        Long orderNum = MyOrderApi.submit(SubmitOrderDtoData.getPickUpSubmitOrderDtoData(productId)).get(0);
        PayApi.orderPay(orderNum);
        TimeUnit.SECONDS.sleep(2L);
        PayApi.orderPayBalance(orderNum);
        TimeUnit.SECONDS.sleep(2L);
        StationApi.getStationOrderByCode(MyOrderApi.stationOrderDetail(orderNum).getStationCode());
        StationApi.orderStationById(orderNum.toString());
        MyOrderApi.receipt(orderNum);
        CommentApi.addComment(SpuCommDtoData.getSpuCommDtoData(OrderApi.getOrderItemAndAddress(orderNum).getOrderItems().get(0).getOrderItemId()));
        ProductApi.delete(productId, true);

        //验证运行后数据是否正确
        Assert.assertEquals(ShopWalletApi.getMongoShopWalletLogBO(orderNum, true).size(), 1);
        Assert.assertEquals(ShopWalletApi.getOrderDetailVO(orderNum, true).getOrderItemDetailList().get(0).getActualTotal(), 7800);
        Assert.assertEquals(ShopWalletApi.getOrderDetailVO(orderNum, true).getOrderItemDetailList().get(0).getPlatformCommission(), 155);
    }

    @Test(description = "JK_66, 同城配送定金预售订单流程", dataProvider = "depositPreSaleProduct")
    public static void sameCityDepositPreSaleOrder(Long productId) throws InterruptedException {
        SameCityApi.saveSameCity(SameCityDtoData.getSameCityDTO());
        MyOrderApi.confirm(OrderDtoData.getSameCityOrderDtoData(productId, 1));
        Long orderNum = MyOrderApi.submit(SubmitOrderDtoData.getSubmitOrderDtoData(productId)).get(0);
        PayApi.orderPay(orderNum);
        TimeUnit.SECONDS.sleep(2L);
        PayApi.orderPayBalance(orderNum);
        OrderApi.delivery(DeliveryOrderDtoData.getSameCityDeliveryOrderDtoData(orderNum));
        MyOrderApi.receipt(orderNum);
        CommentApi.addComment(SpuCommDtoData.getSpuCommDtoData(OrderApi.getOrderItemAndAddress(orderNum).getOrderItems().get(0).getOrderItemId()));
        ProductApi.delete(productId, true);

        //验证运行后数据是否正确
        Assert.assertEquals(ShopWalletApi.getMongoShopWalletLogBO(orderNum, true).size(), 1);
        Assert.assertEquals(ShopWalletApi.getOrderDetailVO(orderNum, true).getOrderItemDetailList().get(0).getActualTotal(), 7800);
        Assert.assertEquals(ShopWalletApi.getOrderDetailVO(orderNum, true).getOrderItemDetailList().get(0).getPlatformCommission(), 155);
    }

    @Test(description = "JK_67,多次退款失败，退货成功全款预售订单", dataProvider = "fullPreSaleProduct")
    public void multiRefundFullPreSaleOrderTestCase(Long productId) throws InterruptedException {
        MyOrderApi.confirm(OrderDtoData.getOrderDtoData(productId, 1));
        Long orderNum = MyOrderApi.submit(SubmitOrderDtoData.getSubmitOrderDtoData(productId)).get(0);
        PayApi.orderPay(orderNum);
        //申请第一次退款，部分退款 等待保存
        TimeUnit.SECONDS.sleep(2L);
        Long refundIdFirst= OrderRefundApi.apply(OrderRefundDtoData.getOrderRefundDTO(orderNum,0L));
        ShopOrderRefundApi.infoByRefundSn(refundIdFirst);
        ShopOrderRefundApi.processRefundOrder(ShopOrderRefundDtoData.getRufuseOrderRefundDTO(refundIdFirst));

        //申请第二次退款，整单退款
        TimeUnit.SECONDS.sleep(2L);
        Long refundIdSec= OrderRefundApi.apply(OrderRefundDtoData.getAllOrderRefundDTO(orderNum));
        ShopOrderRefundApi.infoByRefundSn(refundIdSec);
        ShopOrderRefundApi.processRefundOrder(ShopOrderRefundDtoData.getRufuseOrderRefundDTO(refundIdSec));
        //发货后对订单进行部分退款仅退款 & 整单退货退款：先同意退款申请，发货后拒绝退款
        OrderApi.delivery(DeliveryOrderDtoData.getNoDeliveryOrderDtoData(orderNum));
        TimeUnit.SECONDS.sleep(2L);
        Long refundIdTir= OrderRefundApi.apply(OrderRefundDtoData.getOrderRefundDTO(orderNum,0L));
        ShopOrderRefundApi.infoByRefundSn(refundIdTir);
        ShopOrderRefundApi.processRefundOrder(ShopOrderRefundDtoData.getRufuseOrderRefundDTO(refundIdTir));

        TimeUnit.SECONDS.sleep(2L);
        Long refundIdFourth= OrderRefundApi.apply(OrderRefundDtoData.getAllOrderRefundDeliveryDTO(orderNum));
        ShopOrderRefundApi.infoByRefundSn(refundIdFourth);
        ShopOrderRefundApi.processRefundOrder(ShopOrderRefundDtoData.getReceiveRefundDTO(refundIdFourth));
        OrderRefundApi.submitExpress(OrderRefundDeliveryDtoData.getOrderRefundDeliveryDTO(refundIdFourth));
        TimeUnit.SECONDS.sleep(1L);
        ShopOrderRefundApi.returnMoney(ShopOrderRefundDtoData.getRefuseDeliveryRefundDTO(refundIdFourth));
        //确认收货后，对订单进行部分退款仅退款 & 整单退货退款且同意
        MyOrderApi.receipt(orderNum);
        TimeUnit.SECONDS.sleep(2L);
        Long refundIdFirth= OrderRefundApi.apply(OrderRefundDtoData.getOrderRefundDTO(orderNum,0L));
        ShopOrderRefundApi.infoByRefundSn(refundIdFirth);
        ShopOrderRefundApi.processRefundOrder(ShopOrderRefundDtoData.getRufuseOrderRefundDTO(refundIdFirth));

        TimeUnit.SECONDS.sleep(2L);
        Long refundIdSixth= OrderRefundApi.apply(OrderRefundDtoData.getAllOrderRefundDeliveryDTO(orderNum));
        ShopOrderRefundApi.infoByRefundSn(refundIdSixth);
        ShopOrderRefundApi.processRefundOrder(ShopOrderRefundDtoData.getReceiveRefundDTO(refundIdSixth));
        OrderRefundApi.submitExpress(OrderRefundDeliveryDtoData.getOrderRefundDeliveryDTO(refundIdSixth));
        ShopOrderRefundApi.returnMoney(ShopOrderRefundDtoData.getReceiveDeliveryRefundDTO(refundIdSixth));

        ProductApi.delete(productId, true);

        //验证运行后数据是否正确
        TimeUnit.SECONDS.sleep(2L);
        Assert.assertEquals(ShopOrderRefundApi.getEsOrderRefundVO(orderNum).size(), 6);
        Assert.assertEquals(ShopWalletApi.getMongoShopWalletLogBO(orderNum, true).size(), 2);
        Assert.assertEquals(ShopWalletApi.getOrderDetailVO(orderNum, true).getOrderItemDetailList().get(0).getActualTotal(), 8800);
        Assert.assertEquals(ShopWalletApi.getOrderDetailVO(orderNum, refundIdSixth, true).getOrderItemDetailList().get(0).getRefundAmount(), 8800);
        Assert.assertEquals(ShopWalletApi.getOrderDetailVO(orderNum, true).getOrderItemDetailList().get(0).getPlatformCommission(), 175);
    }
}
