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

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xiaomai.basetest.BaseTestImpl;
import com.xiaomai.cases.polar.coupon.CouponTools;
import com.xiaomai.cases.polar.course.CourseTools;
import com.xiaomai.cases.polar.memberCard.CardTools;
import com.xiaomai.cases.polar.reserve.ReserveTools;
import com.xiaomai.cases.polar.setting.courseCategory.CourseCategoryTools;
import com.xiaomai.enums.ApiModule;
import com.xiaomai.enums.LoginAccount;
import com.xiaomai.enums.Terminal;
import com.xiaomai.utils.CommUtil;
import com.xiaomai.utils.XMJSONPath;
import org.springframework.util.CollectionUtils;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

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

import java.util.List;
import java.util.stream.Collectors;

/**
 * 批量代预约一对一私教课
 *
 * @author adu
 * data 2024/10/30 17:53
 */

public class TestBatchReserve1v1Personal extends BaseTestImpl {
    @Resource(name = "courseCategoryTools")
    CourseCategoryTools courseCategoryTools;
    @Resource(name = "courseTools")
    CourseTools courseTools;

    @Resource(name = "couponTools")
    CouponTools couponTools;

    TestReservePerson testReservePerson = new TestReservePerson();

    @Resource(name = "reserveTools")
    ReserveTools reserveTools;
    CardTools cardTools = new CardTools();
    //获取目标日期范围的时间戳下周一～下周日
    String endDate = CommUtil.oneKeyGetNextWeekEndDay();
    String startDate = CommUtil.oneKeyGetNextWeekStartDay();

    private String benefitId;
    private String memberId;
    private String course1v1Id;
    private String coachedId = "1851503867506028545";

    private String areaIdAll = "1851832978975846403";

    private String areaIdLV1 = "1851832978975846404";
    private String areaIdLV2 = "1851832978975846405";

    private String categoryId = "";
    private String memberCardId;
    List<String> reserveIds = new ArrayList<>();

    @BeforeClass
    @Override
    public void beforeTest() {
        setTestInfo(ApiModule.Polar_Reserve, "API_batchReservePersonal", LoginAccount.ADU_PROD, Terminal.B, "adu");
        super.beforeTest();
    }

    /**
     * 造轮子如下
     * 存量员工：员工只授课私教 员工ID：1851503867506028545 （自动化批量代预约私教（勿动））
     * 提前给员工设置好私教时间，常规可约时间1. 周二，周四，周五 15：00～16：00，19：30～20：30  2.周六，周日 18：20～19：20
     * 存量学员：1816039970498064385，学员手机号：17682302508，姓名：李四-测试机吴彦祖
     * 存量私教课程1v1和1vN（没有会创建）
     * 私教预约设置：1对多私教预约人数设置，每个会员每节课最多可以约2个席位
     * 场地：私教场地专用：1851832978975846403，2个子场LV1：1851832978975846404，LV2：1851832978975846405
     */
    @Test(description = "测试批量代预约1v1私教课")
    public void testBatchReserve1v1Personal() throws InterruptedException {
        //1：造轮子
        //1.1 获取目标教练对应的1v1私教课课程，没有则新建
        // 查询存量的课程分类
        categoryId = courseCategoryTools.getCourseCategoryPage("力量训练");
        courseTools.getPersonalPage("ON", 0, "", "", "ONE_TO_ONE", coachedId);
        int targetData = XMJSONPath.getJSONArrayByReadPath(dataApi.getApi_response(), "$.result.records").size();
        String targetAreaId = "1851832978975846405";
        //1.2 存量教练
        JSONArray coachIds = new JSONArray();
        coachIds.add(coachedId);
        //1.3 存量场地
        JSONArray areaIds = new JSONArray();
        areaIds.add(areaIdLV1);
        areaIds.add(areaIdLV2);
        areaIds.add(areaIdAll);
        if (targetData == 0) {
            //如果没有对应的私教课，则新建教练对应的私教课程
            course1v1Id = courseTools.createPersonalCourse("阿杜自动化批量代预约1v1私教课", categoryId, "STUDIO", "ONE_TO_ONE",
                    1, 1, coachIds, areaIds);

        } else {
            JSONObject obj = XMJSONPath.getJSONArrayByReadPath(dataApi.getApi_response(), "$.result.records").toJavaList(JSONObject.class).stream()
                    .filter(e -> !CollectionUtils.isEmpty(e.getJSONArray("areaIds"))).findFirst().orElse(null);
            if (null != obj) {
                course1v1Id = obj.getString("brandCourseId");
                int size = obj.getJSONArray("areaIds").size();
                //获取可选场地的最后1个
                targetAreaId = obj.getJSONArray("areaIds").getString(size - 1);
            } else {
                //如果有对应的私教课，但是私教课没设置场地，那么再新建个私教课
                course1v1Id = courseTools.createPersonalCourse("杜君丽自动化批量代预约1v1私教课", categoryId, "STUDIO", "ONE_TO_ONE",
                        1, 1, coachIds, areaIds);
            }
        }

        String selectDate2 = CommUtil.oneKeyGetNextWeekXDay(8);//下周二日期时间戳
        String selectDate4 = CommUtil.oneKeyGetNextWeekXDay(10);//下周四日期时间戳

        //1.4 上课计划筛选条件准备好后，为防止有数据问题，先检查下私教课表，对应时间段是否有课次，如果有则删除课次
        reserveTools.getPersonalScheduleTable(Long.valueOf(startDate), Long.valueOf(endDate), course1v1Id);
        List<String> scheduleIds = XMJSONPath.getJSONArrayByReadPath(dataApi.getApi_response(), "$.result.timetableGroups")
                .toJavaList(JSONObject.class)
                .stream()
                .filter(e->selectDate2.equals(e.getString("date"))||selectDate4.equals(e.getString("date")))
                .flatMap(e -> e.getJSONArray("timetableList").toJavaList(JSONObject.class).stream())//重新组建新的数据流
                .filter(object -> 1170 == object.getInteger("minuteOffset"))
                .map(o -> o.getString("scheduleId"))
                .collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(scheduleIds)) {
            //如果目标时间有课次，则删除课次
            scheduleIds.stream().forEach(id -> {
                reserveTools.delPersonalScheduleItem(id);
            });

        }


