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.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.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.DataProvider;
import org.testng.annotations.Test;

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

/**
 * @BelongsProject: xm-sportstest
 * @BelongsPackage: com.xiaomai.cases.lunar.reserve
 * @Author: xuyamei
 * @CreateTime: 2024-06-26  16:05
 * @Description: 小程序签到
 * @Version: 1.0
 */
public class TestXCXSignIn 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;

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

    String todayStartTimeTamp = CommUtil.oneKeyGetAddDay(0);


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


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


    @DataProvider
    public Object[][] dataProvider() {
        return new Object[][]{
                // 参数说明：第一个参数：是否要重新预约，第二个参数：是否开启手动签到，第三个参数：是否开启扫码签到，第四个参数：签到前几分钟，第五个参数：备注
                {true,false,false,5,"SIGN_IN_CONFIG_CLOSED","签到失败，不支持直接确认签到","签到失败，不支持扫码签到","小程序扫码和手动签到关闭"},
                {false,true,false,5,"SIGN_IN_CONFIG_CLOSED","签到失败，课次未开始签到","签到失败，不支持扫码签到","小程序扫码签到关闭"},
                {false,false,true,5,"DO_NOT_START_SIGN_IN","签到失败，不支持直接确认签到","签到失败，课次未开始签到","小程序手动签到关闭"},
                {false,true,true,5,"DO_NOT_START_SIGN_IN","签到失败，课次未开始签到","签到失败，课次未开始签到","小程序扫码和手动签到开启，但是没有到可签到时间"},
                {false,true,true,999,"","","","小程序扫码和手动签到开启，可签到"},
                {false,true,true,5,"HAS_SIGNED","签到失败，已经签到，无需重复操作","签到失败，已经签到，无需重复操作","小程序扫码和手动签到开启，再次签到提示"},
                {true,true,true,990,"","","","小程序扫码和手动签到开启，可签到"}

        };
    }


    @Test(description = "造约课数据-->进行手动确认签到和扫码签到",dataProvider = "dataProvider")
    public void testXCXSignIn(boolean flag,boolean autoSignIn,boolean scanCode,int signInBeforeMinutes,String checkMessage,String signMessage,String scanMessage, String remark) {
        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, autoSignIn, scanCode, signInBeforeMinutes, false, random.nextInt(100) + 10, random.nextInt(5) + 1, false, random.nextInt(100) + 10, "minutes", false, random.nextInt(100) + 10, "minutes");

        if (flag) {
            memberId = userTools.getMemberInfo().getString("memberId");
            // 创建团课课次
            LocalDateTime currentDateTime = LocalDateTime.now();
            int hour = currentDateTime.getHour();
            int minutes = currentDateTime.getMinute();
            Random rand = new Random();
            int minute = signInBeforeMinutes == 990 ? hour*60+minutes-rand.nextInt(100)+10 : hour*60+minutes+10 ;
            createGroupSchedule(minute);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            // 获取会员权益
            memberInfo = getMemberBenefit(memberId);

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

            if (signInBeforeMinutes == 990){
                // B端代预约
                String reserveId = reserveTools.addReserve("","",memberInfo.getString(1),chiefCoachId,memberInfo.getString(0),1,scheduleId,startTime,true,dataUserInfo);
                memberInfo.set(2,reserveId);
            }else {
                String reserveId = reserveCTools.memberReserveAdd("", chiefCoachId, memberInfo.getString(1), "", memberInfo.getString(0), 1, scheduleId, startTime, true);
                if (memberInfo.size() > 2) {
                    memberInfo.set(2, reserveId);
                } else {
                    memberInfo.add(reserveId);
                }
            }

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


        }

        if (signInBeforeMinutes == 999){
            // 手动签到
            reserveCTools.signIn(true,memberInfo.getString(2),memberId);
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            checkResult("小程序扫码签到");
        } else if (signInBeforeMinutes == 990){

            // 扫码签到
            reserveCTools.signInByScanCode(true,scheduleId,memberId);
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            checkResult("小程序手动签到");
        }else{
            String code = reserveCTools.queryPreSignInCheck(true,scheduleId,memberId);
            Assert.assertEquals(code, checkMessage);

            // 扫码签到
            String message = reserveCTools.signIn(false,memberInfo.getString(2),memberId);
            Assert.assertEquals(message, signMessage);
            // 收到签到
            message = reserveCTools.signInByScanCode(false,scheduleId,memberId);
            Assert.assertEquals(message, scanMessage);
        }



    }




    public void createGroupSchedule(int minute){
        DataUserInfo dataUserInfo = new DataUserInfo();
        dataUserInfo.setTerminal(Terminal.B);
        dataUserInfo.setLoginUser(LoginAccount.GYM_PROD);
        // 查询存量的约课课程
        // 查询存量的课程分类
        String categoryId = courseCategoryTools.getCourseCategoryPage("瑜伽");
        courseId = courseTools.getPersonalOrGroupCourseId("GROUP", "C端点名瑜伽团课课程", categoryId, "STUDIO", "", 2, 1,dataUserInfo).getString(0);
        // 创建排课
        //1.1-创建排课日程
        groupScheduleTools.createGroupRuleSchedule(courseId, dataApi.getLoginInfo().getAdminId(), todayStartTimeTamp, todayEndDateTimeTamp, new ArrayList(), new ArrayList(), true, 1,minute,dataUserInfo);
        //1.2-查询排课日程
        JSONArray getGroupRuleScheduleList = groupScheduleTools.getGroupRuleScheduleList(courseId, dataApi.getLoginInfo().getAdminId(),dataUserInfo);
        //统计查询到的目标日程数量
        ruldId = XMJSONPath.readPath(getGroupRuleScheduleList.getJSONObject(0), "$.ruleId");
        System.out.println("--------"+ruldId);
        Long scheduleEndTime = TimeUtils.getTodayEndTime(0);
        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;
            }
        }
    }

    /**
     * @description:买卡
     * @author: xuyamei
     * @date:  2024/6/24 19:42
     * @param courseId 课程id
     * @param memberId 会员id
     * @return: void
     **/
    public void signOrder(String courseId,String memberId){
        DataUserInfo dataUserInfo = new DataUserInfo();
        dataUserInfo.setTerminal(Terminal.B);
        dataUserInfo.setLoginUser(LoginAccount.GYM_PROD);

        // 查询存量的卡
        JSONObject fetchPageOfMemberCard = cardTools.fetchPageOfMemberCard(courseId,"MEMBER_CARD",dataUserInfo);
        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(),dataUserInfo).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,dataApi.getLoginInfo().getBrandId(),dataApi.getLoginInfo().getStudioId(),dataApi.getLoginInfo().getAdminId(),dataUserInfo).getJSONObject("result").getString("latestSnapshotId");

        //检查会员对该卡是否超出购买上限
        boolean limitResult= orderTools.checkAllowPurchase("MEMBER_CARD",cardId,cardId,"1",dataApi.getLoginInfo().getBrandId(),dataApi.getLoginInfo().getStudioId(),dataApi.getLoginInfo().getAdminId(),dataUserInfo).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",true,dataUserInfo);
        }
    }


    /**
     * @description:查询会员是否购买会员卡，如果已购买则查看权益，如果没有则进行购买
     * @author: xuyamei
     * @date:  2024/6/24 19:43
     * @param memberId：会员id
     * @return:
     **/
    public JSONArray getMemberBenefit(String memberId){

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

        JSONArray members = new JSONArray();
        members.add(memberId);
        members.add(benefitId);
        return members;
    }


    public void checkResult(String mes){
        // check 1：查询小程序课次详情，学员是签到状态
        JSONObject memberScheduleItemDetail = reserveCTools.getMemberScheduleItemDetail(scheduleId,memberId);
        String[] result = new String[] {"memberId","scheduleId","reserveId","reserveState","benefitId","courseType","signInState"};
        String[] resultData = new String[] {memberInfo.getString(0),scheduleId,memberInfo.getString(2),"SUCCESS",memberInfo.getString(1),"GROUP_CLASS","SIGNED"};

        for(int j = 0;j<4;j++){
            Assert.assertEquals(memberScheduleItemDetail.getJSONObject("memberScheduleInfoVO").getString(result[j]),resultData[j],mes+"产生的数据与实际数据不符合"+result[j]+"："+resultData[j]);
        }


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

        // check 4：查询B端预约详情
        DataUserInfo dataUserInfo = new DataUserInfo();
        dataUserInfo.setTerminal(Terminal.B);
        dataUserInfo.setLoginUser(LoginAccount.GYM_PROD);

        result = new String[] {"id","benefitId","reserveMemberNum","courseId","courseType","scheduleStartTime","reserveState","scheduleId","signInState"};
        resultData = new String[] {memberInfo.getString(2),memberInfo.getString(1),"1",courseId,"GROUP_CLASS",startTime+"","SUCCESS",scheduleId,"SIGNED"};
        getDetailById = reserveTools.getDetailById(memberInfo.getString(2),dataUserInfo);
        for(int j = 0;j<result.length;j++){
            Assert.assertEquals(getDetailById.getString(result[j]),resultData[j],mes+"产生的数据与实际数据不符合"+result[j]+"："+resultData[j]);
        }
        Assert.assertEquals(getDetailById.getString("memberId"),memberInfo.getString(0),"查询的"+mes+"数据不是同一个会员");


        // check 5：课次学员是否包含该会员且会员状态为已签到
        JSONObject getScheduleItemDetail = groupScheduleTools.getScheduleItemDetail(scheduleId,dataUserInfo);
        JSONArray reserveIds = getScheduleItemDetail.getJSONArray("memberReserveList");
        success = false;
        for (int i = 0; i < reserveIds.size(); i++){
            if(reserveIds.getJSONObject(i).getString("id").equals(memberInfo.getString(2))){
                success = true;
                Assert.assertEquals(reserveIds.getJSONObject(i).getString("signInState"),"SIGNED","签到状态错误");
            }
        }
        Assert.assertTrue(success,"约课后点名课次详情学员不在课次中");
    }





}
