package jnpf.attendance.controller;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.github.pagehelper.PageInfo;
import jnpf.attendance.AttendanceApi;
import jnpf.attendance.service.AttendanceApproveService;
import jnpf.attendance.service.AttendanceGroupService;
import jnpf.base.ActionResult;
import jnpf.base.UserInfo;
import jnpf.base.vo.PageListVO;
import jnpf.config.ConfigValueUtil;
import jnpf.database.util.TenantDataSourceUtil;
import jnpf.engine.FlowTaskApi;
import jnpf.entity.attendance.AttendanceApprovalAdminVo;
import jnpf.entity.workflow.AttendanceWorkOvertimeApprove;
import jnpf.entity.workflow.SelfApprove;
import jnpf.enums.attendance.ApprovalSettingTypeEnum;
import jnpf.enums.personnel.FtbPersonnelsCheckStatusCodeEnum;
import jnpf.exception.ApproveException;
import jnpf.exception.HandleException;
import jnpf.exception.LoginException;
import jnpf.model.attendance.dto.*;
import jnpf.model.attendance.vo.*;
import jnpf.model.attendance.vo.attendance.AttendanceToThousandsFacesVo;
import jnpf.model.attendance.vo.attendance.GroupMiniVo;
import jnpf.model.attendance.vo.attendance.LeaveConsumptionDetailVo;
import jnpf.model.attendance.vo.attendance.TimeVo;
import jnpf.model.attendance.vo.flow.HandlerVo;
import jnpf.model.doclibrary.vo.UseDetailVo;
import jnpf.model.workflow.dto.AttendanceBusinessTripApproveOaDto;
import jnpf.model.workflow.dto.AttendanceWorkOvertimeApproveDto;
import jnpf.model.workflow.dto.SelfApproveDto;
import jnpf.util.*;
import jnpf.util.data.DataSourceContextHolder;
import jnpf.workflow.service.SelfApproveService;
import jnpf.workflow.service.WorkOvertimeApproveService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.util.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * describe
 * 考勤审批相关
 *
 * @author HuangLinPan
 * @date 2023/11/22
 */

@RestController
@RequestMapping(value = "/attendance")
@Slf4j
public class AttendanceApproveController implements AttendanceApi {

    @Resource
    private AttendanceApproveService attendanceApproveService;
    @Autowired
    private WorkOvertimeApproveService workApproveService;
    @Resource
    private UserProvider userProvider;

    @Autowired
    private ConfigValueUtil configValueUtil;

    @Resource
    private AttendanceGroupService attendanceGroupService;

    /**
     * 假期劵的使用记录
     *
     * @param id              劵的id
     * @param balanceQueryDto 参数
     * @return jnpf.base.ActionResult<java.lang.String>
     * @author hlp
     */
    @GetMapping("/useDetail/{id}")
    public ActionResult<PageListVO<UseDetailVo>> getUseDetail(@PathVariable("id") String id, BalanceQueryDto balanceQueryDto) {
        PageInfo<UseDetailVo> vo = attendanceApproveService.getUseDetail(id, balanceQueryDto);
        return ActionResult.page(vo.getList(), FtbUtil.getPagination(vo));
    }


    /**
     * 定时失效劵
     *
     * @param tenantId 租户id
     * @return java.lang.Boolean
     * @author hlp
     */
    @Override
    @PostMapping(value = "/invalidationCoupons")
    public Boolean invalidationCoupons(@RequestParam String tenantId) {
        return attendanceApproveService.invalidationCoupons(tenantId);
    }


    /**
     * 每月定时计算用户存休
     *
     * @param tenantId 租户Id
     */
    @Override
    @PostMapping(value = "/storageRest")
    public Boolean storageRest(@RequestParam(value = "tenantId") String tenantId) {
        return attendanceApproveService.storageRest(tenantId);
    }


    /**
     * 加班--开始日期选择后触发接口返回当天及后一天的排班信息
     *
     * @param balanceQueryDto 参数
     * @return jnpf.base.ActionResult<java.util.List < jnpf.model.attendance.vo.UserClassesVo>>
     * @author hlp
     */
    @GetMapping("/workOverTime/getClasses")
    public ActionResult<List<UserClassesVo>> getClasses(BalanceQueryDto balanceQueryDto) {
        List<UserClassesVo> vo = attendanceApproveService.getClasses(balanceQueryDto);
        return ActionResult.success(vo);
    }

