package com.template.controller;

import com.seewo.open.sdk.DefaultSeewoClient;
import com.seewo.open.sdk.SeewoClient;
import com.seewo.open.sdk.auth.Account;
import com.template.common.utils.TimeExchange;
import com.template.config.ScheduleConfig;
import com.template.config.SeewoConfig;
import com.template.model.pojo.SmartAttendance;
import com.template.model.pojo.SmartClass;
import com.template.model.pojo.SmartUser;
import com.template.model.result.CommonResult;
import com.template.model.seewo.*;
import com.template.services.SmartAttendanceService;
import com.template.services.SmartClassService;
import com.template.services.SmartUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;


@Component
//@EnableAsync
public class ScheduleController {

    @Resource
    private SeewoConfig seewoConfig;

    @Resource
    private ScheduleConfig scheduleConfig;

    @Autowired
    private SmartClassService smartClassService;

    @Autowired
    private SmartUserService smartUserService;

    @Autowired
    private SmartAttendanceService smartAttendanceService;


    /**
     * @Scheduled注解会在默认情况下以单线程的方式执行定时任务。 这个“单线程”指两个方面：
     * 如果一个定时任务执行时间大于其任务间隔时间，那么下一次将会等待上一次执行结束后再继续执行。
     * 如果多个定时任务在同一时刻执行，任务会依次执行。
     * @Async：对某个方法进行异步执行
     * @EnableAsync：开启异步支持
     */

    //定时格式参考：https://blog.csdn.net/java13992394428/article/details/108740453

