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

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.mortals.framework.annotation.UnAuth;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.model.OrderCol;
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.code.OffWorkResultEnum;
import com.mortals.xhx.common.code.ProcessStatusEnum;
import com.mortals.xhx.common.code.YesNoEnum;
import com.mortals.xhx.module.attendance.model.*;
import com.mortals.xhx.module.attendance.model.vo.AttendStatInfo;
import com.mortals.xhx.module.attendance.service.AttendanceLeaveRecordService;
import com.mortals.xhx.module.attendance.service.AttendanceRecordHikService;
import com.mortals.xhx.module.attendance.service.AttendanceRecordService;
import com.mortals.xhx.module.attendance.service.AttendanceVacationRecordService;
import com.mortals.xhx.module.dept.model.DeptEntity;
import com.mortals.xhx.module.dept.model.DeptQuery;
import com.mortals.xhx.module.dept.model.DeptTreeSelect;
import com.mortals.xhx.module.dept.service.DeptService;
import com.mortals.xhx.module.job.model.JobEntity;
import com.mortals.xhx.module.job.model.JobQuery;
import com.mortals.xhx.module.job.service.JobService;
import com.mortals.xhx.module.staff.model.StaffEntity;
import com.mortals.xhx.module.staff.model.vo.HolidayListVo;
import com.mortals.xhx.module.staff.model.vo.StaffCheckAuthorizePdu;
import com.mortals.xhx.module.staff.model.vo.StaffInfoVo;
import com.mortals.xhx.module.staff.service.StaffService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 员工基本信息
 *
 * @author zxfei
 * @date 2023-04-07
 */
@RestController
@RequestMapping("staff")
public class StaffController extends BaseCRUDJsonBodyMappingController<StaffService, StaffEntity, Long> {

    @Autowired
    private ParamService paramService;
    @Autowired
    private JobService jobService;
    @Autowired
    private DeptService deptService;

    @Autowired
    private AttendanceRecordService recordService;
    @Autowired
    private AttendanceRecordHikService recordHikService;

    @Autowired
    private AttendanceVacationRecordService vacationRecordService;

    @Autowired
    private AttendanceLeaveRecordService leaveRecordService;


    public StaffController() {
        super.setModuleDesc("员工基本信息");
    }

    @Override
    protected void init(Map<String, Object> model, Context context) {
        this.addDict(model, "gender", paramService.getParamBySecondOrganize("Staff", "gender"));
        this.addDict(model, "politicalstatus", paramService.getParamBySecondOrganize("Staff", "politicalstatus"));
        this.addDict(model, "staffType", paramService.getParamBySecondOrganize("Staff", "staffType"));
        this.addDict(model, "status", paramService.getParamBySecondOrganize("Staff", "status"));
        this.addDict(model, "positionId", jobService.queryPositionName(new JobQuery()).stream().collect(Collectors.toMap(x -> x.getId().toString(), y -> y.getJobName(), (o, n) -> n)));

        DeptQuery deptQuery = new DeptQuery();
        deptQuery.setOrderColList(Arrays.asList(new OrderCol("deptName")));
        List<DeptEntity> list = deptService.find(deptQuery);
        List<DeptTreeSelect> treeSelects = deptService.buildDeptTreeSelect(list);
        this.addDict(model, "deptPerson", treeSelects);

        this.addDict(model, "deptId", deptService.find(deptQuery).stream().collect(Collectors.toMap(x -> x.getId().toString(), y -> y.getDeptName())));


        super.init(model, context);
    }


    @Override
    protected int doListAfter(StaffEntity query, Map<String, Object> model, Context context) throws AppException {
        //todo 员工信息统计--员工关系统计
        StaffInfoVo staffInfoVo = new StaffInfoVo();
        staffInfoVo.setRefreshDate(new Date());
        model.put("staff", staffInfoVo);
        return super.doListAfter(query, model, context);
    }

    @Override
    protected void saveBefore(StaffEntity entity, Map<String, Object> model, Context context) throws AppException {
        entity.setSource(2);
        //判断手机号码是否包含* 如果包含则不添加更新
        if (!entity.newEntity() && !ObjectUtils.isEmpty(entity.getPhoneNumber()) && StrUtil.contains(entity.getPhoneNumber(), "*")) {
            entity.setPhoneNumber(null);
        }
    }