    /**
     * 加班--加班明细
     *
     * @param balanceQueryDto 参数
     * @return jnpf.base.ActionResult<java.util.List < jnpf.model.attendance.vo.UserClassesVo>>
     * @author hlp
     */
    @GetMapping("/workOverTime/shifts")
    public ActionResult<LeaveShiftVo> getWorkOverTimeShifts(BalanceQueryDto balanceQueryDto) {
        try {
            LeaveShiftVo vo = attendanceApproveService.getWorkOverTimeShifts(balanceQueryDto);
            return ActionResult.success(vo);
        } catch (Exception e) {
            return ActionResult.fail(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode(), e.getMessage());
        }
    }


    /**
     * 获取请假申请时长及设计班次(请假时选择了开始和结束时间后请求该接口)
     *
     * @param leaveQueryDto 参数
     * @return jnpf.base.ActionResult<jnpf.model.attendance.vo.LeaveShiftVo>
     * @author hlp
     */
    @GetMapping("/leaveDuration")
    public ActionResult<LeaveShiftVo> getLeaveDuration(LeaveQueryDto leaveQueryDto) throws HandleException {
        if (null == leaveQueryDto.getStartTime() || leaveQueryDto.getStartTime().isEmpty()) {
            return ActionResult.fail("开始时间不能为空");
        }
        if (null == leaveQueryDto.getEndTime() || leaveQueryDto.getEndTime().isEmpty()) {
            return ActionResult.fail("结束时间不能为空");
        }
        LeaveShiftVo vo = attendanceApproveService.getLeaveDuration(leaveQueryDto);
        return ActionResult.success(vo);
    }

    /**
     * 请假审批通过后的触发接口
     *
     * @param tenantId 租户id
     * @param applyId  审批的唯一id  对应表f_id
     * @param status   是否审核通过 0.待审核  1.通过 2.未通过
     * @param userId   审批用户Id
     */
    @GetMapping(value = "/approve/leave/pass")
    @NoDataSourceBind
    public void leaveApprove(@RequestParam(value = "tenantId") String tenantId, @RequestParam(value = "applyId") String applyId, @RequestParam(value = "status") Integer status, @RequestParam("userId") String userId, @RequestParam("userName") String userName) throws ApproveException {
        log.error("请假审批通过后的触发接口 tenantId : {},入参applyId:{}", tenantId, applyId);
        checkOutTenant(tenantId);
        attendanceApproveService.leaveApprove(applyId, status, tenantId, userId, userName);
    }

    /**
     * 加班审批通过后触发接口
     *
     * @param tenantId 租户id
     * @param applyId  审批的唯一id 对应表f_id
     * @param status   是否审核通过 0.待审核 2.未通过 1.通过
     * @param userId   审批用户Id
     * @author hlp
     */
    @GetMapping(value = "/approve/work/pass")
    @NoDataSourceBind
    public void workApprove(@RequestParam(value = "tenantId") String tenantId, @RequestParam(value = "applyId") String applyId, @RequestParam(value = "status") Integer status, @RequestParam("userId") String userId, @RequestParam("userName") String userName) throws ApproveException {
        log.error("加班审批通过后的触发接口 tenantId : {},入参applyId:{}", tenantId, applyId);
        checkOutTenant(tenantId);
        attendanceApproveService.workApprove(applyId, status, tenantId, userId, userName);
    }

    /**
     * 借调审批通过后触发接口
     *
     * @param tenantId 租户id
     * @param applyId  审批的唯一id 对应表f_id
     * @param status   是否审核通过 0.待审核 2.未通过 1.通过
     * @param userId   审批用户Id
     * @author hlp
     */
    @GetMapping(value = "/approve/self/pass")
    @NoDataSourceBind
    public void selfApprove(@RequestParam(value = "tenantId") String tenantId, @RequestParam(value = "applyId") String applyId, @RequestParam(value = "departureTime") String departureTime, @RequestParam(value = "backTime") String backTime, @RequestParam(value = "status") Integer status, @RequestParam("userId") String userId, @RequestParam("userName") String userName) throws ApproveException, HandleException {
        log.error("借调审批通过后的触发接口 tenantId : {},入参applyId:{}", tenantId, applyId);
        checkOutTenant(tenantId);
        attendanceApproveService.selfApprove(applyId, departureTime, backTime, status, userId, userName, tenantId);
    }

    /**
     * 审批校验接口
     *
     * @param taskId 任务id
     * @param type   审批类型 1.常规补卡审批 2.调整出勤结果审批 3.外勤审批 4.请假审批 5.加班审批 6.借调审批 7.外出  8.出差
     * @return jnpf.base.ActionResult<java.lang.Object>
     * @author hlp
     */
    @PostMapping("/approvalCheck")
    public ActionResult<Object> getApprovalAdmin(@RequestParam("taskId") String taskId, @RequestParam("type") String type) {
        return attendanceApproveService.getApprovalAdmin(taskId, type);
    }