    /**
     * 每天八点自动派单
     * 周六周日定时器不生效
     * 其余时间都是早上八点前捞一遍当前时间以前的单子
     * 有合适的维修师傅就把单子派给维修师傅
     * 周一到周五早上七点执行：0 0 7 ? * MON-FRI
     * 周一到周五1、2、3、4、5、6、7、18、19、20、21、22点执行：0 0 1,2,3,4,5,6,7,18,19,20,21,22 ? * MON-FRI
     */
    //凌晨两点：0 0 2 * * ?
    //每小时执行一次：0 0 */1 * * ?
    //每分钟执行一次：0 */1 * * * ?
    //周一到周五早上七点执行：0 0 7 ? * MON-FRI
    @Async
    @Scheduled(cron = "0 */1 * * * ? ")
    @Transactional(rollbackFor = {Exception.class})
    public void autoDispatch() throws Exception {

        if (scheduleConfig.getIsOpen().equals("1")) {

            List<SmartAttendance> attendances = new ArrayList<>();
            List<SmartUser> students = smartUserService.queryStudentDatas();

            //循环班级的classUid
            List<SmartClass> classes = smartClassService.getSmartClasss();

            //当天已存在的考勤数据 判断是否重复使用
            List<SmartAttendance> attendanceList = smartAttendanceService.queryAttendances(TimeExchange.getStartOfDayStr(new Date()), TimeExchange.getEndOfDayStr(new Date()));

            for (SmartClass data : classes) {
                //region 获取考勤事件ID
                //初始化客户端
                SeewoClient seewoClient = new DefaultSeewoClient(new Account(seewoConfig.getAppId(), seewoConfig.getAppSecret()));
                AttendanceRuleListEventByClazzParam kParam = new AttendanceRuleListEventByClazzParam();
                //响应体，MimeType为 application/json
                AttendanceRuleListEventByClazzParam.RequestBody kRequestBody = AttendanceRuleListEventByClazzParam.RequestBody.builder()
                        .build();
                kParam.setRequestBody(kRequestBody);
                //query
                AttendanceRuleListEventByClazzParam.Query kQuery = AttendanceRuleListEventByClazzParam.Query.builder()
                        .appId(seewoConfig.getAppId())
                        .schoolUid(seewoConfig.getSchoolId())
                        .date(TimeExchange.getDate())
                        .classUid(data.getClassUid())
                        .page(1)
                        .pageSize(20)
                        .build();
                kRequestBody.setQuery(kQuery);
                kParam.setRequestBody(kRequestBody);
                AttendanceRuleListEventByClazzRequest kRequest = new AttendanceRuleListEventByClazzRequest(kParam);
                System.out.println("入参：" + kRequest);
                //如果想要调用沙箱环境，请通过设置 request 对象的 serverUrl 属性，如：
                //request.setServerUrl("https://openapi.test.seewo.com")
                //执行请求，如果想获取到com.seewo.open.sdk.HttpResponse对象，请调用 seewoClient.execute 方法
                AttendanceRuleListEventByClazzResult kResult = seewoClient.invoke(kRequest);
                System.out.println("出参：" + kResult);

                //考勤事件ID
                List<String> eventIds = new ArrayList<>();

                if (kResult != null && kResult.getResponseBody().getCode().equals("000000")) {
                    List<AttendanceRuleListEventByClazzResult.EventsItem> eventItems = kResult.getResponseBody().getData().getEvents();
                    for (AttendanceRuleListEventByClazzResult.EventsItem eventItem : eventItems) {
                        eventIds.add(eventItem.getRuleId());
                    }
                }
                //endregion

                for (String eventId : eventIds) {
                    /**
                     * 定时获取考勤
                     */
                    //初始化客户端
                    //SeewoClient seewoClient = new DefaultSeewoClient(new Account(seewoConfig.getAppId(), seewoConfig.getAppSecret()));
                    AttendanceServiceListAttendClassRecordsParam param = new AttendanceServiceListAttendClassRecordsParam();
                    //响应体，MimeType为 application/json
                    AttendanceServiceListAttendClassRecordsParam.RequestBody requestBody = AttendanceServiceListAttendClassRecordsParam.RequestBody.builder()
                            .build();
                    param.setRequestBody(requestBody);
                    //query
                    AttendanceServiceListAttendClassRecordsParam.Query query = AttendanceServiceListAttendClassRecordsParam.Query.builder()
                            .eventId(eventId)//考勤事件ID 固定写死
                            .attendDate(TimeExchange.getDate())//考勤日期
                            .appId(seewoConfig.getAppId())//appid
                            .grade(1)//年级序号
                            .classUid(data.getClassUid())//班级uid 班级uid与年级序号、班级序号二选一确定具体的班级，如果都填以classUid为准
                            .schoolUid(seewoConfig.getSchoolId())//学校uid
                            .attendType(1)//考勤类型 时间考勤（默认）：1  课程考勤：2
                            .build();
                    requestBody.setQuery(query);
                    param.setRequestBody(requestBody);
                    AttendanceServiceListAttendClassRecordsRequest request = new AttendanceServiceListAttendClassRecordsRequest(param);
                    System.out.println("入参：" + request);
                    //如果想要调用沙箱环境，请通过设置 request 对象的 serverUrl 属性，如：
                    //request.setServerUrl("https://openapi.test.seewo.com")
                    //执行请求，如果想获取到com.seewo.open.sdk.HttpResponse对象，请调用 seewoClient.execute 方法
                    AttendanceServiceListAttendClassRecordsResult result = seewoClient.invoke(request);
                    System.out.println("出参：" + result);

                    if (result != null && result.getResponseBody().getCode().equals("000000")) {
                        String userUid = "";
                        List<AttendanceServiceListAttendClassRecordsResult.RecordsItem> items = result.getResponseBody().getData().getRecords();
                        if (students != null && students.size() > 0) {
                            for (AttendanceServiceListAttendClassRecordsResult.RecordsItem item : items) {
                                Optional<SmartUser> student = students.stream().filter(e -> e.getXwStudentUid().equals(item.getUserUid())).findFirst();
                                if(student != null && student.isPresent()){

                                    Optional<SmartAttendance> existData = attendanceList.stream().filter(e -> e.getUserId().equals(student.get().getId())
                                    && e.getClassId().equals(student.get().getSchoolClass()) && e.getAttendTime().equals(TimeExchange.StringToDate((TimeExchange.getDate() + " " + item.getAttendTime()),"yyyy-MM-dd HH:mm:ss"))).findFirst();
                                    if(!(existData != null && existData.isPresent())){
                                        SmartAttendance attendance = new SmartAttendance();
                                        attendance.setUserId(student.get().getId());
                                        attendance.setUserUid(item.getUserUid());
                                        attendance.setClassId(student.get().getSchoolClass());
                                        attendance.setClassUid(result.getResponseBody().getData().getClassUid());
                                        attendance.setXwUserName(item.getUserName());
                                        attendance.setXwStudentCode(item.getStudentCode());
                                        attendance.setAttendTime(TimeExchange.StringToDate((TimeExchange.getDate() + " " + item.getAttendTime()),"yyyy-MM-dd HH:mm:ss"));
                                        attendance.setStatus(item.getStatus());
                                        attendances.add(attendance);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if(attendances.size() > 0){
                smartAttendanceService.saveBatch(attendances);
            }
        }
    }
}