    @Override
    protected int infoAfter(Long id, Map<String, Object> model, StaffEntity entity, Context context) throws AppException {
        //todo 员工统计信息

        AttendanceRecordHikQuery hikQuery = new AttendanceRecordHikQuery();
        hikQuery.setAttendanceDateStart(DateUtil.beginOfMonth(new Date()).toDateStr());
        hikQuery.setAttendanceDateEnd(DateUtil.today());
        hikQuery.setWorkNum(entity.getWorkNum());

        //出勤天数
        Map<String, List<AttendanceRecordHikEntity>> collect = recordHikService.find(hikQuery, context).stream().collect(Collectors.groupingBy(x -> DateUtil.formatDate(x.getAttendanceDate())));
        Integer attendDays = collect.keySet().size();


        AttendanceRecordQuery attendanceRecordQuery = new AttendanceRecordQuery();
        attendanceRecordQuery.setAttendanceDateStart(DateUtil.beginOfMonth(new Date()).toDateStr());
        attendanceRecordQuery.setAttendanceDateEnd(DateUtil.today());
        attendanceRecordQuery.setWorkNum(entity.getWorkNum());
        List<AttendanceRecordEntity> attendanceRecordEntities = recordService.find(attendanceRecordQuery);

        List<AttendanceRecordDetailEntity> allDetail = new ArrayList<>();
        for (AttendanceRecordEntity recordEntity:attendanceRecordEntities){
            allDetail.addAll(recordEntity.getAttendanceRecordDetailList());
        }
        //迟到次数
        long beLate = 0l;
        //早退次数
        long leaveEarly = 0l;
        //缺卡次数
        long lackOfCards = 0l;
        for(AttendanceRecordDetailEntity item:allDetail){
            if(GoWorkResultEnum.迟到.getValue() == item.getGoWorkResult() || OffWorkResultEnum.迟到.getValue() == item.getOffWorkResult()){
                beLate++;
            }
            if(GoWorkResultEnum.早退.getValue() == item.getGoWorkResult() || OffWorkResultEnum.早退.getValue() == item.getOffWorkResult()){
                leaveEarly++;
            }
            if(GoWorkResultEnum.缺卡.getValue() == item.getGoWorkResult() || OffWorkResultEnum.缺卡.getValue() == item.getOffWorkResult()){
                lackOfCards++;
            }
        }

//        //迟到次数
//        Long beLate = attendanceRecordEntities.parallelStream()
//                .flatMap(item -> item.getAttendanceRecordDetailList().stream())
//                .filter(f -> GoWorkResultEnum.迟到.getValue() == f.getGoWorkResult() || OffWorkResultEnum.迟到.getValue() == f.getOffWorkResult())
//                .map(i -> i.getStaffId())
//                .distinct()
//                .count();
//
//        //早退次数
//        long leaveEarly = attendanceRecordEntities.parallelStream()
//                .flatMap(item -> item.getAttendanceRecordDetailList().stream())
//                .filter(f -> GoWorkResultEnum.早退.getValue() == f.getGoWorkResult() || OffWorkResultEnum.早退.getValue() == f.getOffWorkResult())
//                .map(i -> i.getStaffId())
//                .distinct()
//                .count();
//
//        //缺卡次数
//        long lackOfCards = attendanceRecordEntities.parallelStream()
//                .flatMap(item -> item.getAttendanceRecordDetailList().stream())
//                .filter(f -> GoWorkResultEnum.缺卡.getValue() == f.getGoWorkResult() || OffWorkResultEnum.缺卡.getValue() == f.getOffWorkResult())
//                .map(i -> i.getStaffId())
//                .distinct()
//                .count();


        AttendanceLeaveRecordQuery leaveRecordQuery = new AttendanceLeaveRecordQuery();
        //请假开始时间大于当前月份初始日期
        leaveRecordQuery.setStartTimeStart(DateUtil.beginOfMonth(new Date()).toDateStr());
        leaveRecordQuery.setStartTimeEnd(DateUtil.today());
        leaveRecordQuery.setLeavePersonId(entity.getId());
        leaveRecordQuery.setProcessStatus(ProcessStatusEnum.已处理.getValue());
        int levealPersonNum = leaveRecordService.count(leaveRecordQuery, getContext());

        List<HolidayListVo> holidayListVos = new ArrayList<>();
        HolidayListVo vo = new HolidayListVo();

        vo.setWorkName(entity.getName());
        vo.setWorkStatus(String.valueOf(entity.getStatus()));
        vo.setWorkDept(entity.getDeptName());
        vo.setWorkLimit("--");
        vo.setWorkBeginDay(entity.getEntryDate());
        vo.setWorkFormalDay(entity.getRegularDate());
        vo.setAttendanceCount(attendDays);
        vo.setLeaveCount(levealPersonNum);
        vo.setLateCount(beLate + leaveEarly);
        vo.setMinerCount(0L);
        vo.setLackCardCount(lackOfCards);
        vo.setWorkOverDay(0L);
        vo.setCompensatoryDay(0);
        vo.setMarriageHoliday(0);
        vo.setWinterHoliday(0);
        vo.setPaternityLeaveDay(0);
        holidayListVos.add(vo);
        entity.setHolidayLists(holidayListVos);
        return super.infoAfter(id, model, entity, context);
    }

