package com.mortals.xhx.module.attendance.web;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.unit.DataUnit;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.mortals.framework.annotation.UnAuth;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.PageInfo;
import com.mortals.framework.model.Result;
import com.mortals.framework.service.ICacheService;
import com.mortals.framework.util.DataUtil;
import com.mortals.framework.utils.ReflectUtils;
import com.mortals.framework.utils.poi.ExcelUtil;
import com.mortals.framework.web.BaseCRUDJsonBodyMappingController;
import com.mortals.xhx.base.system.param.service.ParamService;
import com.mortals.xhx.common.code.GoWorkResultEnum;
import com.mortals.xhx.common.utils.DynamicColExcelUtil;
import com.mortals.xhx.module.attendance.model.AttendanceClassQuery;
import com.mortals.xhx.module.attendance.model.AttendanceGroupQuery;
import com.mortals.xhx.module.attendance.model.AttendanceStaffStatEntity;
import com.mortals.xhx.module.attendance.model.vo.AttendanceSummaryQuery;
import com.mortals.xhx.module.attendance.service.AttendanceClassService;
import com.mortals.xhx.module.attendance.service.AttendanceGroupService;
import com.mortals.xhx.module.dept.model.DeptQuery;
import com.mortals.xhx.module.dept.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import com.mortals.framework.model.Context;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.mortals.framework.web.BaseCRUDJsonBodyMappingController;
import com.mortals.xhx.module.attendance.model.AttendanceStatEntity;
import com.mortals.xhx.module.attendance.service.AttendanceStatService;
import org.apache.commons.lang3.ArrayUtils;
import com.mortals.framework.util.StringUtils;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import static com.mortals.framework.ap.SysConstains.*;
import static com.mortals.xhx.common.key.RedisKey.KEY_ATTENDANCE_STAT_CACHE;

/**
 * 考勤汇总信息
 *
 * @author zxfei
 * @date 2023-04-08
 */
@RestController
@RequestMapping("attendance/stat")
public class AttendanceStatController extends BaseCRUDJsonBodyMappingController<AttendanceStatService, AttendanceStatEntity, Long> {

    @Autowired
    private ParamService paramService;

    @Autowired
    private AttendanceGroupService attendanceGroupService;

    @Autowired
    private DeptService deptService;

    @Autowired
    private ICacheService cacheService;

    @Autowired
    private AttendanceClassService attendanceClassService;

    public AttendanceStatController() {
        super.setModuleDesc("考勤汇总信息");
    }

    private ExecutorService executorService = Executors.newCachedThreadPool();

    private static String SUMMARY_TASK_KEY = "attendanceSummaryTask:run";

    @Override
    protected void init(Map<String, Object> model, Context context) {
        this.addDict(model, "deptId", deptService.find(new DeptQuery()).stream().collect(Collectors.toMap(x -> x.getId().toString(), y -> y.getDeptName())));
        this.addDict(model, "groupId", attendanceGroupService.find(new AttendanceGroupQuery()).stream().collect(Collectors.toMap(x -> x.getId().toString(), y -> y.getGroupName())));
        this.addDict(model, "classId", attendanceClassService.find(new AttendanceClassQuery()).stream().collect(Collectors.toMap(x -> x.getId().toString(), y -> y.getClassName())));
        this.addDict(model, "goWorkResult", GoWorkResultEnum.getEnumMap());
        this.addDict(model, "offWorkResult", GoWorkResultEnum.getEnumMap());
        super.init(model, context);
    }

    @PostMapping({"summary"})
    @UnAuth
    public Rest<Object> summary(@RequestBody AttendanceSummaryQuery query) {
        Rest<Object> ret = new Rest();
        Map<String, Object> model = new HashMap();
        Context context = this.getContext();
        String busiDesc = "执行考勤汇总任务";
        int code = 1;
        try {
            if (StringUtils.isNotEmpty(query.getSummaryTimeStart()) && StringUtils.isNotEmpty(query.getSummaryTimeEnd())) {
                List<String> dateList = getDatesBetween(query.getSummaryTimeStart(), query.getSummaryTimeEnd());
                for (String day : dateList) {
                    AttendanceSummaryQuery temp = new AttendanceSummaryQuery(day);
                    cacheService.lpush(KEY_ATTENDANCE_STAT_CACHE,temp);
                }
            } else {
                cacheService.lpush(KEY_ATTENDANCE_STAT_CACHE,query);
            }

            model.put("message_info", "开始执行考勤汇总,请稍后查看");
        } catch (Exception var9) {
            code = -1;
            this.doException(this.request, busiDesc, model, var9);
        }
        ret.setCode(code);
        ret.setMsg(model.get("message_info") == null ? "" : model.remove("message_info").toString());
        return ret;
    }