    /**
     * 提交时审批校验接口
     *
     * @param type 审批类型 1.常规补卡审批 2.调整出勤结果审批 3.外勤审批 4.请假审批 5.加班审批 6.借调审批 7.外出  8.出差
     * @return jnpf.base.ActionResult<java.lang.Object>
     * @author hlp
     */
    @PostMapping("/submitApprovalCheck")
    public ActionResult<Object> submitValidation(@RequestParam("type") String type) {
        String body = getBody(ServletUtil.getRequest());
        return attendanceApproveService.submitValidation(body, type);
    }

    /**
     * 获取考勤组审批管理员
     *
     * @param taskId 考勤组id
     * @param type   审批类型 1.常规补卡审批 2.调整出勤结果审批 3.外勤审批 4.请假审批 5.加班审批   6.外出 7.出差 其他：借调
     * @return
     */
    @PostMapping("/getApprovalAdmin")
    public ActionResult<HandlerVo> getApprovalAdmin(HttpServletRequest request, String taskId, String type) throws Exception {
        ServletInputStream inputStream = request.getInputStream();
        byte[] bytes = IOUtils.toByteArray(inputStream);
        String body = new String(bytes, "UTF-8");

        type = type.split("\\?")[0];
        Integer typeInt = Integer.parseInt(type);
        HandlerVo handlerVo = new HandlerVo();
        if (ApprovalSettingTypeEnum.LEAVE.getCode().equals(typeInt)) {
            /** 请假审批*/
//            System.out.println("请假审批...");
            AttendanceApprovalAdminVo approveUser = attendanceApproveService.getLeaveApproveUser(body);
            List<AttendanceUserVo> userList = approveUser.getUserList();
            if (CollectionUtil.isEmpty(userList)) {
                log.error("没有找到该考勤组请假审批管理员");
                return ActionResult.success(handlerVo);
            }
            String idsStr = toUserIdsStr(userList);
            handlerVo.setHandleId(idsStr);
//            System.out.println("请假审批-userIds:" + handlerVo);
            return ActionResult.success(handlerVo);
        }
        if (ApprovalSettingTypeEnum.OVERTIME.getCode().equals(typeInt)) {
            /** 加班审批*/
//            System.out.println("加班审批...");
            AttendanceApprovalAdminVo approveUser = attendanceApproveService.getOvertimeApproveUser(body);
//            System.out.println("approveUser:" + approveUser.toString());
            if (CollectionUtil.isEmpty(approveUser.getUserList())) {
                log.error("没有找到该考勤组加班审批管理员");
                return ActionResult.success(handlerVo);
            }
            handlerVo.setHandleId(toUserIdsStr(approveUser.getUserList()));
//            System.out.println("加班审批-userIds:" + handlerVo);
            return ActionResult.success(handlerVo);
        }
        if (ApprovalSettingTypeEnum.ROUTINE.getCode().equals(typeInt)) {
            /** 补卡审批*/
//            System.out.println("补卡审批...");
            AttendanceApprovalAdminVo approveUser = attendanceApproveService.getReplacementCardApproveUser(body);
            List<AttendanceUserVo> userList = approveUser.getUserList();
            if (CollectionUtil.isEmpty(userList)) {
                log.error("没有找到该考勤组补卡审批管理员");
                return ActionResult.success(handlerVo);
            }
            String idsStr = toUserIdsStr(userList);
            handlerVo.setHandleId(idsStr);
//            System.out.println("补卡审批-userIds:" + handlerVo);
            return ActionResult.success(handlerVo);
        }
        if (ApprovalSettingTypeEnum.ACTION_RESULT.getCode().equals(typeInt)) {
            /** 调整出勤结果*/
//            System.out.println("调整出勤结果审批...");
            AttendanceApprovalAdminVo approvalUser = attendanceApproveService.getAttendanceAlter(body);
            List<AttendanceUserVo> userList = approvalUser.getUserList();
            if (CollectionUtil.isEmpty(userList)) {
                log.error("没有找到该考勤组调整出勤结果审批管理员");
                return ActionResult.success(handlerVo);
            }
            String idsStr = toUserIdsStr(userList);
            handlerVo.setHandleId(idsStr);
//            System.out.println("调整出勤审批-userIds:" + handlerVo);
            return ActionResult.success(handlerVo);
        }
        if (ApprovalSettingTypeEnum.OUT.getCode().equals(typeInt)) {
            /** 外勤审批*/
//            System.out.println("外勤审批...");
            AttendanceApprovalAdminVo approvalUser = attendanceApproveService.getFieldApproval();
            List<AttendanceUserVo> userList = approvalUser.getUserList();
            if (CollectionUtil.isEmpty(userList)) {
                log.error("没有找到该考勤组外勤审批管理员");
                return ActionResult.success(handlerVo);
            }
            String idsStr = toUserIdsStr(userList);
            handlerVo.setHandleId(idsStr);
//            System.out.println("外勤审批-userIds:" + handlerVo);
            return ActionResult.success(handlerVo);
        }
        if (ApprovalSettingTypeEnum.GO_OUT.getCode().equals(typeInt)) {
            /** 外出审批*/
            AttendanceApprovalAdminVo approvalUser = attendanceApproveService.getGoOutApproval();
            List<AttendanceUserVo> userList = approvalUser.getUserList();
            if (CollectionUtil.isEmpty(userList)) {
                log.error("没有找到该考勤组外出审批管理员");
                return ActionResult.success(handlerVo);
            }
            String idsStr = toUserIdsStr(userList);
            handlerVo.setHandleId(idsStr);
//            System.out.println("外勤审批-userIds:" + handlerVo);
            return ActionResult.success(handlerVo);
        }
        if (ApprovalSettingTypeEnum.BUSINESS_TRIP.getCode().equals(typeInt)) {
            /** 出差审批*/
//            System.out.println("出差审批...");
            AttendanceApprovalAdminVo approvalUser = attendanceApproveService.getBusinessTripApproval();
            List<AttendanceUserVo> userList = approvalUser.getUserList();
            if (CollectionUtil.isEmpty(userList)) {
                log.error("没有找到该考勤组出差审批管理员");
                return ActionResult.success(handlerVo);
            }
            String idsStr = toUserIdsStr(userList);
            handlerVo.setHandleId(idsStr);
//            System.out.println("出差审批-userIds:" + handlerVo);
            return ActionResult.success(handlerVo);
        }
        /** 借调审批*/
//        System.out.println("借调审批...");
        List<String> managerIds = attendanceApproveService.secondedApproval(body);
        if (CollectionUtil.isEmpty(managerIds)) {
            log.error("没有找到该考勤组借调审批管理员");
            return ActionResult.success(handlerVo);
        }
        String idsStr = CollectionUtil.join(managerIds, ",");
        handlerVo.setHandleId(idsStr);
//        System.out.println("借调审批-userIds:" + handlerVo);
        return ActionResult.success(handlerVo);
    }