        //2：根据筛选条件获取上课日期，并选择日期 周二和周四
        Integer[] weekDaysArray = {2, 3, 4, 5};//周三时间没配置
        List<Integer> weekdaysList = Arrays.asList(weekDaysArray);
        reserveTools.getPersonalBatchReserveTimeBlockList(course1v1Id, coachedId, startDate, endDate, 1, 1170, 60, weekdaysList,targetAreaId);//19：30～20：30
        //check 返回结果是否和预期一致
        Assert.assertTrue(XMJSONPath.getJSONArrayByReadPath(dataApi.getApi_response(), "$.result").size() == 4, "目标日期有4个，目前数量对不上");
        //下周三日期是不可约check【非私教可约时间】
        String conflictDate = CommUtil.oneKeyGetNextWeekXDay(9);//下周三日期时间戳
        JSONObject conflictObj = XMJSONPath.getJSONArrayByReadPath(dataApi.getApi_response(), "$.result").toJavaList(JSONObject.class).stream()
                .filter(e -> conflictDate.equals(e.getString("reserveDate"))).findFirst().orElse(null);
        Assert.assertTrue(null != conflictObj, "没有获取到下周三的数据");
        Assert.assertTrue(Boolean.valueOf(conflictObj.getString("canReserve")).equals(false), "下周三日期应该不能选择预约，因为没设置私教时间，现在返回的是可约，请检查");
        Assert.assertTrue("非私教可约时间".equals(conflictObj.getString("cannotReserveReason")), "下周三日期应该不能选择预约，因为没设置私教时间，原因应该是：非私教可约时间，现在返回的不是哦，请检查");

        //3：选择预约学员
        //3.1查询存量的学员，如果没有则新建
        JSONArray memberInfo = testReservePerson.createMember("李四-测试机吴彦祖", course1v1Id);
        System.out.println("memberInfo******" + memberInfo);
        // memberInfo******["1816039970498064385","1851923531241930753","1851923531233542145"],参考出处： members.add(memberId);members.add(benefitId);members.add(memberCardId); 以后建议用map或者对象存，用key来获取
        memberId = memberInfo.getString(0);
        benefitId = memberInfo.getString(1);
        memberCardId = memberInfo.getString(2);

        //3.2操作确认预约
        List<JSONObject> reserveDayInfoList = new ArrayList<>();

        JSONObject selectDate2Ob = new JSONObject();
        selectDate2Ob.put("reserveDate", selectDate2);
        reserveDayInfoList.add(selectDate2Ob);
        JSONObject selectDate4Ob = new JSONObject();
        selectDate4Ob.put("reserveDate", selectDate4);
        reserveDayInfoList.add(selectDate4Ob);
        reserveTools.batchReservePersonal(1, memberId, benefitId, course1v1Id, coachedId, 1170, reserveDayInfoList, 1, 60,targetAreaId);
        Assert.assertTrue(Boolean.valueOf(XMJSONPath.readPath(dataApi.getApi_response(), "$.success")) == true, "调用接口返回结果：" + XMJSONPath.readPath(dataApi.getApi_response(), "$.message"));
        String taskId1V1 = XMJSONPath.readPath(dataApi.getApi_response(), "$.result");

