package jnpf.workflow.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import jnpf.attendance.antifreeze.UserAntifreeze;
import jnpf.attendance.service.AttendanceDailyRuleService;
import jnpf.attendance.service.handle.notice.AttendanceNoticeHandler;
import jnpf.base.service.SuperServiceImpl;
import jnpf.constants.AttendanceConstant;
import jnpf.engine.vo.ApproverByTaskIdAndNodeIdVo;
import jnpf.entity.attendance.ApplyParam;
import jnpf.entity.workflow.AttendanceGoOutApprove;
import jnpf.entity.workflow.AttendanceLeaveApprove;
import jnpf.enums.attendance.ApprovalSettingTypeEnum;
import jnpf.enums.attendance.AttendanceNoticeEnum;
import jnpf.enums.attendance.AttendanceTypeEnum;
import jnpf.exception.HandleException;
import jnpf.model.attendance.dto.LeaveApproveForOaDto;
import jnpf.model.attendance.vo.DailyRuleResultVo;
import jnpf.model.attendance.vo.attendance.ApproveBaseImVo;
import jnpf.model.attendance.vo.attendance.ApproveImVo;
import jnpf.model.attendance.vo.attendance.AttendanceApproveImVo;
import jnpf.model.workflow.dto.AttendanceLeaveApproveDto;
import jnpf.model.workflow.vo.AttendanceLeaveFlowApproveVo;
import jnpf.permission.model.user.PartUserInfoVo;
import jnpf.util.*;
import jnpf.workflow.mapper.AttendanceLeaveMapper;
import jnpf.workflow.service.FlowTaskService;
import jnpf.workflow.service.LeaveApproveService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * describe
 *
 * @author HuangLinPan
 * @date 2023/12/11
 */
@Service
@Slf4j
public class LeaveApproveServiceImpl extends SuperServiceImpl<AttendanceLeaveMapper, AttendanceLeaveApprove> implements LeaveApproveService {
    @Autowired
    private UserAntifreeze userAntifreeze;

    @Resource
    private FlowTaskService flowTaskService;

    @Autowired
    private UserProvider userProvider;

    @Resource
    private AttendanceDailyRuleService attendanceDailyRuleService;

    @Autowired
    private AttendanceNoticeHandler attendanceNoticeHandler;

