package com.ruoyi.system.manager;


import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.TdApplyInfoList;
import com.ruoyi.system.enums.ApplyListStatusEnum;
import com.ruoyi.system.service.ISysDictTypeService;
import com.ruoyi.system.service.TdApplyInfoListService;
import lombok.val;
import org.dromara.warm.flow.core.FlowFactory;
import org.dromara.warm.flow.core.dto.FlowParams;
import org.dromara.warm.flow.core.entity.Instance;
import org.dromara.warm.flow.core.entity.Task;
import org.dromara.warm.flow.core.enums.SkipType;
import org.dromara.warm.flow.core.service.InsService;
import org.dromara.warm.flow.core.service.TaskService;
import org.dromara.warm.flow.core.utils.IdUtils;
import org.dromara.warm.flow.core.utils.StreamUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;


/**
 * ClassName: ApplyInfoListManager
 * Package: com.ruoyi.web.controller.manager
 * Description:人员管理
 *
 * @Author wangxy
 * @Create 2025/5/14 11:30
 * @Version 1.0
 */
@Component
public class ApplyInfoListManager {


    @Resource
    private TdApplyInfoListService applyInfoListService;


    @Resource
    private InsService insService;

    @Resource
    private TaskService taskService;


    @Resource
    private ISysDictTypeService sysDictTypeService;


    /**
     * 人员登记
     *
     * @param applyInfoList
     * @return
     */
    public List<TdApplyInfoList> selectTdApplyInfoListList(TdApplyInfoList applyInfoList) {
        return applyInfoListService.selectApplyInfoListList(applyInfoList);
    }


    public TdApplyInfoList selectTdApplyInfoListById(String applyId) {
        return applyInfoListService.lambdaQuery().eq(TdApplyInfoList::getApplyId, applyId).one();
    }


    public boolean insertTdApplyInfoList(TdApplyInfoList applyInfoList) {
        // 设置流转参数
        String id = IdUtils.nextIdStr();
        applyInfoList.setApplyId(id);
        LoginUser user = SecurityUtils.getLoginUser();
        // 从字典表中获取流程编码
        String flowCode = getFlowType(1L);
        // 传递流程编码，绑定流程定义 【必传】
        FlowParams flowParams = FlowParams.build().flowCode(flowCode);
        // 设置办理人唯一标识，保存为流程实例的创建人 【必传】
        flowParams.handler(user.getUser().getUserId().toString());
        // 流程变量
        Map<String, Object> variable = new HashMap<>();
        // 流程变量传递业务数据，按实际业务需求传递 【按需传】
        variable.put("businessData", applyInfoList);
        variable.put("businessType", "applyInfoList");
        // 条件表达式替换，判断是否满足某个任务的跳转条件  【按需传】
        variable.put("flag", 1);
        // 办理人变量表达式替换  【按需传】
        variable.put("handler1", Arrays.asList(4, "5", 100L));
        variable.put("handler2", 12L);
        variable.put("handler3", new Object[]{9, "10", 102L});
        variable.put("handler4", "15");
        Task task = FlowFactory.newTask().setId(55L);
        variable.put("handler5", task);
        variable.put("handler6", 77L);
        flowParams.variable(variable);
        // 新增请假表
        Instance instance = insService.start(id, flowParams);
        applyInfoList.setInstanceId(instance.getId());
        applyInfoList.setNodeCode(instance.getNodeCode());
        applyInfoList.setNodeName(instance.getNodeName());
        applyInfoList.setNodeType(instance.getNodeType());
        applyInfoList.setFlowStatus(instance.getFlowStatus());
        applyInfoList.setCreateTime(DateUtils.getNowDate());
        applyInfoList.setDeptId(SecurityUtils.getDeptId());
        applyInfoList.setDeptName(SecurityUtils.getLoginUser().getUser().getDept().getDeptName());
        applyInfoList.setCreateId(SecurityUtils.getLoginUser().getUserId());
        applyInfoList.setCreateBy(SecurityUtils.getLoginUser().getUsername());
        applyInfoList.setApplyStatus(ApplyListStatusEnum.NEWSAVE.getStatus());
        return applyInfoListService.save(applyInfoList);

    }


    public boolean updateTdApplyInfoList(TdApplyInfoList applyInfoList) {
        applyInfoList.setUpdateTime(DateUtils.getNowDate());
        applyInfoList.setUpdateBy(SecurityUtils.getLoginUser().getUsername());
        return applyInfoListService.saveOrUpdate(applyInfoList);

    }