    /**
     * 获取考勤组管理员具体信息
     *
     * @param type 审批类型 1.常规补卡审批 2.调整出勤结果审批 3.外勤审批 4.请假审批 5.加班审批 6.外出 7.出差  0：借调
     * @return ActionResult<AttendanceApprovalAdminVo>
     */
    @GetMapping("/getGroupAdminInfo/{type}")
    public ActionResult<AttendanceApprovalAdminVo> getGroupAdminInfo(@PathVariable("type") Integer type,
                                                                     @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date startTime,
                                                                     @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date endTime,
                                                                     @RequestParam(required = false) String clockInResultId,
                                                                     @RequestParam(required = false) String selfGroupId
    ) throws HandleException {

        AttendanceApprovalAdminVo approvalAdminVo = attendanceApproveService.getGroupAdminInfo(type, startTime, endTime, clockInResultId, selfGroupId);
        return ActionResult.success(approvalAdminVo);
    }


    /**
     * 返回用户id
     *
     * @param userVoList
     * @return
     */
    private String toUserIdsStr(List<AttendanceUserVo> userVoList) {
        List<String> userIds = userVoList.stream().map(AttendanceUserVo::getUserId).collect(Collectors.toList());
        return CollectionUtil.join(userIds, ",");
    }


    public void checkOutTenant(String tenantId) {
        if (configValueUtil.isMultiTenancy()) {
            // 判断是不是从外面直接请求
            if (StringUtil.isNotEmpty(tenantId)) {
                //切换成租户库
                try {
                    TenantDataSourceUtil.switchTenant(tenantId);
                } catch (LoginException e) {
                    throw new RuntimeException("切换租户失败");
                }
            } else {
                UserInfo userInfo = UserProvider.getUser();
                Assert.notNull(userInfo.getUserId(), "缺少租户信息");
                DataSourceContextHolder.setDatasource(userInfo.getTenantId(), userInfo.getTenantDbConnectionString(), userInfo.isAssignDataSource());
            }
        }
    }