    @Override
    protected int saveAfter(StaffEntity entity, Map<String, Object> model, Context context) throws AppException {
        deptService.updateDeptNum(context);
        return super.saveAfter(entity, model, context);
    }

    /**
     * 同步更新人员
     */
    @PostMapping(value = "syncPersons")
    public String syncPersons() {
        JSONObject jsonObject = new JSONObject();
        String busiDesc = this.getModuleDesc() + "同步";
        try {
            //同步部门
            deptService.syncDept(getContext());
            Rest<Void> rest = this.service.syncPersons(getContext());
            if (rest.getCode() == YesNoEnum.NO.getValue()) {
                throw new AppException("同步异常！");
            }
            recordSysLog(request, busiDesc + " 【成功】");
            jsonObject.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
            jsonObject.put(KEY_RESULT_MSG, busiDesc + " 【成功】");
        } catch (Exception e) {
            log.error("同步人员", e);
            jsonObject.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            jsonObject.put(KEY_RESULT_MSG, super.convertException(e));
        }
        return jsonObject.toJSONString();
    }

    @Override
    public String delete(Long[] id) {
        return super.delete(id);
    }

    @PostMapping(value = "check/authorize")
    public String checkAuthorize(StaffCheckAuthorizePdu pdu) {
        Map<String, Object> model = new HashMap();
        if (pdu.getStaffId() == null) {
            return this.createFailJsonResp("请选择待授权" + this.getModuleDesc() + "信息");
        } else {
            JSONObject ret = new JSONObject();
            String busiDesc = "授权" + this.getModuleDesc();
            Context context = this.getContext();

            try {
                this.service.checkAuthorize(pdu, context);
                if (!ObjectUtils.isEmpty(context) && !ObjectUtils.isEmpty(context.getUser())) {
                    this.recordSysLog(this.request, busiDesc + " 【成功】");
                }
            } catch (Exception var8) {
                this.doException(this.request, busiDesc, model, var8);
                Object msg = model.get("message_info");
                return this.createFailJsonResp(msg == null ? "系统异常" : msg.toString());
            }

            this.init(model, context);
            ret.put("data", model);
            ret.put("code", 1);
            ret.put("msg", model.remove("message_info"));
            return ret.toJSONString();
        }
    }

    /**
     * 更新人员大厅数据
     */
    @PostMapping(value = "updateSala")
    @UnAuth
    public String doUpdateSala() {
        JSONObject jsonObject = new JSONObject();
        String busiDesc = "更新人员大厅数据";
        try {
            this.service.doUpdateSala();
            recordSysLog(request, busiDesc + " 【成功】");
            jsonObject.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
            jsonObject.put(KEY_RESULT_MSG, busiDesc + " 【成功】");
        } catch (Exception e) {
            log.error("同步人员", e);
            jsonObject.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            jsonObject.put(KEY_RESULT_MSG, super.convertException(e));
        }
        return jsonObject.toJSONString();
    }
}

