package com.xiaomai.cases.polar.reserve.group;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xiaomai.basetest.BaseTestImpl;
import com.xiaomai.cases.polar.clue.MemberTools;
import com.xiaomai.cases.polar.course.CourseTools;
import com.xiaomai.cases.polar.finance.order.OrderTools;
import com.xiaomai.cases.polar.member.Tools;
import com.xiaomai.cases.polar.memberCard.CardTools;
import com.xiaomai.cases.polar.reserve.ReserveTools;
import com.xiaomai.cases.polar.schedule.group.GroupScheduleTools;
import com.xiaomai.cases.polar.setting.courseCategory.CourseCategoryTools;
import com.xiaomai.cases.polar.setting.rules.RuleTools;
import com.xiaomai.enums.ApiModule;
import com.xiaomai.enums.LoginAccount;
import com.xiaomai.enums.Terminal;
import com.xiaomai.utils.CommUtil;
import com.xiaomai.utils.RandomStringUtil;
import com.xiaomai.utils.TimeUtils;
import com.xiaomai.utils.XMJSONPath;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Random;

/**
 * @BelongsProject: xm-sportstest
 * @BelongsPackage: com.xiaomai.cases.polar.reserve
 * @Author: xuyamei
 * @CreateTime: 2024-06-11  18:25
 * @Description: 添加预约\取消预约
 * @Version: 1.0
 */
public class TestAddMemberReserve extends BaseTestImpl {
    @Resource(name = "courseCategoryTools")
    CourseCategoryTools courseCategoryTools;
    @Resource(name = "courseTools")
    CourseTools courseTools;

    @Resource(name = "reserveTools")
    ReserveTools reserveTools;

    @Resource(name = "groupScheduleTools")
    GroupScheduleTools groupScheduleTools;

    @Resource(name = "ruleTools")
    RuleTools ruleTools;

    MemberTools memberTools = new MemberTools();


    OrderTools orderTools = new OrderTools();
    CardTools cardTools = new CardTools();

    Tools tools = new Tools();

    String todayStartTimeTamp = CommUtil.oneKeyGetAddDay(0);

    //获取今天结束日期的时间戳
    String todayEndDateTimeTamp = CommUtil.getNDayEndTimeTamp(0);
    private String ruldId;
    private String scheduleId;
    private Long startTime;
    private String courseId;
    JSONArray memberInfo1 = new JSONArray();
    JSONArray memberInfo2 = new JSONArray();


    @BeforeMethod
    @Override
    public void beforeTest(){
        setTestInfo(ApiModule.Polar_Reserve,"API_addReserve", LoginAccount.GYM_PROD, Terminal.B,"xym");
        super.beforeTest();
    }