    @Transactional(rollbackFor = Exception.class)
    public boolean submit(String id) {
        // 设置流转参数
        TdApplyInfoList applyInfoList = applyInfoListService.lambdaQuery()
                .eq(TdApplyInfoList::getApplyId, id).one();
        LoginUser user = SecurityUtils.getLoginUser();
        // 是通过流程还是退回流程  【必传】
        FlowParams flowParams = FlowParams.build().skipType(SkipType.PASS.getKey());
        // 作为办理人保存到历史记录表 【必传】
        flowParams.handler(user.getUser().getUserId().toString());
        // 设置办理人拥有的权限，办理中需要校验是否有权限办理 【必传】
        List<SysRole> roles = user.getUser().getRoles();
        List<String> permissionList = new ArrayList<>();
        if (Objects.nonNull(roles)) {
            permissionList = roles.stream().map(role -> "role:" + role.getRoleId()).collect(Collectors.toList());
        }
        permissionList.add("dept:" + SecurityUtils.getLoginUser().getUser().getDeptId());
        permissionList.add(user.getUser().getUserId().toString());
        flowParams.permissionFlag(permissionList);
        // 流程变量
        Map<String, Object> variable = new HashMap<>();
        // 流程变量传递业务数据，按实际业务需求传递  【按需传】
        variable.put("businessType", "applyInfoList");
        // 办理人变量表达式替换  【按需传】
        variable.put("flag", 1);
        flowParams.variable(variable);
        // 更新请假表
        Instance instance = insService.skipByInsId(applyInfoList.getInstanceId(), flowParams);
        applyInfoList.setNodeCode(instance.getNodeCode());
        applyInfoList.setNodeName(instance.getNodeName());
        applyInfoList.setNodeType(instance.getNodeType());
        applyInfoList.setFlowStatus(instance.getFlowStatus());
        applyInfoList.setUpdateTime(DateUtils.getNowDate());
        applyInfoList.setApplyStatus(ApplyListStatusEnum.SUBMIT.getStatus());
        return applyInfoListService.saveOrUpdate(applyInfoList);
    }


    @Transactional(rollbackFor = Exception.class)
    public boolean handle(TdApplyInfoList applyInfoList, Long taskId, String skipType, String message) {
        // 设置流转参数
        LoginUser user = SecurityUtils.getLoginUser();
        // 是通过流程还是退回流程 【必传】
        FlowParams flowParams = FlowParams.build().skipType(skipType);
        // 作为办理人保存到历史记录表 【必传】
        flowParams.handler(user.getUser().getUserId().toString());
        // 作为审批意见保存到历史记录表  【按需传】
        flowParams.message(message);
        // 流程变量
        Map<String, Object> variable = new HashMap<>();
        // 流程变量传递业务数据，按实际业务需求传递  【按需传】
        variable.put("businessType", "applyInfoList");
        // 办理人变量表达式替换  【按需传】
        variable.put("flag", 1);
        flowParams.variable(variable);
        // 请假信息存入flowParams,方便查看历史审批数据  【按需传】
        flowParams.hisTaskExt(JSON.toJSONString(applyInfoList));
        Instance instance = taskService.skip(taskId, flowParams);
        // 更新请假表
        applyInfoList.setNodeCode(instance.getNodeCode());
        applyInfoList.setNodeName(instance.getNodeName());
        applyInfoList.setNodeType(instance.getNodeType());
        applyInfoList.setFlowStatus(instance.getFlowStatus());
        if ("PASS".equals(skipType)) {
            applyInfoList.setApplyStatus(ApplyListStatusEnum.AUDITED.getStatus());
        } else {
            applyInfoList.setApplyStatus(ApplyListStatusEnum.GOBACK.getStatus());
        }
        applyInfoList.setUpdateTime(DateUtils.getNowDate());
        return applyInfoListService.saveOrUpdate(applyInfoList);
    }


    public boolean termination(TdApplyInfoList applyInfoList) {
        // 设置流转参数
        FlowParams flowParams = new FlowParams();
        LoginUser user = SecurityUtils.getLoginUser();
        // 作为审批意见保存到历史记录表  【按需传】
        flowParams.message("终止流程");
        // 作为办理人保存到历史记录表 【必传】
        flowParams.handler(user.getUserId().toString());
        Map<String, Object> variable = new HashMap<>();
        // 流程变量传递业务数据，按实际业务需求传递  【按需传】
        variable.put("businessType", "applyInfoList");
        flowParams.variable(variable);
        Instance instance = insService.termination(applyInfoList.getInstanceId(), flowParams);
        if (instance == null) {
            throw new ServiceException("流程实例不存在");
        }
        // 更新请假表
        applyInfoList.setNodeCode(instance.getNodeCode());
        applyInfoList.setNodeName(instance.getNodeName());
        applyInfoList.setNodeType(instance.getNodeType());
        applyInfoList.setFlowStatus(instance.getFlowStatus());
        applyInfoList.setApplyStatus(ApplyListStatusEnum.NEWSAVE.getStatus());
        return applyInfoListService.saveOrUpdate(applyInfoList);
    }


    public int deleteApplyInfoListByIds(String[] applyIds) {
        List<String> list = Arrays.asList(applyIds);
        List<TdApplyInfoList> applyInfoListList = applyInfoListService.
                lambdaQuery().in(TdApplyInfoList::getApplyId, list).list();
        if (applyInfoListService.lambdaUpdate().in(TdApplyInfoList::getApplyId, list).remove()) {
            List<Long> instanceIds = applyInfoListList.stream().map(TdApplyInfoList::getInstanceId).collect(Collectors.toList());
            return insService.remove(instanceIds) ? 1 : 0;
        }
        return 0;
    }


    /**
     * 从字典表中获取流程编码
     *
     * @param type 请假信息
     * @return 流程编码
     */
    private String getFlowType(Long type) {
        List<SysDictData> leaveType = sysDictTypeService.selectDictDataByType("leave_type");
        Map<String, String> map = StreamUtils.toMap(leaveType, SysDictData::getDictValue, SysDictData::getRemark);
        return map.get(type.toString());
    }


}
