package com.xjrsoft.module.attendance.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.yulichang.toolkit.MPJWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.xjrsoft.common.model.result.RT;
import com.xjrsoft.module.attendance.dto.AttendanceStatisticDto;
import com.xjrsoft.module.attendance.vo.TeacherStatisticsVo;
import com.xjrsoft.module.attendance.vo.VisitorInfoVo;
import com.xjrsoft.module.concat.service.IXjrUserService;
import com.xjrsoft.module.organization.entity.UserDeptRelation;
import com.xjrsoft.module.outint.entity.StudentOutInRecord;
import com.xjrsoft.module.outint.entity.TeacherOutInRecord;
import com.xjrsoft.module.outint.service.IStudentOutInRecordService;
import com.xjrsoft.module.outint.service.ITeacherOutInRecordService;
import com.xjrsoft.module.personnel.service.IReservationSchoolService;
import com.xjrsoft.module.student.entity.BaseStudent;
import com.xjrsoft.module.student.entity.BaseStudentSchoolRoll;
import com.xjrsoft.module.student.service.IStudentLeaveService;
import com.xjrsoft.module.teacher.entity.BaseTeacher;
import com.xjrsoft.module.teacher.entity.XjrUser;
import com.xjrsoft.module.teacher.service.IWfTeacherleaveService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
* @title: 考勤消息设置
* @Author dzx
* @Date: 2024-05-21
* @Version 1.0
*/
@RestController
@RequestMapping("/statistics")
@Api(value = "/statistics" ,tags = "考勤统计")
@AllArgsConstructor
public class StatisticsController {


    private final IXjrUserService xjrUserService;
    private final ITeacherOutInRecordService teacherOutInRecordService;
    private final IStudentOutInRecordService studentOutInRecordService;
    private final IWfTeacherleaveService wfTeacherleaveService;
    private final IStudentLeaveService studentLeaveService;
    private final IReservationSchoolService reservationSchoolService;

    @GetMapping(value = "/teacher-statistics")
    @ApiOperation(value="教职工考勤统计")
    @SaCheckPermission("statistics:detail")
    public RT<TeacherStatisticsVo> teacherStatistics(@Valid AttendanceStatisticDto dto){
        TeacherStatisticsVo statisticsVo = new TeacherStatisticsVo();
        //查询总人数
        MPJLambdaWrapper<XjrUser> queryWrapper = MPJWrappers.<XjrUser>lambdaJoin()
                .disableSubLogicDel()
                .eq(ObjectUtil.isNotNull(dto.getDeptId()), UserDeptRelation::getDeptId, dto.getDeptId())
                .innerJoin(BaseTeacher.class,BaseTeacher::getUserId,XjrUser::getId)
                .innerJoin(UserDeptRelation.class, UserDeptRelation::getUserId, XjrUser::getId);
        long allCount = xjrUserService.count(queryWrapper);
        statisticsVo.setAllCount(allCount);
        if(dto.getDate() != null && !"".equals(dto.getDate())){
            DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE;
            LocalDate queryDate = LocalDate.parse(dto.getDate(), formatter);
            LocalDateTime startTime, endTime;
            if(dto.getTimePeriod() == 1){
                startTime = queryDate.atTime(9, 0, 0);
                endTime = queryDate.atTime(12, 0, 0);
            }else if(dto.getTimePeriod() == 2){
                startTime = queryDate.atTime(12, 0, 0);
                endTime = queryDate.atTime(18, 0, 0);
            }else{
                startTime = queryDate.atTime(0, 0, 0);
                endTime = queryDate.atTime(23, 59, 59);
            }

            List<TeacherOutInRecord> outInRecords = teacherOutInRecordService.list(
                    new QueryWrapper<TeacherOutInRecord>().lambda()
                            .between(TeacherOutInRecord::getRecordTime, startTime, endTime)
                            .eq(TeacherOutInRecord::getStatus, 1)
            );
            //实到人数
            statisticsVo.setActualCount(Long.valueOf(outInRecords.size()));

            //查询教师请假人数
            Long leaveCount = wfTeacherleaveService.getLeaveCount(startTime, endTime);
            if(leaveCount == null){
                leaveCount = 0L;
            }
            statisticsVo.setLeaveCount(leaveCount);

            //通过考勤规则和实到人数信息，计算迟到的
            Long lateCount = 0L;
            for (TeacherOutInRecord outInRecord : outInRecords) {
                if("迟到".equals(outInRecord.getAttendanceStatus())){
                    lateCount ++;
                }
            }
            statisticsVo.setLateCount(lateCount);

            //最后通过总人数-实到人数-请假人数计算出缺勤人数
            statisticsVo.setAbsenteeismCount(statisticsVo.getAllCount() - statisticsVo.getLeaveCount() - statisticsVo.getActualCount());

            //计算出勤率
            BigDecimal divide = BigDecimal.valueOf(statisticsVo.getActualCount()).divide(BigDecimal.valueOf(statisticsVo.getAllCount()), 4, RoundingMode.HALF_UP);
            statisticsVo.setAttendanceRate(divide.doubleValue());
        }

        return RT.ok(statisticsVo);
    }