    public static List<String> getDatesBetween(String startDateStr, String endDateStr) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate startDate = LocalDate.parse(startDateStr, formatter);
        LocalDate endDate = LocalDate.parse(endDateStr, formatter);
        List<String> dates = new ArrayList<>();
        //这里是判断开始日期是否在结束日期之后或者=结束日期
        while (startDate.isBefore(endDate) || startDate.isEqual(endDate)) {
            String add = startDate.format(formatter);
            dates.add(add);
            startDate = startDate.plusDays(1);
        }
        return dates;
    }

    @PostMapping({"listExt"})
    @UnAuth
    public Rest<Object> listExt(@RequestBody AttendanceSummaryQuery query) {
        Rest<Object> ret = new Rest();
        Map<String, Object> model = new HashMap();
        Context context = this.getContext();
        String busiDesc = "查询" + this.getModuleDesc();
        int code = 1;
        try {
            PageInfo pageInfo = this.buildPageInfoExt(query);
            Result<AttendanceStatEntity> result = this.getService().findExt(query, pageInfo, context);
            model.put("data", result.getList());
            model.put("pageInfo", result.getPageInfo());
            this.parsePageInfo(model, result.getPageInfo());
            model.put("message_info", busiDesc + "成功");
            if (!ObjectUtils.isEmpty(context) && !ObjectUtils.isEmpty(context.getUser())) {
                this.recordSysLog(this.request, busiDesc + " 【成功】");
            }
        } catch (Exception var9) {
            code = -1;
            this.doException(this.request, busiDesc, model, var9);
        }

        this.init(model, context);
        ret.setCode(code);
        ret.setData(model);
        ret.setDict(model.get("dict"));
        ret.setMsg(model.get("message_info") == null ? "" : model.remove("message_info").toString());
        return ret;
    }

    protected PageInfo buildPageInfoExt(AttendanceSummaryQuery query) {
        PageInfo pageInfo = new PageInfo();
        if (!ObjectUtils.isEmpty(query) && !ObjectUtils.isEmpty(query.getPage())) {
            pageInfo.setCurrPage(query.getPage());
        }

        if (!ObjectUtils.isEmpty(query) && !ObjectUtils.isEmpty(query.getSize())) {
            pageInfo.setPrePageResult(query.getSize());
        }

        return pageInfo;
    }

    @PostMapping({"exportExcelExt"})
    @UnAuth
    public void exportExcel(@RequestBody AttendanceSummaryQuery query) {
        Context context = this.getContext();
        String busiDesc = "导出" + this.getModuleDesc();
        List<String> properties = query.getProperties();

        try {
            String name = StringUtils.trim(this.moduleDesc);
            if (StringUtils.isEmpty(name)) {
                name = System.currentTimeMillis() + "";
            }
            String fileName = name + ".xlsx";
            PageInfo pageInfo = new PageInfo(-1);
            List<AttendanceStatEntity> list = this.getService().findExt(query, pageInfo, context).getList();
            Class<AttendanceStatEntity> tClass = ReflectUtils.getClassGenricType(this.getClass(), 1);
            DynamicColExcelUtil<AttendanceStatEntity, Long> util = new DynamicColExcelUtil(tClass);
            this.doExportAfter(context, list);
            DateTime startDate = DateUtil.parse(query.getSummaryTimeStart());
            DateTime endDate = DateUtil.parse(query.getSummaryTimeEnd());
            Long subDay = DateUtil.between(startDate, endDate, DateUnit.DAY);


            final String[] weekStr={"星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
            //由于1表示周日，2表示周一所以需要-1后对应上数组下标
            List<List<Map<String, Object>>> lists = list.stream().map(item -> {
                attendanceStatExport(item);
                List<AttendanceStaffStatEntity> attendanceStaffStatEntities = item.getAttendanceStaffStatEntities();
                Map<Integer, String> collect = new HashMap<>();
                if (!ObjectUtils.isEmpty(attendanceStaffStatEntities)) {
                    collect = attendanceStaffStatEntities.stream().collect(Collectors.toMap(x -> x.getYear() + x.getMonth() + x.getDay(), y -> y.getAttendanceSummary(),(o,n)->n));
                }
                List<Map<String, Object>> mapList = new ArrayList<>();
                for (int i = 0; i <= subDay.intValue(); i++) {
                    DateTime curDate = DateUtil.offsetDay(startDate, i);
                    //判断详细是否存在，如果不存在 则构造一个空的
                    Integer year = DateUtil.year(curDate);
                    Integer month = DateUtil.month(curDate) + 1;
                    Integer day = DateUtil.dayOfMonth(curDate);
                    Integer total = year + month + day;

                    int index = DateUtil.dayOfWeek(curDate);

                    String dateStr = curDate.toDateStr() +"("+ weekStr[index - 1]+")";

                    Map<String, Object> map = new HashMap<>();
                    if (collect.get(total) != null) {
                        map.put("name", dateStr);
                        map.put("value", collect.get(total));
                    } else {
                        map.put("name", dateStr);
                        map.put("value", "--");
                    }
                    mapList.add(map);
                }
                return mapList;

            }).collect(Collectors.toList());

            // byte[] data = util.exportExcel(list, properties, name);
            byte[] data = util.exportExcel(list, properties, lists, name,6);
            this.responseStream(this.response, data, fileName);
            this.recordSysLog(this.request, busiDesc + " 【成功】");
        } catch (Exception var12) {
            this.doException(this.request, "导出异常", new HashMap(), var12);
        }

    }

    private void attendanceStatExport(AttendanceStatEntity entity){
        if(isNull(entity.getBackToUnit())){
            entity.setBackToUnit(null);
        }
        if(isNull(entity.getOnDutyLeave())){
            entity.setOnDutyLeave(null);
        }
        if(isNull(entity.getOutOfOffice())){
            entity.setOutOfOffice(null);
        }
        if(isNull(entity.getShiftCompensation())){
            entity.setShiftCompensation(null);
        }
        if(isNull(entity.getPhysicalExamination())){
            entity.setPhysicalExamination(null);
        }
        if(isNull(entity.getQuarantine())){
            entity.setQuarantine(null);
        }
        if(isNull(entity.getBusinessTrip())){
            entity.setBusinessTrip(null);
        }
        if(isNull(entity.getPublicHoliday())){
            entity.setPublicHoliday(null);
        }
        if(isNull(entity.getSickLeave())){
            entity.setSickLeave(null);
        }
        if(isNull(entity.getFuneralLeave())){
            entity.setFuneralLeave(null);
        }
        if(isNull(entity.getMarriageLeave())){
            entity.setMarriageLeave(null);
        }
        if(isNull(entity.getChildRearingLeave())){
            entity.setChildRearingLeave(null);
        }
        if(isNull(entity.getMaternityLeave())){
            entity.setMaternityLeave(null);
        }
        if(isNull(entity.getTransferBack())){
            entity.setTransferBack(null);
        }
        if(isNull(entity.getHomeLeave())){
            entity.setHomeLeave(null);
        }
        if(isNull(entity.getPersonalLeave())){
            entity.setPersonalLeave(null);
        }
        if(isNull(entity.getAbsenteeismDays())){
            entity.setAbsenteeismDays(null);
        }
        if(isNull(entity.getOtherDays())){
            entity.setOtherDays(null);
        }
        if(isNull(entity.getNonCompliancePunch())){
            entity.setNonCompliancePunch(null);
        }
        if(entity.getLateTimes()!=null && entity.getLateTimes()==0){
            entity.setLateTimes(null);
        }
        if(entity.getSurfingMobileTimes()!=null && entity.getSurfingMobileTimes()==0){
            entity.setSurfingMobileTimes(null);
        }
        if(entity.getOvertimeTimes()!=null && entity.getOvertimeTimes()==0){
            entity.setOvertimeTimes(null);
        }
        if(isNull(entity.getVacancy())){
            entity.setVacancy(null);
        }
        if(entity.getNonStandardDressTimes()!=null && entity.getNonStandardDressTimes()==0){
            entity.setNonStandardDressTimes(null);
        }
        if(isNull(entity.getUnexcusedMeetingAbsence())){
            entity.setUnexcusedMeetingAbsence(null);
        }
        if(isNull(entity.getEarlyLeaveMeeting())){
            entity.setEarlyLeaveMeeting(null);
        }
        if(isNull(entity.getBreastfeedingLeaveDays())){
            entity.setBreastfeedingLeaveDays(null);
        }
        if(isNull(entity.getMenstrualLeaveDays())){
            entity.setMenstrualLeaveDays(null);
        }
        if(isNull(entity.getAnnualLeaveDays())){
            entity.setAnnualLeaveDays(null);
        }
        if(isNull(entity.getCompensatedLeaveDays())){
            entity.setCompensatedLeaveDays(null);
        }
        if(isNull(entity.getPaternityLeaveDays())){
            entity.setPaternityLeaveDays(null);
        }
    }

    private boolean isNull(BigDecimal bigDecimal){
        if (ObjectUtils.isEmpty(bigDecimal)){
            return true;
        }else {
            BigDecimal zero = new BigDecimal("0");
            if(bigDecimal.compareTo(zero) > 0){
                return false;
            }else {
                return true;
            }
        }
    }
}
