package com.xiaomai.cases.lunar.reserve;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xiaomai.basetest.BaseTestImpl;
import com.xiaomai.cases.lunar.user.UserTools;
import com.xiaomai.cases.polar.course.CourseTools;
import com.xiaomai.cases.polar.finance.order.OrderTools;
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.client.DataUserInfo;
import com.xiaomai.enums.ApiModule;
import com.xiaomai.enums.LoginAccount;
import com.xiaomai.enums.Terminal;
import com.xiaomai.utils.CommUtil;
import com.xiaomai.utils.TimeUtils;
import com.xiaomai.utils.XMJSONPath;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

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

/**
 * @BelongsProject: xm-sportstest
 * @BelongsPackage: com.xiaomai.cases.lunar.reserve
 * @Author: xuyamei
 * @CreateTime: 2024-07-30  14:44
 * @Description: 单次预约
 * @Version: 1.0
 */
public class TestCreateSingleReserve extends BaseTestImpl {
    @Resource(name = "userTools")
    UserTools userTools;

    @Resource(name = "reserveCTools")
    ReserveCTools reserveCTools;

    @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;

    @Resource(name = "orderTools")
    OrderTools orderTools;


    String todayStartTimeTamp = CommUtil.oneKeyGetAddDay(1);


    //获取今天结束日期的时间戳
    String todayEndDateTimeTamp = CommUtil.getNDayEndTimeTamp(1);
    Long scheduleEndTime = TimeUtils.getTodayEndTime(1);
    private String ruldId;
    private String reserveId;
    private String scheduleId;
    private Long startTime;
    private String courseId;
    private String memberId;
    private String chiefCoachId;
    private String voucherId;
    private String benefitId;


    @BeforeMethod
    @Override
    public void beforeTest(){
        setTestInfo(ApiModule.Lunar_Reserve,"API_createSingleReserve", LoginAccount.GYM_MINIAPPC, Terminal.minApp,"xym");
        super.beforeTest();
    }