    @GetMapping(value = "/student-statistics")
    @ApiOperation(value="学生考勤统计")
    @SaCheckPermission("statistics:detail")
    public RT<TeacherStatisticsVo> studentStatistics(@Valid AttendanceStatisticDto dto){
        TeacherStatisticsVo statisticsVo = new TeacherStatisticsVo();
        //查询总人数
        MPJLambdaWrapper<XjrUser> queryWrapper = MPJWrappers.<XjrUser>lambdaJoin()
                .disableSubLogicDel()
                .distinct()
                .eq(ObjectUtil.isNotNull(dto.getGradeId()), BaseStudentSchoolRoll::getGradeId, dto.getGradeId())
                .eq(ObjectUtil.isNotNull(dto.getClassId()), BaseStudentSchoolRoll::getClassId, dto.getClassId())
                .innerJoin(BaseStudentSchoolRoll.class, BaseStudentSchoolRoll::getUserId, XjrUser::getId)
                .innerJoin(BaseStudent.class, BaseStudent::getUserId, XjrUser::getId);
        long allCount = xjrUserService.count(queryWrapper);
        statisticsVo.setAllCount(allCount);
        if(dto.getDate() != null && !"".equals(dto.getDate())){
            DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE;
            LocalDate queryDate = LocalDate.parse(dto.getDate(), formatter);
            LocalDateTime startTime, endTime;
            if(dto.getTimePeriod() != null && dto.getTimePeriod() == 1){
                startTime = queryDate.atTime(9, 0, 0);
                endTime = queryDate.atTime(12, 0, 0);
            }else if(dto.getTimePeriod() != null && dto.getTimePeriod() == 2){
                startTime = queryDate.atTime(12, 0, 0);
                endTime = queryDate.atTime(18, 0, 0);
            }else{
                startTime = queryDate.atTime(0, 0, 0);
                endTime = queryDate.atTime(23, 59, 59);
            }

            List<StudentOutInRecord> outInRecords = studentOutInRecordService.list(
                    new QueryWrapper<StudentOutInRecord>().lambda()
                            .between(StudentOutInRecord::getRecordTime, startTime, endTime)
                            .eq(StudentOutInRecord::getStatus, 1)
            );
            //实到人数
            statisticsVo.setActualCount(Long.valueOf(outInRecords.size()));

            //查询教师请假人数
            Long leaveCount = studentLeaveService.getLeaveCount(startTime, endTime, dto);
            if(leaveCount == null){
                leaveCount = 0L;
            }
            statisticsVo.setLeaveCount(leaveCount);

            //通过考勤规则和实到人数信息，计算迟到的
            Long lateCount = 0L;
            Integer playTruantCount = 0;
            for (StudentOutInRecord outInRecord : outInRecords) {
                if("迟到".equals(outInRecord.getAttendanceStatus())){
                    lateCount ++;
                }else if("旷课".equals(outInRecord.getAttendanceStatus())){
                    playTruantCount ++;
                }
            }
            statisticsVo.setPlayTruantCount(playTruantCount);
            statisticsVo.setLateCount(lateCount);


            //计算出勤率
            if(statisticsVo.getAllCount() != null && statisticsVo.getAllCount() != 0){
                //最后通过总人数-实到人数-请假人数计算出缺勤人数
                statisticsVo.setAbsenteeismCount(statisticsVo.getAllCount() - statisticsVo.getLeaveCount() - statisticsVo.getActualCount());
                BigDecimal divide = BigDecimal.valueOf(statisticsVo.getActualCount()).divide(BigDecimal.valueOf(statisticsVo.getAllCount()), 4, RoundingMode.HALF_UP);
                statisticsVo.setAttendanceRate(divide.doubleValue());
            }else{
                statisticsVo.setAttendanceRate(0D);
                statisticsVo.setAbsenteeismCount(0L);
            }

        }

        return RT.ok(statisticsVo);
    }


    @GetMapping(value = "/visitor-list")
    @ApiOperation(value="访客列表")
    @SaCheckPermission("statistics:detail")
    public RT<List<VisitorInfoVo>> visitorList(@Valid AttendanceStatisticDto dto){
        List<VisitorInfoVo> visionList = reservationSchoolService.getVisionList(dto.getDate());
        return RT.ok(visionList);
    }

}