        //4:任务中心check
        Thread.sleep(4000);
        couponTools.getStudioBatchTaskPage();
        Long goalTask = XMJSONPath.getJSONArrayByReadPath(dataApi.getApi_response(), "$.result.records").toJavaList(JSONObject.class).stream().filter(e ->
                e.getString("id").equals(taskId1V1)).count();
        Assert.assertTrue(goalTask == 1, "刚操作批量预约私教课，在任务中心查看，后端没返回目标数据");
        //4.1 check发送状态成功， 发送1个学员，2条成功，0条失败
        XMJSONPath.getJSONArrayByReadPath(dataApi.getApi_response(), "$.result.records").toJavaList(JSONObject.class).stream().filter(e ->
                e.getString("id").equals(taskId1V1)).forEach(object ->
                Assert.assertTrue("SUCCESS".equals(object.getString("state")) && 2 == object.getInteger("totalNumber") && 0 == object.getInteger("failNumber") &&
                        2 == object.getInteger("successNumber")));

        //5：查询课表，获取课次ID，预约记录ID，学员ID
        reserveTools.getPersonalScheduleTable(Long.valueOf(startDate), Long.valueOf(endDate), course1v1Id);
        Assert.assertTrue(XMJSONPath.getJSONArrayByReadPath(dataApi.getApi_response(), "$.result.timetableGroups").size() >= 2, "下周私教课次刚预约生成2个课次，但是目前返回的不是至少2课次");

        List<JSONObject> dataInfo = XMJSONPath.getJSONArrayByReadPath(dataApi.getApi_response(), "$.result.timetableGroups")
                .toJavaList(JSONObject.class)
                .stream()
                // .filter(e -> e.getDate("date").after(new Date())) //针对具体的筛选时间
                .filter(e -> e.getJSONArray("timetableList").toJavaList(JSONObject.class).stream().anyMatch(o -> 1170 == o.getInteger("minuteOffset")))
                .map(e -> new JSONObject()
                        .fluentPut("date", e.getString("date"))
                        .fluentPut("timetableList", e.getJSONArray("timetableList").toJavaList(JSONObject.class).stream().map(
                                o -> new JSONObject().fluentPut("scheduleId", o.getString("scheduleId"))
                                        .fluentPut("reserveIds", o.getJSONArray("reserveIds"))
                                        .fluentPut("memberIds", o.getJSONArray("memberIds"))
                        ).collect(Collectors.toList()))
                ).collect(Collectors.toList());

        Assert.assertTrue(dataInfo.size() == 2, "目标数据只有2条，但是获取的到数据不等于2");
        //5.1查看对应课次中是否有对应的预约学员
        dataInfo.stream().forEach(e ->
                {
                    if (selectDate2.equals(e.getString("date")) || selectDate4.equals(e.getString("date"))) {
                        Assert.assertTrue(null != e.getJSONArray("timetableList").getJSONObject(0).getJSONArray("memberIds") && e.getJSONArray("timetableList").getJSONObject(0).getJSONArray("memberIds").size() == 1);
                        Assert.assertTrue(memberId.equals(e.getJSONArray("timetableList").getJSONObject(0).getJSONArray("memberIds").getString(0)), "约课后课次详情学员不在课次中");
                    }
                }
        );
        //6：cehck预约记录是否包含该预约
        // 6.1 check学员详情预约记录（比对课次ID）
        JSONArray getPageByMember = reserveTools.getPageByMember(course1v1Id, "SUCCESS", "", coachedId, Long.valueOf(startDate), Long.valueOf(endDate), memberId, "PERSONAL");
        Assert.assertTrue(getPageByMember.size() >= 2, "下周该学员已约私教课目前不足2条，请检查");
        System.out.println("getPageByMember===========" + getPageByMember);
        List<String> scheduleIdList = getPageByMember.toJavaList(JSONObject.class).stream().map(o -> o.getString("scheduleId")).collect(Collectors.toList());

        List<String> tableScheduleIds = dataInfo.stream().flatMap(e -> e.getJSONArray("timetableList").toJavaList(JSONObject.class).stream())//重新组建新的数据流
                .map(o -> o.getString("scheduleId"))
                .collect(Collectors.toList());
        Assert.assertTrue(CollectionUtils.isEmpty(scheduleIdList.stream().filter(id -> !tableScheduleIds.contains(id)).collect(Collectors.toList())), "约课后在会员详情页面未查询到相关信息");