    @Test
    public void testAddMemberReserve(){
        // 查询存量的约课课程
        // 查询存量的课程分类
        String categoryId = courseCategoryTools.getCourseCategoryPage("瑜伽");
        courseId = courseTools.getPersonalOrGroupCourseId("GROUP", "空中瑜伽团课课程", categoryId, "STUDIO", "", 2, 1).getString(0);
        // 创建排课
        int[] minuteOffset = {60, 120, 180,  240, 300, 360,  420,  480, 540,  600,  660, 720, 780,  840,  900, 960, 1020, 1080, 1140, 1200, 1260};
        Random random = new Random();
        //1.1-创建排课日程
        groupScheduleTools.createGroupRuleSchedule(courseId, xmAppApi.getLoginInfo().getAdminId(), todayStartTimeTamp, todayEndDateTimeTamp, new ArrayList(), new ArrayList(), true, 1,minuteOffset[random.nextInt(20)]);
        //1.2-查询排课日程
        JSONArray getGroupRuleScheduleList = groupScheduleTools.getGroupRuleScheduleList(courseId, xmAppApi.getLoginInfo().getAdminId());
        //统计查询到的目标日程数量
        ruldId = XMJSONPath.readPath(getGroupRuleScheduleList.getJSONObject(0), "$.ruleId");
        System.out.println("----------ruldId---------"+ ruldId);
        Long scheduleStartTime = TimeUtils.getTodayTime();
        Long scheduleEndTime = TimeUtils.getTodayEndTime();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        // 查询课次id
        JSONArray getGroupScheduleTable = groupScheduleTools.getGroupScheduleTable(scheduleStartTime, scheduleEndTime,courseId);
        for (int i = 0; i < getGroupScheduleTable.size(); i++){
            if (getGroupScheduleTable.getJSONObject(i).containsKey("ruleId") && getGroupScheduleTable.getJSONObject(i).getString("ruleId").equals(ruldId)){
                scheduleId = getGroupScheduleTable.getJSONObject(i).getString("scheduleId");
                break;
            }
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        String memberId;
        // 查询存量的学员没有则创建学员
        if (tools.commonSearch("约课学员sandy","NORMAL").getJSONArray("result").size()>0){
            memberId = tools.commonSearch("约课学员sandy","NORMAL").getJSONArray("result").getJSONObject(0).getString("id");
        }else if (tools.commonSearch("约课学员sandy","HISTORY").getJSONArray("result").size()>0){
            memberId = tools.commonSearch("约课学员sandy","HISTORY").getJSONArray("result").getJSONObject(0).getString("id");
        }else if (tools.commonSearch("约课学员sandy","POTENTIAL").getJSONArray("result").size()>0){
            memberId = tools.commonSearch("约课学员sandy","POTENTIAL").getJSONArray("result").getJSONObject(0).getString("id");
        }else{
            memberId = memberTools.create("约课学员sandy", RandomStringUtil.randomMobile("203")).getString("result");
        }
        memberInfo1.add(memberId);


        // 查询是否有可用的会员卡，没有则购买
        JSONArray listUserReservableBenefit = cardTools.listUserReservableBenefit(courseId, "GROUP_CLASS", "MEMBER", memberId, TimeUtils.getTodayTime());
        if (listUserReservableBenefit.size() == 0) {
            // 购买适用的会员卡
            signOrder(courseId, memberId);
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            listUserReservableBenefit = cardTools.listUserReservableBenefit(courseId, "GROUP_CLASS", "MEMBER", memberId, TimeUtils.getTodayTime());
        }
        // 查询权益
        String benefitId = listUserReservableBenefit.getJSONObject(0).getString("benefitId");
        String memberCardId = listUserReservableBenefit.getJSONObject(0).getString("memberCardId");
        memberInfo1.add(benefitId);
        memberInfo1.add(memberCardId);


        // 查询课次详情 查课次的开始时间
        JSONObject getScheduleItemDetail = groupScheduleTools.getScheduleItemDetail(scheduleId);
        startTime = getScheduleItemDetail.getLongValue("startTime");
        // 预约
        String reserveId = reserveTools.addReserve("","",benefitId,xmAppApi.getLoginInfo().getAdminId(),memberId,1,scheduleId,startTime,true);
        memberInfo1.add(reserveId);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        // check 1：课次学员是否包含该会员
        getScheduleItemDetail = groupScheduleTools.getScheduleItemDetail(scheduleId);
        JSONArray reserveIds = getScheduleItemDetail.getJSONArray("reserveIds");
        boolean success = false;
        for (int i = 0; i < reserveIds.size(); i++){
            if(reserveIds.getString(i).equals(reserveId)){
                success = true;
            }
        }
        Assert.assertTrue(success,"约课后课次详情学员不在课次中");

        // check 2: 预约记录是否包含该预约
        // check 2.1 学员详情预约记录
        JSONArray getPageByMember = reserveTools.getPageByMember(courseId,"SUCCESS","","", startTime,scheduleEndTime,memberId,"GROUP_CLASS");
        String[] result = new String[] {"id","benefitId","reserveMemberNum","courseId","courseType","scheduleStartTime","reserveState","scheduleId"};
        String[] resultData = new String[] {reserveId,benefitId,"1",courseId,"GROUP_CLASS",startTime+"","SUCCESS",scheduleId};
        success = false;
        for(int i =0;i<getPageByMember.size();i++){
            if (getPageByMember.getJSONObject(i).getString("id").equals(reserveId)){
                success = true;
                for(int j = 0;j<result.length;j++){
                    Assert.assertEquals(getPageByMember.getJSONObject(i).getString(result[j]),resultData[j],"约课产生的数据与实际数据不符合"+result[j]+"："+resultData[j]);
                }
            }
        }
        Assert.assertTrue(success,"约课后在会员详情页面未查询到相关信息");
        // check 2.2 预约记录列表
        JSONArray getPageByStudio = reserveTools.getPageByStudio(courseId,"SUCCESS","","",startTime,scheduleEndTime,memberId,"GROUP_CLASS","");
        success = false;
        for(int i =0;i<getPageByStudio.size();i++){
            if (getPageByStudio.getJSONObject(i).getString("id").equals(reserveId)){
                success = true;
                for(int j = 0;j<result.length;j++){
                    Assert.assertEquals(getPageByStudio.getJSONObject(i).getString(result[j]),resultData[j],"约课产生的数据与实际数据不符合"+result[j]+"："+resultData[j]);
                }
                Assert.assertEquals(getPageByStudio.getJSONObject(i).getString("memberId"),memberId,"查询的约课数据不是同一个会员");
            }
        }
        Assert.assertTrue(success,"约课后在约课记录没有查询到相关信息");
        // check 2.3 预约记录详情
        JSONObject getDetailById = reserveTools.getDetailById(reserveId);
        for(int j = 0;j<result.length;j++){
            Assert.assertEquals(getDetailById.getString(result[j]),resultData[j],"约课产生的数据与实际数据不符合"+result[j]+"："+resultData[j]);
        }
        Assert.assertEquals(getDetailById.getString("memberId"),memberId,"查询的约课数据不是同一个会员");

        // check 3： 会员卡消耗记录中包含该记录锁定
        JSONArray consumeRecord = cardTools.fetchPageOfConsumeRecord(benefitId,memberCardId).getJSONObject("result").getJSONArray("records");
        String[] result2 = {"resourceId","consumeType","changeOfUsablePurchaseBalance"};
        String[] respect = {reserveId,"RESERVE","-1.00"};
        String[] message = {"会员卡消耗记录中记录的资源id与实际约课记录id不符合","会员卡消耗记录中记录的资源id与实际约课记录类型不符合","会员卡消耗记录中记录的资源id与实际约课记录余额不符合"};
        for (int i = 0; i < result2.length; i++){
            Assert.assertEquals(consumeRecord.getJSONObject(0).getString(result2[i]),respect[i],message[i]);
        }



    }

    @Test(priority = 1,description = "学员已经在课次中，无需重复添加")
    public void testAddMemberReserve2(){
        reserveTools.addReserve("","",memberInfo1.getString(1),xmAppApi.getLoginInfo().getAdminId(),memberInfo1.getString(0),1,scheduleId,startTime,false);
        String message = dataApi.getBodyInJSON().getString("message");
        Assert.assertTrue(message.equals("会员已约该课程，不可重复预约") || message.equals("预约失败，无需重复添加"));
    }

    @Test(priority = 2)
    public void testAddMemberReserve3(){
        //  修改课次人数上限为1
        groupScheduleTools.editGroupSchedule(scheduleId,startTime,xmAppApi.getLoginInfo().getAdminId(),1,1);

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        // 修改预约规则不允许排队
        JSONObject getRules = ruleTools.getGroupBookingRules(); // 获取场馆团课预约规则
        String id = getRules.getString("id"); // 获取规则id
        Random random = new Random();
        int bookingSeatCount = random.nextInt(10)+1; // 席位
        ruleTools.saveGroupBookingRules(id,false,bookingSeatCount,true,true,random.nextInt(30)+10,true,random.nextInt(100)+10,random.nextInt(5)+1,true,random.nextInt(100)+10,"minutes",true,random.nextInt(100)+10,"minutes");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        // 新学员 购买卡
        String memberId2 = "";
        // 查询存量的学员没有则创建学员
        if (tools.commonSearch("约课学员susan","NORMAL").getJSONArray("result").size()>0){
            memberId2 = tools.commonSearch("约课学员susan","NORMAL").getJSONArray("result").getJSONObject(0).getString("id");
        }else if (tools.commonSearch("约课学员susan","HISTORY").getJSONArray("result").size()>0){
            memberId2 = tools.commonSearch("约课学员susan","HISTORY").getJSONArray("result").getJSONObject(0).getString("id");
        }else if (tools.commonSearch("约课学员susan","POTENTIAL").getJSONArray("result").size()>0){
            memberId2 = tools.commonSearch("约课学员susan","POTENTIAL").getJSONArray("result").getJSONObject(0).getString("id");
        }else{
            memberId2 = memberTools.create("约课学员susan", RandomStringUtil.randomMobile("203")).getString("result");
        }
        memberInfo2.add(memberId2);

        // 查询是否有可用的会员卡，没有则购买
        JSONArray listUserReservableBenefit = cardTools.listUserReservableBenefit(courseId, "GROUP_CLASS", "MEMBER", memberId2, TimeUtils.getTodayTime());
        if (listUserReservableBenefit.size() == 0) {
            // 购买适用的会员卡
            signOrder(courseId, memberId2);
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            listUserReservableBenefit = cardTools.listUserReservableBenefit(courseId, "GROUP_CLASS", "MEMBER", memberId2, TimeUtils.getTodayTime());
        }
        String benefitId = listUserReservableBenefit.getJSONObject(0).getString("benefitId");
        String memberCardId = listUserReservableBenefit.getJSONObject(0).getString("memberCardId");
        memberInfo2.add(benefitId);
        memberInfo2.add(memberCardId);

        reserveTools.addReserve("","",benefitId,xmAppApi.getLoginInfo().getAdminId(),memberId2,1,scheduleId,startTime,true);
        String resultCode = dataApi.getBodyInJSON().getJSONObject("result").getString("resultCode");
        Assert.assertEquals(resultCode,"FULL_CAPACITY","课次已满员，但是返回的错误code不是FULL_CAPACITY："+resultCode);
    }

    @DataProvider
    public Object[][] dataProvider(){
        return new Object[][]{
                {true,"操作成功"},
                {false,"已取消预约，无需重复取消"}
        };

    }
    @Test(dataProvider = "dataProvider",priority = 3)
    public void testCancelMemberReserve(boolean success,String message){
        reserveTools.cancelMemberReserve(memberInfo1.getString(3),success);
        Assert.assertEquals(dataApi.getBodyInJSON().getString("message").contains(message),true);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        if (success){
            // check 1：课次学员是否包含该会员
            JSONObject getScheduleItemDetail = groupScheduleTools.getScheduleItemDetail(scheduleId);
            JSONArray reserveIds = getScheduleItemDetail.getJSONArray("reserveIds");
            success = false;
            for (int i = 0; i < reserveIds.size(); i++){
                if(reserveIds.getString(i).equals(memberInfo1.getString(3))){
                    success = true;
                }
            }
            Assert.assertFalse(success,"取消约课后课次详情学员还在课次中");

            // check 2：会员详情 - 预约记录已取消
            JSONArray getPageByMember = reserveTools.getPageByMember(courseId,"RESERVE_CANCEL","","", startTime,TimeUtils.getTodayEndTime(),memberInfo1.getString(0),"GROUP_CLASS");
            success = false;
            for(int i =0;i<getPageByMember.size();i++){
                if (getPageByMember.getJSONObject(i).getString("id").equals(memberInfo1.getString(3))){
                    success = true;
                }
            }
            Assert.assertTrue(success,"取消约课后查询取消状态在会员详情页面未查询到相关信息");

            // check 3：预约记录列表中已取消
            JSONArray getPageByStudio = reserveTools.getPageByStudio(courseId,"RESERVE_CANCEL","","",startTime,TimeUtils.getTodayEndTime(),memberInfo1.getString(0),"GROUP_CLASS","");
            success = false;
            for(int i =0;i<getPageByStudio.size();i++){
                if (getPageByStudio.getJSONObject(i).getString("id").equals(memberInfo1.getString(3))){
                    success = true;
                }
            }
            Assert.assertTrue(success,"取消约课后在约课记录查询取消状态没有查询到相关信息");

            // check 3： 会员卡消耗记录中包含该记录锁定的次数释放
            JSONArray consumeRecord = cardTools.fetchPageOfConsumeRecord(memberInfo1.getString(1),memberInfo1.getString(2)).getJSONObject("result").getJSONArray("records");
            String[] result2 = new String[] {"resourceId","consumeType","changeOfUsablePurchaseBalance"};
            String[] respect = new String[] {memberInfo1.getString(3),"CANCEL_RESERVE","1.00"};
            String[] message1 = new String[] {"会员卡消耗记录中记录的资源id与实际约课记录id不符合","会员卡消耗记录中记录的资源id与实际约课记录类型不符合","会员卡消耗记录中记录的资源id与实际约课记录余额不符合"};
            for (int i = 0; i < result2.length; i++){
                Assert.assertEquals(consumeRecord.getJSONObject(0).getString(result2[i]),respect[i],message1[i]);
            }

        }
    }

    @Test(priority = 4)
    public void del(){
        // 删除排课数据
        groupScheduleTools.delGroupRuleSchedule(ruldId,true);
        groupScheduleTools.delGroupScheduleItem(scheduleId);
    }




    // 买卡
    public void signOrder(String courseId,String memberId){
        // 查询存量的卡
        JSONObject fetchPageOfMemberCard = cardTools.fetchPageOfMemberCard(courseId,"MEMBER_CARD");
        int total = Integer.parseInt(fetchPageOfMemberCard.getString("total"));
        String cardId = "";
        BigDecimal quantity = new BigDecimal(0) ;
        float price = 0;
        int validPeriod = 0;
        if (total == 0) {
            cardId = cardTools.memberCardCreate("约课使用会员卡"+TimeUtils.getCurrentTime()).getString("result");
        }
        cardId = fetchPageOfMemberCard.getJSONArray("records").getJSONObject(0).getString("id");
        quantity =  new BigDecimal(fetchPageOfMemberCard.getJSONArray("records").getJSONObject(0).getJSONArray("benefitList").getJSONObject(0).getString("balance"));
        price = Float.parseFloat(fetchPageOfMemberCard.getJSONArray("records").getJSONObject(0).getString("price"));
        validPeriod = Integer.parseInt(fetchPageOfMemberCard.getJSONArray("records").getJSONObject(0).getString("validPeriod"));

        //获取签单要用的卡快照id
        String latestSnapshotId = orderTools.fetchDetailById(cardId,xmAppApi.getLoginInfo().getBrandId(),xmAppApi.getLoginInfo().getStudioId(),xmAppApi.getLoginInfo().getAdminId()).getJSONObject("result").getString("latestSnapshotId");

        //检查会员对该卡是否超出购买上限
        boolean limitResult= orderTools.checkAllowPurchase("MEMBER_CARD",cardId,cardId,"1",xmAppApi.getLoginInfo().getBrandId(),xmAppApi.getLoginInfo().getStudioId(),xmAppApi.getLoginInfo().getAdminId()).getBoolean("success");

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        if( limitResult == true){
            //创建订单
            JSONObject orderResult=orderTools.signOrder(cardId,latestSnapshotId,quantity,price,validPeriod,latestSnapshotId, price/2,"PURCHASE",
                    "MEMBER_CARD",memberId,price-price/2,price-price/2,"1");
        }
    }

}