    @Resource
    private CustomTenantUtil customTenantUtil;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(String id, AttendanceLeaveApprove entity, AttendanceLeaveApproveDto attendanceLeaveApproveDto) {
        //表单信息
        if (StringUtil.isEmpty(entity.getId())) {
            entity.setId(id);
            save(entity);
            try {
                // 发送审批消息
                String tenantId = userProvider.get().getTenantId();
                new Thread(() -> {
                    // 睡眠1秒，确保事务提交完成
                    try {
                        Thread.sleep(1000);
                        leaveSendIm(entity, tenantId);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }).start();
            } catch (Exception e) {
                log.error("发送请假审批消息通知第一级审批人失败", e);
                throw new RuntimeException(e);
            }
        } else {
            entity.setId(id);
            updateById(entity);
        }
    }

    private void leaveSendIm(AttendanceLeaveApprove entity, String tenantId) throws HandleException {
        customTenantUtil.checkOutTenant(tenantId);
        // 查询第一节点审批人
        ApproverByTaskIdAndNodeIdVo data = flowTaskService.getApproveInfo(entity.getId(), null, tenantId, null);
        if (null != data) {
            AttendanceApproveImVo jsonToBean = JsonUtil.getJsonToBean(data, AttendanceApproveImVo.class);
            jsonToBean.setId(data.getTaskId());
            List<DailyRuleResultVo> dailyRuleResultVos = attendanceDailyRuleService.applyVerifyHandle(new ApplyParam(entity.getUserId(), entity.getStartTime(), entity.getEndTime(), AttendanceTypeEnum.LEAVE));
            // 实时获取申请时长
            BigDecimal hours = new BigDecimal("0");
            for (DailyRuleResultVo dailyRuleResultVo : dailyRuleResultVos) {
                hours = hours.add(dailyRuleResultVo.getDuration());
            }
            List<PartUserInfoVo> allByIds = userAntifreeze.getAllByIds(CollUtil.newArrayList(entity.getUserId()), tenantId);
            PartUserInfoVo partUserInfoVo = allByIds.stream().findFirst().orElse(null);
            // 组装消息
            ApproveImVo approveImVo = new ApproveImVo();
            approveImVo.setTenantId(tenantId);
            approveImVo.setAttendanceNoticeEnum(AttendanceNoticeEnum.APPROVE);
            ApproveBaseImVo approveBaseImVo = new ApproveBaseImVo();
            approveBaseImVo.setType(ApprovalSettingTypeEnum.LEAVE.getCode());
            approveBaseImVo.setStartTime(entity.getStartTime());
            approveBaseImVo.setEndTime(entity.getEndTime());
            approveBaseImVo.setStartTimeType(entity.getStartTimeType());
            approveBaseImVo.setEndTimeType(entity.getEndTimeType());
            approveBaseImVo.setUnit(entity.getUnit());
            // 请假类型
            approveBaseImVo.setLeaveType(entity.getType());
            StringBuilder stringBuffer = new StringBuilder();
            if (!Objects.isNull(partUserInfoVo)) {
                stringBuffer.append(partUserInfoVo.getRealName());
            }
            approveBaseImVo.setTitle(stringBuffer.append("的【请假】审批").toString());
            data.getUserOperators().forEach(v -> {
                approveImVo.setUserIds(CollUtil.newArrayList(v.getUserId()));
                jsonToBean.setTaskId(v.getTaskOperatorId());
                // URL 拼接
//                String encode = Base64Util.encode(JSONUtil.toJsonStr(jsonToBean));
                String encode = FtbUtil.encodeJson(jsonToBean);
                String url = AttendanceConstant.APPROVE_URL + encode;
                approveBaseImVo.setUrl(url);
                approveImVo.setApproveBaseImVo(approveBaseImVo);
                attendanceNoticeHandler.send(approveImVo);
            });
        }
    }

    @Override
    public void submit(String id, AttendanceLeaveApprove entity, AttendanceLeaveApproveDto attendanceLeaveApproveDto) {
        //表单信息
        if (StringUtil.isEmpty(entity.getId())) {
            entity.setId(id);
            save(entity);
            try {
                // 发送审批消息
                String tenantId = userProvider.get().getTenantId();
                new Thread(() -> {
                    // 睡眠1秒，确保事务提交完成
                    try {
                        Thread.sleep(1000);
                        leaveSendIm(entity, tenantId);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }).start();
            } catch (Exception e) {
                log.error("发送请假审批消息通知第一级审批人失败", e);
                throw new RuntimeException(e);
            }
        } else {
            entity.setId(id);
            updateById(entity);
        }
    }

    @Override
    public AttendanceLeaveFlowApproveVo getAttendanceLeave(String id) {
        AttendanceLeaveApprove attendanceLeaveApprove = this.getById(id);
        AttendanceLeaveFlowApproveVo jsonToBean = JsonUtil.getJsonToBean(attendanceLeaveApprove, AttendanceLeaveFlowApproveVo.class);
        // 当审核未通过时动态取值
//        if (1 != jsonToBean.getStatus()){
        // 动态获取涉及班次/借调班次

        // 实际使用余额/未抵扣余额/剩余余额(兑换券/抵扣劵)


//        }
        return jsonToBean;
    }

    @Override
    public void saveForOa(LeaveApproveForOaDto dto) {
        AttendanceLeaveApprove entity = JsonUtil.getJsonToBean(dto, AttendanceLeaveApprove.class);
        entity.setUserId(JSONUtil.toList(dto.getApplyUser(), String.class).get(0));
        log.error("FoeOa开始存数据库请假参数................: {}", entity);
        save(entity);
    }
}