    @Test(description = "小程序单次团课预约")
    public void testCreateSingleReserve() {
        DataUserInfo dataUserInfo = new DataUserInfo();
        dataUserInfo.setTerminal(Terminal.B);
        dataUserInfo.setLoginUser(LoginAccount.GYM_PROD);
        // 预约规则开启允许排队
        JSONObject getRules = ruleTools.getGroupBookingRules(); // 获取场馆团课预约规则
        String id = getRules.getString("id"); // 获取规则id
        Random random = new Random();
        int bookingSeatCount = random.nextInt(10)+1; // 席位
        ruleTools.saveGroupBookingRules(id,true,bookingSeatCount,true,true,random.nextInt(30)+10,false,random.nextInt(100)+10,random.nextInt(5)+1,false,random.nextInt(100)+10,"minutes",false,random.nextInt(100)+10,"minutes");

        memberId = userTools.getMemberInfo().getString("memberId");
        // 创建团课课次
        createGroupSchedule();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        // 课次详情获取上课老师和
        JSONObject memberScheduleItemDetail = reserveCTools.getMemberScheduleItemDetail(scheduleId, memberId);
        startTime = memberScheduleItemDetail.getLongValue("startTime");
        chiefCoachId = memberScheduleItemDetail.getString("chiefCoachId");

        // 校验会员加入课次是否有冲突
        boolean checkMemberConflict = reserveCTools.checkMemberConflict(memberId,scheduleId);
        if (checkMemberConflict){
            Assert.assertTrue(true,"校验会员有课次冲突");
        }

        // 检查是否支持预约
        String checkAddSingleReserve = reserveCTools.checkAddSingleReserve(false,courseId,chiefCoachId,memberId,scheduleId,startTime,10,0);
        Assert.assertEquals(checkAddSingleReserve,"SUCCESS","支持单次付费约课但返回的不是SUCCESS");

        // 创建单次付费约课
        voucherId = reserveCTools.createSingleReserve(false,courseId,chiefCoachId,memberId,scheduleId,startTime,10,0);

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        // 通过订单id获取单次约课任务信息
        JSONObject getDetail = reserveCTools.getDetailById(voucherId);
        // 验证单次约课信息
        String[] result = {"scheduleStartTime","spanMinutes","reserveState","courseId","memberId","scheduleId","courseType","accountType"};
        String[] expect = {String.valueOf(startTime),"10","SUCCESS",courseId,memberId,scheduleId,"GROUP_CLASS","SINGLE_RESERVE"};
        for (int i = 0; i < result.length-2; i++){
            Assert.assertEquals(getDetail.getString(result[i]),expect[i],getDetail.getString(result[i])+"返回值与预期值不一致:"+expect[i]);
        }
        reserveId = getDetail.getString("reserveId");
        benefitId = getDetail.getString("id");

        // check 1：查询小程序课次详情，学员是预约状态
        String[] result1 = {"reserveState","memberId","scheduleId","accountType"};
        String[] expect1 = {"SUCCESS",memberId,scheduleId,"SINGLE_RESERVE"};
        memberScheduleItemDetail = reserveCTools.getMemberScheduleItemDetail(scheduleId,memberId);
        for(int i = 0;i<4;i++) {
            Assert.assertEquals(memberScheduleItemDetail.getJSONObject("memberScheduleInfoVO").getString(result1[i]), expect1[i], "预约产生的数据与实际数据不符合" + result[i] + "：" + expect[i]);
        }

        // check 2：查询小程序预约记录
        JSONArray getPageByMember = reserveCTools.getPageByMember("SUCCESS","",startTime,scheduleEndTime,memberId,"GROUP_CLASS");
        boolean 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++){
                    String resultString = result[j].equals("reserveId")?"id":result[j];
                    Assert.assertEquals(getPageByMember.getJSONObject(i).getString(resultString),expect[j],"预约产生的数据与实际数据不符合"+result[j]+"："+expect[j]);
                }
                Assert.assertEquals(getPageByMember.getJSONObject(i).getString("memberId"),memberId,"查询的预约数据不是同一个会员");
            }
        }
        Assert.assertTrue(success,"预约记录没有查询到相关信息");
        // check 3：查询小程序预约详情
        JSONObject getDetailById = reserveCTools.getReserveDetailById(reserveId);
        for(int j = 0;j<result.length;j++){
            String resultString = result[j].equals("reserveId")?"id":result[j];
            Assert.assertEquals(getDetailById.getString(resultString),expect[j],"单次预约产生的数据与实际数据不符合"+result[j]+"："+expect[j]);
        }
        Assert.assertEquals(getDetailById.getString("memberId"),memberId,"查询的数据不是同一个会员");

        // check 4：查询B端预约详情
        result = new String[] {"id","benefitId","benefitType","reserveMemberNum","courseId","courseType","scheduleStartTime","reserveState","scheduleId","accountType"};
        expect = new String[] {reserveId,benefitId,"STORED_VALUE","1",courseId,"GROUP_CLASS",startTime+"","SUCCESS",scheduleId,"SINGLE_RESERVE"};
        getDetailById = reserveTools.getDetailById(reserveId,dataUserInfo);
        for(int j = 0;j<result.length;j++){
            Assert.assertEquals(getDetailById.getString(result[j]),expect[j],"单次预约产生的数据与实际数据不符合"+result[j]+"："+expect[j]);
        }
        Assert.assertEquals(getDetailById.getString("memberId"),memberId,"查询的单次预约数据不是同一个会员");


        // check 5：查询B端课次详情
        // 课次学员是否包含该会员 且 消耗方式为单次约课
        JSONObject getScheduleItemDetail = groupScheduleTools.getScheduleItemDetail(scheduleId,dataUserInfo);
        JSONArray reserveIds = getScheduleItemDetail.getJSONArray("memberReserveList");
        success = false;
        for (int i = 0; i < reserveIds.size(); i++){
            if(reserveIds.getJSONObject(0).getString("id").equals(reserveId)){
                success = true;
                for (int j = 0; j < result.length; j++){
                    Assert.assertEquals(reserveIds.getJSONObject(0).getString(result[j]),expect[j],"单次预约产生的数据与实际数据不符合"+result[j]+"："+expect[j]);
                }
            }
        }
        Assert.assertTrue(success,"约课后课次详情学员不在课次中");
    }



    @Test(priority = 2,description = "取消单次约课")
    public void cancelMemberReserve(){
        reserveCTools.cancelMemberReserve(reserveId,memberId,true);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        DataUserInfo dataUserInfo = new DataUserInfo();
        dataUserInfo.setTerminal(Terminal.B);
        dataUserInfo.setLoginUser(LoginAccount.GYM_PROD);

         String[] result = {"memberOperation","memberId","scheduleId"};
         String[] expect = {"TO_RESERVE",memberId,scheduleId};
        // check 1：查询小程序课次详情，学员是预约状态
        JSONObject memberScheduleItemDetail = reserveCTools.getMemberScheduleItemDetail(scheduleId,memberId);
        for(int i = 0;i<result.length;i++) {
            Assert.assertEquals(memberScheduleItemDetail.getJSONObject("memberScheduleInfoVO").getString(result[i]), expect[i], "取消预约产生的数据与实际数据不符合" + result[i] + "：" + expect[i]);
        }

        // 验证单次约课信息
        result = new String[]{"scheduleStartTime","spanMinutes","reserveState","courseId","memberId","scheduleId","courseType","accountType","refundState"};
        expect = new String[]{String.valueOf(startTime),"10","RESERVE_CANCEL",courseId,memberId,scheduleId,"GROUP_CLASS","SINGLE_RESERVE","NO_REFUND"};

        // check 2：查询小程序预约记录
        JSONArray getPageByMember = reserveCTools.getPageByMember("RESERVE_CANCEL","",startTime,scheduleEndTime,memberId,"GROUP_CLASS");
        boolean 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++){
                    String resultString = result[j].equals("reserveId")?"id":result[j];
                    Assert.assertEquals(getPageByMember.getJSONObject(i).getString(resultString),expect[j],"取消预约产生的数据与实际数据不符合"+result[j]+"："+expect[j]);
                }
                Assert.assertEquals(getPageByMember.getJSONObject(i).getString("memberId"),memberId,"查询的预约数据不是同一个会员");
            }
        }
        Assert.assertTrue(success,"取消预约记录没有查询到相关信息");
        // check 3：查询小程序预约详情
        JSONObject getDetailById = reserveCTools.getReserveDetailById(reserveId);
        for(int j = 0;j<result.length;j++){
            String resultString = result[j].equals("reserveId")?"id":result[j];
            Assert.assertEquals(getDetailById.getString(resultString),expect[j],"单次取消预约产生的数据与实际数据不符合"+result[j]+"："+expect[j]);
        }
        Assert.assertEquals(getDetailById.getString("memberId"),memberId,"查询的数据不是同一个会员");

        // check 4：查询B端预约详情
        result = new String[] {"id","benefitId","benefitType","reserveMemberNum","courseId","courseType","scheduleStartTime","reserveState","scheduleId","accountType","refundState"};
        expect = new String[] {reserveId,benefitId,"STORED_VALUE","1",courseId,"GROUP_CLASS",startTime+"","RESERVE_CANCEL",scheduleId,"SINGLE_RESERVE","NO_REFUND"};
        getDetailById = reserveTools.getDetailById(reserveId,dataUserInfo);
        for(int j = 0;j<result.length;j++){
            Assert.assertEquals(getDetailById.getString(result[j]),expect[j],"单次取消预约产生的数据与实际数据不符合"+result[j]+"："+expect[j]);
        }
        Assert.assertEquals(getDetailById.getString("memberId"),memberId,"查询的单次预约数据不是同一个会员");


        // check 5：查询B端课次详情
        // 课次学员是否包含该会员 且 消耗方式为单次约课
        JSONObject getScheduleItemDetail = groupScheduleTools.getScheduleItemDetail(scheduleId,dataUserInfo);
        JSONArray reserveIds = getScheduleItemDetail.getJSONArray("reserveIds");
        Assert.assertTrue(reserveIds.size()==0,"取消约课后课次详情学员还在课次中");

        // check 6：查询订单状态为已作废
        JSONObject fetchDetailById = orderTools.getDetail(voucherId,dataUserInfo);
        Assert.assertEquals(fetchDetailById.getJSONObject("result").getString("state"),"DISCARD","单次付费约课取消订单状态不是已作废");
        Assert.assertEquals(fetchDetailById.getJSONObject("result").getString("discardMemo"),"取消预约/排队，自动作废订单","单次付费约课取消备注不是：取消预约/排队，自动作废订单");

    }


    @Test(priority = 3)
    public void del(){
        DataUserInfo dataUserInfo = new DataUserInfo();
        dataUserInfo.setTerminal(Terminal.B);
        dataUserInfo.setLoginUser(LoginAccount.GYM_PROD);
        // 删除排课数据
        groupScheduleTools.delGroupRuleSchedule(ruldId,true,dataUserInfo);
        // 删除课次
        groupScheduleTools.delGroupScheduleItem(scheduleId,dataUserInfo);
    }

    // 创建团课课次
    public void createGroupSchedule(){
        DataUserInfo dataUserInfo = new DataUserInfo();
        dataUserInfo.setTerminal(Terminal.B);
        dataUserInfo.setLoginUser(LoginAccount.GYM_PROD);
        // 查询存量的约课课程
        // 查询存量的课程分类
        String categoryId = courseCategoryTools.getCourseCategoryPage("瑜伽");
        courseId = courseTools.getPersonalOrGroupCourseId("GROUP", "单次付费约课团课", categoryId, "STUDIO", "", 2, 1,dataUserInfo).getString(0);
        // 修改课程支持单次约课
        courseTools.editGroupCourse(categoryId,courseId,"单次付费约课团课",10,true,0,dataUserInfo);
        // 创建排课
        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, dataApi.getLoginInfo().getAdminId(), todayStartTimeTamp, todayEndDateTimeTamp, new ArrayList(), new ArrayList(), true, 1,minuteOffset[random.nextInt(20)],dataUserInfo);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        //1.2-查询排课日程
        JSONArray getGroupRuleScheduleList = groupScheduleTools.getGroupRuleScheduleList(courseId, dataApi.getLoginInfo().getAdminId(),dataUserInfo);
        //统计查询到的目标日程数量
        ruldId = XMJSONPath.readPath(getGroupRuleScheduleList.getJSONObject(0), "$.ruleId");
        Long scheduleEndTime = TimeUtils.getTodayEndTime(1);
        try {
            Thread.sleep(2500);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        // 查询课次id
        JSONArray memberTimetable = reserveCTools.memberTimetable(memberId,Long.valueOf(todayStartTimeTamp), scheduleEndTime);
        for (int i = 0; i < memberTimetable.size(); i++){
            if (memberTimetable.getJSONObject(i).containsKey("ruleId") && memberTimetable.getJSONObject(i).getString("ruleId").equals(ruldId)){
                scheduleId = memberTimetable.getJSONObject(i).getString("scheduleId");
                break;
            }
        }


    }


}


