package com.template.controller;

import com.alibaba.fastjson.JSON;
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.SmartGrade;
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.SmartGradeService;
import com.template.services.SmartUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 org.springframework.util.StringUtils;

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 {

    private static Logger logger = LoggerFactory.getLogger(ScheduleController.class);

    @Resource
    private SeewoConfig seewoConfig;

    @Resource
    private ScheduleConfig scheduleConfig;

    @Autowired
    private SmartClassService smartClassService;

    @Autowired
    private SmartGradeService smartGradeService;

    @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
    //0 0 22 * * ?
    @Async
    @Scheduled(cron = "0 0 22 * * ? ")
    @Transactional(rollbackFor = {Exception.class})
    public void autoDispatch() throws Exception {

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

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

//            SmartUser studentData = smartUserService.getSmartById(1088);
//            students.add(studentData);

                //循环班级的classUid
                List<SmartClass> classes = smartClassService.getSmartClasss();
                List<SmartGrade> grades = smartGradeService.list(null);

//            SmartClass classData = smartClassService.getSmartClassById(204);
//            classes.add(classData);

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

                for (SmartClass data : classes) {

                    if (data.getName().equals("七年级21班")) {
                        String sd = "";
                    }
                    Optional<SmartGrade> oGrade = grades.stream().filter(e -> e.getId().equals(data.getGradeId())).findFirst();
                    //region 获取考勤事件ID
                    //初始化客户端
                    SeewoClient seewoClient = new DefaultSeewoClient(new Account(seewoConfig.getAppId(), seewoConfig.getAppSecret()));
                    AttendanceRuleListEventByClazzParam param = new AttendanceRuleListEventByClazzParam();
                    //响应体，MimeType为 application/json
                    AttendanceRuleListEventByClazzParam.RequestBody requestBody = AttendanceRuleListEventByClazzParam.RequestBody.builder()
                            .build();
                    param.setRequestBody(requestBody);
                    //query
                    AttendanceRuleListEventByClazzParam.Query query = AttendanceRuleListEventByClazzParam.Query.builder()
                            .appId(seewoConfig.getAppId())
                            .schoolUid(seewoConfig.getSchoolId())
                            .date(TimeExchange.getDate())
                            .classUid(data.getClassUid())
                            .page(1)
                            .pageSize(20)
                            .build();
                    requestBody.setQuery(query);
                    AttendanceRuleListEventByClazzRequest request = new AttendanceRuleListEventByClazzRequest(param);
                    // 该接口需要数据权限，请将授权资源id替换至下方，请妥善保管好授权资源id，避免泄露
                    // permissionId位置: 控制台 -> 应用详情 -> 我申请的 -> 已通过的接口 -> 调用范围 -> 审批信息 中查看授权资源的「学校id」或「区域id」
                    request.setPermissionId("");
                    logger.info("入参：" + request);
                    //执行请求，如果想获取到com.seewo.open.sdk.HttpResponse对象，请调用 seewoClient.execute 方法
                    AttendanceRuleListEventByClazzResult result = seewoClient.invoke(request);
                    logger.info("出参：" + result);
                    //endregion

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

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

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

                        if (kResult != null && kResult.getResponseBody().getCode().equals("000000")) {
                            List<AttendanceServiceListAttendClassRecordsResult.RecordsItem> items = kResult.getResponseBody().getData().getRecords();
                            if (students != null && students.size() > 0 && items != null && items.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()) &&  StringUtils.hasText(item.getAttendTime()) && e.getAttendTime().equals(TimeExchange.StringToDate((TimeExchange.getDate() + " " + item.getAttendTime()), "yyyy-MM-dd HH:mm:ss"))).findFirst();
                                        if (!(existData != null && existData.isPresent())) {
                                            if(item.getStatus().intValue() != 6){//请假数据不通过考勤接口拿 因为考勤给的请假数据没有请假原因和请假时长
                                                SmartAttendance attendance = new SmartAttendance();
                                                attendance.setUserId(student.get().getId());
                                                attendance.setUserUid(item.getUserUid());
                                                attendance.setClassId(student.get().getSchoolClass());
                                                attendance.setClassUid(kResult.getResponseBody().getData().getClassUid());
                                                attendance.setXwUserName(item.getUserName());
                                                attendance.setXwStudentCode(item.getStudentCode());
                                                attendance.setAttendTime(StringUtils.hasText(item.getAttendTime()) ? TimeExchange.StringToDate((TimeExchange.getDate() + " " + item.getAttendTime()), "yyyy-MM-dd HH:mm:ss") : new Date());
                                                attendance.setStatus(item.getStatus());
                                                attendances.add(attendance);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                if (attendances.size() > 0) {
                    smartAttendanceService.saveBatch(attendances);
                }
            }
        } catch (Exception e) {
            logger.info("考勤定时任务失败：" + e.getMessage());
            throw new Exception("考勤定时任务失败" + e.getMessage());
        }

    }


}