    /**
     * 获取远程请求参数
     *
     * @return
     * @throws IOException
     */
    private String getBody(HttpServletRequest request) {
        ServletInputStream inputStream = null;
        try {
            inputStream = request.getInputStream();
            byte[] bytes = IOUtils.toByteArray(inputStream);
            String body = new String(bytes, "UTF-8");
            return body;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取考勤组用户余额
     *
     * @param groupId 考勤组
     * @param month   年月（2024-5-13）
     * @return jnpf.base.ActionResult<jnpf.model.attendance.vo.UserBalanceVo>
     * @author hlp
     */
    @GetMapping("/userBalanceByGroupId")
    public ActionResult<List<UserBalanceVo>> getBalanceDetailS(@RequestParam String groupId, @RequestParam String month) {
        List<UserBalanceVo> vo = attendanceApproveService.getBalanceDetailS(groupId, month);
        return ActionResult.success(vo);
    }

    /**
     * 外出审批通/拒绝时调用接口
     *
     * @param tenantId 租户Id
     * @param applyId  审批的唯一id 对应表f_id
     * @param status   是否审核通过 0.待审核  1.通过 2.未通过
     * @param userId   审批用户Id
     * @throws ApproveException
     */
    @GetMapping(value = "/approve/goOut/pass")
    @NoDataSourceBind
    public void goOutApprove(@RequestParam(value = "tenantId") String tenantId, @RequestParam(value = "applyId") String applyId, @RequestParam(value = "status") Integer status, @RequestParam("userId") String userId, @RequestParam("userName") String userName) throws ApproveException {
        log.error("外出审批通过后的触发接口 tenantId : {}", tenantId);
        log.error("外出审批通过后的触发接口 入参applyId : {}", applyId);
        checkOutTenant(tenantId);
        attendanceApproveService.goOutApprove(applyId, status, tenantId, userId, userName);
    }

    /**
     * 出差审批通/拒绝时调用接口
     *
     * @param tenantId 租户Id
     * @param applyId  审批的唯一id 对应表f_id
     * @param status   是否审核通过 0.待审核  1.通过 2.未通过
     * @param userId   审批用户Id
     * @throws ApproveException
     */
    @GetMapping(value = "/approve/businessTrip/pass")
    @NoDataSourceBind
    public void businessTripApprove(@RequestParam(value = "tenantId") String tenantId, @RequestParam(value = "applyId") String applyId, @RequestParam(value = "status") Integer status, @RequestParam("userId") String userId, @RequestParam("userName") String userName) throws ApproveException {
        checkOutTenant(tenantId);
        attendanceApproveService.businessTripApprove(applyId, status, tenantId, userId, userName);
    }


    /**
     * 发消息通知下一节点审核人
     *
     * @param workflowImQueryDto 审批参数信息
     */
    @GetMapping("/im")
    @NoDataSourceBind
    public ActionResult workIm(WorkflowImQueryDto workflowImQueryDto) {
        log.error("发消息通知下一节点审核人入参： {}", workflowImQueryDto.toString());
        // 因OA流调用时会等待流程完成后才会提交事务，本接口会依赖于事务的提交结果，所以单独开一个线程执行
        new Thread(() -> {
            checkOutTenant(workflowImQueryDto.getTenantId());
            attendanceApproveService.sendIm(workflowImQueryDto);
        }).start();

        return ActionResult.success();
    }

    /**
     * 获取用户当前时间所在考勤组的请假类型
     */
//    @GetMapping("/leaveList")
//    public ActionResult getLeaveList() throws HandleException {
//        return attendanceApproveService.getLeaveList();
//    }

    /***************************************以下为考勤V1.7版本提供的新接口****************************************************/

    /**
     * 新版OA收拢保存考勤出差审批
     *
     * @param approveOaDto 出差对象
     */
    @PostMapping("/businessTripForOa")
    public ActionResult<Void> createBusinessTrip(@RequestBody @Valid AttendanceBusinessTripApproveOaDto approveOaDto) {
        log.error("FoeOa开始出差了参数................: {}", approveOaDto);
        // AttendanceBusinessTripApproveOaDto(id=null, userId=["450558716723340421"],
        // departure=[{"detailAddress":"","areaLabels":"贵州省/贵阳市/市辖区","areaIds":["354094501027910","354094501027911","354094501027912"]}],
        // destination=[{"detailAd"四川省/南充市/市辖区","areaIds":["354094498033736","354094499168330","354094499168331"]}],
        // startTime=null, endTime=null, dayNum=null, transportationVehicles=4, reason=------------, fileJs, time=[1730390400000, 1730476800000])
        return attendanceApproveService.createBusinessTrip(approveOaDto);
    }

    /**
     * 新版OA收拢出差审批通过后触发接口
     *
     * @param taskId 审批的唯一id 对应表f_id
     * @param status 是否审核通过 0.待审核 2.未通过 1.通过
     * @author hlp
     */
    @GetMapping(value = "/oaApprove/businessTrip/pass")
    public ActionResult<Void> businessTripApprove(@RequestParam(value = "taskId") String taskId, @RequestParam(value = "status") Integer status) {
        ActionResult<Void> result = new ActionResult<>();
        result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getCode());
        result.setMsg(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getMsg());
        try {
            UserInfo userInfo = userProvider.get();
            log.error("出差taskId:{},status:{},userInfo:{}", taskId, status, userInfo);
            attendanceApproveService.businessTripApprove(taskId, status, userInfo.getTenantId(), userInfo.getUserId(), userInfo.getUserName());
        } catch (ApproveException e) {
            result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }

    /**
     * 通过传入的开始结束时间及单位获取时长
     *
     * @param dto 时长对象
     */
    @GetMapping("/getDurationForOa")
    public ActionResult<Void> getDurationForOa(@RequestBody DurationForOaDto dto) {
        log.error("FoeOa通过传入的开始结束时间及单位获取时长了参数................: {}", dto);
        return attendanceApproveService.getDurationForOa(dto);
    }

    /**
     * 新版OA收拢保存考勤外出审批  小时外出逻辑
     *
     * @param dto 对象
     */
    @PostMapping("/goOutForOa")
    public ActionResult<Void> createGoOutForOa(@RequestBody GoOutApproveForOaDto dto) {
        log.error("FoeOa开始外出了参数................: {}", dto);
        return attendanceApproveService.createGoOutForOa(dto);
    }

    /**
     * 新版OA收拢外出审批通过后触发接口   小时外出逻辑
     *
     * @param taskId 审批的唯一id 对应表f_id
     * @param status 是否审核通过 0.待审核 2.未通过 1.通过
     * @author hlp
     */
    @GetMapping(value = "/oaApprove/goOut/pass")
    public ActionResult<Void> goOutApproveForOa(@RequestParam(value = "taskId") String taskId, @RequestParam(value = "status") Integer status) {
        ActionResult<Void> result = new ActionResult<>();
        result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getCode());
        result.setMsg(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getMsg());
        try {
            UserInfo userInfo = userProvider.get();
            log.error("外出taskId:{},status:{},userInfo:{}", taskId, status, userInfo);
            attendanceApproveService.goOutApprove(taskId, status, userInfo.getTenantId(), userInfo.getUserId(), userInfo.getUserName());
        } catch (ApproveException e) {
            result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }

    /**
     * 新版OA收拢保存考勤请假审批
     *
     * @param dto 对象
     */
    @PostMapping("/leaveForOa")
    public ActionResult<Void> createLeaveForOa(@RequestBody LeaveApproveForOaDto dto) {
        log.error("FoeOa开始请假了参数................: {}", dto);
        return attendanceApproveService.createLeaveForOa(dto);
    }

    /**
     * 请假审批通过后的触发接口
     *
     * @param taskId 审批的唯一id  对应表f_id
     * @param status 是否审核通过 0.待审核  1.通过 2.未通过
     */
    @GetMapping(value = "/oaApprove/leave/pass")
    public ActionResult<Void> leaveApproveForOa(@RequestParam(value = "taskId") String taskId, @RequestParam(value = "status") Integer status) {
        ActionResult<Void> result = new ActionResult<>();
        result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getCode());
        result.setMsg(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getMsg());
        try {
            UserInfo userInfo = userProvider.get();
            log.error("请假taskId:{},status:{},userInfo:{}", taskId, status, userInfo);
            attendanceApproveService.leaveApprove(taskId, status, userInfo.getTenantId(), userInfo.getUserId(), userInfo.getUserName());
        } catch (Exception e) {
            log.error("exception", e);
            result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
            result.setMsg(e.getMessage());
        }
        log.error("请假 result:{}", result);
        return result;
    }



    /**
     * 新建加班申请
     *
     * @param attendanceWorkOvertimeApproveDto 表单对象
     * @return java.lang.Object
     */
    @PostMapping("/createWorkOvertimeForOa")
    public Object createWorkOvertimeForOa(@RequestBody @Valid AttendanceWorkOvertimeApproveDto attendanceWorkOvertimeApproveDto) {
        // AttendanceWorkOvertimeApproveDto(super=AttendanceBaseForOa(super=jnpf.model.workflow.dto.AttendanceWorkOvertimeApproveDto@dc44583a, taskId=623849038774196101, status=null, fFlowtaskid=null, fFlowid=null, uniqueId=null, tenantId=null, flowTitle=null, applyUser=["450558466533106821"], startTime=Wed Nov 06 14:12:00 CST 2024, endTime=Wed Nov 06 15:13:00 CST 2024, time=[1730873520000, 1730877180000], unit=null), id=null, userId=null, workDay=null, startTime=Wed Nov 06 14:12:00 CST 2024, endTime=Wed Nov 06 15:13:00 CST 2024, time=[1730873520000, 1730877180000], reason=null, flowtaskid=null, flowid=null, uniqueid=null, tenantId=null, picture=null, fileJson=null, flowTitle=null, applyUser=["450558466533106821"], applyDate=null, submitStatus=null, shiftInvolved=null, groupId=504574013792892037)
        log.error("新建加班申请 参数 : {}", attendanceWorkOvertimeApproveDto);
        ActionResult<Void> result = new ActionResult<>();
        result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getCode());
        result.setMsg(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getMsg());
        String userId = userProvider.get().getUserId();
        attendanceWorkOvertimeApproveDto.setUserId(userId);
        attendanceWorkOvertimeApproveDto.setTenantId(userProvider.get().getTenantId());
        attendanceWorkOvertimeApproveDto.setId(attendanceWorkOvertimeApproveDto.getTaskId());
        AttendanceWorkOvertimeApprove entity = JsonUtil.getJsonToBean(attendanceWorkOvertimeApproveDto, AttendanceWorkOvertimeApprove.class);
        // 处理加班日期
        entity.setWorkDay(attendanceWorkOvertimeApproveDto.getStartTime());
        try {
            attendanceApproveService.submitCheckWorkForOa(attendanceWorkOvertimeApproveDto);
            entity.setId(attendanceWorkOvertimeApproveDto.getTaskId());
            workApproveService.saveForOa(entity);
        } catch (Exception e) {
            result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }


    /**
     * 加班审批通过后触发接口
     *
     * @param taskId 审批的唯一id 对应表f_id
     * @param status 是否审核通过 0.待审核 2.未通过 1.通过
     * @author hlp
     */
    @GetMapping(value = "/oaApprove/work/pass")
    public ActionResult workApproveForOa(@RequestParam(value = "taskId") String taskId, @RequestParam(value = "status") Integer status) {
        ActionResult<Void> result = new ActionResult<>();
        result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getCode());
        result.setMsg(FtbPersonnelsCheckStatusCodeEnum.CHECK_PASS.getMsg());
        try {
            UserInfo user = UserProvider.getUser();
            log.error("加班审批通过后的触发接口 tenantId : {},入参applyId:{}", user.getTenantId(), taskId);
            attendanceApproveService.checkWork(taskId);
            attendanceApproveService.workApprove(taskId, status, user.getTenantId(), user.getUserId(), user.getUserName());
        } catch (Exception e) {
            result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }

    /**
     * 获取用户所选时间段所在考勤组
     */
    @PostMapping("/getUserGroupByTime")
    public ActionResult getUserGroupByTime(@RequestBody GroupOaDto groupOaDto) {
        log.error("getUserGroupByTime groupOaDto:{}", groupOaDto.toString());
        if (groupOaDto.isFromOaCondition()){
            List<AttendanceGroupVo> attendanceGroupVos = attendanceGroupService.secondedApprovalGroupListNew();
            return ActionResult.success(attendanceGroupVos.stream().map(vo->{
                GroupMiniVo groupMiniVo = new GroupMiniVo();
                groupMiniVo.setGroupId(vo.getId());
                groupMiniVo.setGroupName(vo.getGroupName());
                return groupMiniVo;
            }).collect(Collectors.toList()));
        }

        if (null == groupOaDto.getUserId()) {
            groupOaDto.setUserIdStr(userProvider.get().getUserId());
        } else {
            groupOaDto.setUserIdStr(groupOaDto.getUserId()[0]);
        }
        log.error("getUserGroupByTime groupOaDto:{}", groupOaDto);
        return attendanceApproveService.getUserGroupByTime(groupOaDto);
    }


    /**
     * oa收拢获取请假申请时长及设计班次(请假时选择了开始和结束时间后请求该接口)
     *
     * @param leaveQueryForOaDto 参数
     * @return jnpf.base.ActionResult<jnpf.model.attendance.vo.LeaveShiftVo>
     * @author hlp
     */
    @PostMapping("/leaveDurationForOa")
    public ActionResult<LeaveShiftVo> getLeaveDuration(@RequestBody LeaveQueryForOaDto leaveQueryForOaDto) throws HandleException {
        log.error("leaveDurationForOa leaveQueryForOaDto:{}", leaveQueryForOaDto);
        if (null == leaveQueryForOaDto.getTime() || leaveQueryForOaDto.getTime().length < 1) {
            return ActionResult.fail("时间参数不能为空");
        }
        LeaveQueryDto leaveQueryDto = new LeaveQueryDto(leaveQueryForOaDto.getUnit(), leaveQueryForOaDto.getStartTime().getTime() + "", leaveQueryForOaDto.getEndTime().getTime() + "", leaveQueryForOaDto.getStartTimeType(), leaveQueryForOaDto.getEndTimeType(), leaveQueryForOaDto.getApplyId(), leaveQueryForOaDto.getTypeId());
        log.error("leaveDurationForOa leaveQueryDto:{}", leaveQueryDto);
        LeaveShiftVo vo = attendanceApproveService.getLeaveDuration(leaveQueryDto);
        return ActionResult.success(vo);
    }

    /**
     * 获取用户当前时间所在考勤组
     */
    @GetMapping("/nowGroup")
    public ActionResult getNowGroup() {
        return attendanceApproveService.getNowGroup();
    }


    /**
     * 提供OA使用时长计算
     *
     * @param time 时间数组
     * @return 时长
     */
    @GetMapping("/oaForTime")
    public ActionResult getOaForTime(String[] time) {
        Date startTime = new Date(Long.valueOf(time[0]));
        Date endTime = new Date(Long.valueOf(time[1]));
        // 校验结束时间不能小于开始时间
        if (endTime.before(startTime)) {
            return ActionResult.fail("结束时间不能小于开始时间");
        }

        BigDecimal totalDuration = FtbUtil.getTimeDifference(startTime, endTime);
        TimeVo timeVo = new TimeVo();
        timeVo.setTotalDuration(totalDuration);
        return ActionResult.success(timeVo);

    }


    @Override
    @PostMapping(value = "/attendanceToThousandsFaces")
    public AttendanceToThousandsFacesVo attendanceToThousandsFaces() {
        return attendanceApproveService.attendanceToThousandsFaces();
    }

    /**
     * 选择了请假类型和请假时间后请求接口，获取用户余额使用情况：
     *
     * @param leaveQueryForOaDto 参数
     * @return 用户剩余请假时长
     */

    @PostMapping("/residueBalance")
    public ActionResult getResidueBalance(@RequestBody LeaveQueryForOaDto leaveQueryForOaDto)  {
        log.error("leaveDurationForOa leaveQueryForOaDto:{}", leaveQueryForOaDto);
        if (null == leaveQueryForOaDto.getTime() || leaveQueryForOaDto.getTime().length < 1) {
            return ActionResult.fail("时间参数不能为空");
        }
        LeaveQueryDto leaveQueryDto = new LeaveQueryDto(leaveQueryForOaDto.getUnit(), leaveQueryForOaDto.getStartTime().getTime() + "", leaveQueryForOaDto.getEndTime().getTime() + "", leaveQueryForOaDto.getStartTimeType(), leaveQueryForOaDto.getEndTimeType(), leaveQueryForOaDto.getApplyId(), leaveQueryForOaDto.getTypeId());
        if (null == leaveQueryDto.getStartTime() || leaveQueryDto.getStartTime().isEmpty()) {
            return ActionResult.fail("开始时间不能为空");
        }
        if (null == leaveQueryDto.getEndTime() || leaveQueryDto.getEndTime().isEmpty()) {
            return ActionResult.fail("结束时间不能为空");
        }
        if (null == leaveQueryDto.getTypeId() || leaveQueryDto.getTypeId().isEmpty()) {
            return ActionResult.fail("请选择请假类型");
        }
        LeaveConsumptionDetailVo residueBalance = null;
        try {
            residueBalance = attendanceApproveService.getResidueBalance(leaveQueryDto);
        } catch (Exception e) {
            ActionResult<Void> result = new ActionResult<>();
            result.setCode(FtbPersonnelsCheckStatusCodeEnum.CHECK_REFUSE.getCode());
            result.setMsg(e.getMessage());
            return result;
        }
        // 3天调休假+0.5天存休(剩余5.5天)
        StringBuilder sb = new StringBuilder();
        assert residueBalance != null;
        if (residueBalance.getInputTypeBalance().compareTo(BigDecimal.ZERO) > 0) {
            sb.append(residueBalance.getInputTypeBalanceStr());
        }
        if (residueBalance.getInputTypeBalance().compareTo(BigDecimal.ZERO) > 0 && residueBalance.getRetirementLeave().compareTo(BigDecimal.ZERO) > 0) {
            sb.append("+");
        }
        if (residueBalance.getRetirementLeave().compareTo(BigDecimal.ZERO) > 0) {
            sb.append(residueBalance.getRetirementLeaveStr());
        }
        if (residueBalance.getBalance().compareTo(BigDecimal.ZERO) > 0) {
            sb.append("(剩余").append(residueBalance.getBalance().setScale(2, RoundingMode.HALF_UP)).append("天)");
        }
        return ActionResult.success(new HashMap<>(){{put("residueBalance",sb.toString());}});
    }


}