        // 6.2 check 预约记录列表（比对预约记录ID）
        JSONArray getPageByStudio = reserveTools.getPageByStudio(course1v1Id, "SUCCESS", "", coachedId, Long.valueOf(startDate), Long.valueOf(endDate), memberId, "PERSONAL", "");
        Assert.assertTrue(getPageByStudio.size() >= 2, "下周已给学员批量代预约私教课2节，目前查到的相关记录不足2条，请检查");
        reserveIds = getPageByStudio.toJavaList(JSONObject.class).stream().map(o -> o.getString("id")).collect(Collectors.toList());
        List<String> tableReserveIds = dataInfo.stream().flatMap(e -> e.getJSONArray("timetableList").toJavaList(JSONObject.class).stream())//重新组建新的数据流
                .map(o -> o.getJSONArray("reserveIds").getString(0))
                .collect(Collectors.toList());
        Assert.assertTrue(CollectionUtils.isEmpty(reserveIds.stream().filter(id -> !tableReserveIds.contains(id)).collect(Collectors.toList())), "约课后在约课记录页面未查询到相关信息");

        //7: check会员卡消耗记录中包含该记录锁定
        JSONArray consumeRecord = cardTools.fetchPageOfConsumeRecord(benefitId, memberCardId).getJSONObject("result").getJSONArray("records");
        if (consumeRecord.size() > 0) {
            reserveIds.stream().forEach(e -> {
                Long count = consumeRecord.toJavaList(JSONObject.class).stream().filter(o -> e.equals(o.getString("resourceId")) && "RESERVE".equals(o.getString("consumeType")) && "-1.00".equals(o.getString("changeOfUsablePurchaseBalance"))).count();
                Assert.assertTrue(count == 1, "消耗记录中没有对应的已预约记录");
            });
        }


    }

    @Test(description = "取消一对一私教课，课次删除", priority = 1)
    public void testCancel1v1ReservePersonal() {
        if (reserveIds.size() > 0) {
            reserveIds.stream().forEach(reserveId -> {
                        reserveTools.cancelMemberReserve(reserveId, true);
                        try {
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }

                        // check 1：课次已删除,课表没有该条数据
                        reserveTools.getPersonalScheduleTable(Long.valueOf(startDate), Long.valueOf(endDate), course1v1Id);
                        JSONArray timetableGroups=XMJSONPath.getJSONArrayByReadPath(dataApi.getApi_response(), "$.result.timetableGroups");
                        if(timetableGroups.size()>0){
                            List<String> scheduleIds = timetableGroups.toJavaList(JSONObject.class)
                                    .stream()
                                    .flatMap(e -> e.getJSONArray("timetableList").toJavaList(JSONObject.class).stream())//重新组建新的数据流
                                    .filter(object -> 1170 == object.getInteger("minuteOffset") && reserveId.equals(object.getJSONArray("reserveIds").getString(0)))
                                    .map(o -> o.getString("scheduleId"))
                                    .collect(Collectors.toList());
                            Assert.assertTrue(CollectionUtils.isEmpty(scheduleIds), "取消约课后课次未删除");
                        }


                        // check 2：会员详情 - 预约记录已取消
                        JSONArray getPageByMember = reserveTools.getPageByMember(course1v1Id, "RESERVE_CANCEL", "", coachedId, Long.valueOf(startDate), Long.valueOf(endDate), memberId, "PERSONAL");
                        getPageByMember.toJavaList(JSONObject.class).stream().filter(e -> reserveId.equals(e.getString("id"))).forEach(o -> {
                            Assert.assertTrue("RESERVE_CANCEL".equals(o.getString("reserveState")), "取消约课状态不是已取消");
                        });


                        // check 3：预约记录列表中已取消
                        JSONArray getPageByStudio = reserveTools.getPageByStudio(course1v1Id, "RESERVE_CANCEL", "", coachedId, Long.valueOf(startDate), Long.valueOf(endDate), memberId, "PERSONAL", "");
                        getPageByStudio.toJavaList(JSONObject.class).stream().filter(e -> reserveId.equals(e.getString("id"))).forEach(o -> {
                            Assert.assertTrue("RESERVE_CANCEL".equals(o.getString("reserveState")), "取消约课状态不是已取消");
                        });


                        // check 4： 会员卡消耗记录中包含该记录锁定的次数释放
                        JSONArray consumeRecord = cardTools.fetchPageOfConsumeRecord(benefitId, memberCardId).getJSONObject("result").getJSONArray("records");
                        if (consumeRecord.size() > 0) {
                            Long count = consumeRecord.toJavaList(JSONObject.class).stream().filter(o -> reserveId.equals(o.getString("resourceId")) && "CANCEL_RESERVE".equals(o.getString("consumeType")) && "1.00".equals(o.getString("changeOfUsablePurchaseBalance"))).count();
                            Assert.assertTrue(count == 1, "消耗记录中没有对应的已取消记录");
                        }

                    }
            );


        }
    }



}

    