package com.jy.flow.controller;


import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jy.flow.adapter.AbstractWarmFlowAdapter;
import com.jy.flow.dto.FlowHisTaskDto;
import com.jy.flow.dto.FlowTaskDto;
import com.jy.flow.service.ExecuteService;
import com.jy.flow.service.HhDefService;
import com.jy.flow.vo.FlowTaskVo;
import com.jy.flow.vo.WarmFlowInteractiveTypeVo;
import com.jy.framework.satoken.LoginContext;
import com.jy.system.dao.SysDeptDao;
import com.jy.system.dao.SysRoleDao;
import com.jy.system.dao.SysUserDao;
import com.jy.system.model.dto.SysUserSelectDto;
import com.jy.system.model.entity.SysDept;
import com.jy.system.model.entity.SysRole;
import com.jy.system.model.entity.SysUser;
import com.jy.system.model.vo.SysUserVo;
import com.warm.flow.core.FlowFactory;
import com.warm.flow.core.entity.HisTask;
import com.warm.flow.core.entity.Instance;
import com.warm.flow.core.entity.Node;
import com.warm.flow.core.entity.Task;
import com.warm.flow.core.entity.User;
import com.warm.flow.core.enums.CooperateType;
import com.warm.flow.core.enums.UserType;
import com.warm.flow.core.service.HisTaskService;
import com.warm.flow.core.service.InsService;
import com.warm.flow.core.service.NodeService;
import com.warm.flow.core.service.TaskService;
import com.warm.flow.core.service.UserService;
import com.warm.flow.core.utils.StreamUtils;
import com.warm.flow.orm.entity.FlowHisTask;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/flow/execute")
public class ExecuteController {

    @Resource
    private SysUserDao sysUserDao;

    @Resource
    private SysDeptDao sysDeptDao;

    @Resource
    private SysRoleDao sysRoleDao;

    @Resource
    private HisTaskService hisTaskService;

    @Resource
    private TaskService taskService;

    @Resource
    private NodeService nodeService;

    @Resource
    private InsService insService;

    @Resource
    private UserService flowUserservice;

    @Resource
    private ExecuteService executeService;

    @Resource
    private HhDefService hhDefService;

    /**
     * 分页待办任务列表
     */
    @GetMapping("/todoPage")
    public Page<FlowTaskVo> toDoPage(FlowTaskDto dto) {
        dto.setPermissionList(AbstractWarmFlowAdapter.permissionList());
        Page<FlowTaskVo> page = executeService.toDoPage(dto);
        List<FlowTaskVo> list = page.getRecords();

        List<Long> taskIds = StreamUtils.toList(list, FlowTaskVo::getId);
        List<User> userList = flowUserservice.getByAssociateds(taskIds);
        Map<Long, List<User>> map = StreamUtils.groupByKey(userList, User::getAssociated);
        for (FlowTaskVo taskVo : list) {
            if (ObjectUtil.isNull(taskVo)) {
                continue;
            }
            List<User> users = map.get(taskVo.getId());

            if (ObjectUtil.isEmpty(users)) {
                continue;
            }

            for (User user : users) {
                switch (UserType.getByKey(user.getType())) {
                    case APPROVAL -> {
                        if (StrUtil.isEmpty(taskVo.getApprover())) {
                            taskVo.setApprover("");
                        }
                        String name = getName(user.getProcessedBy());
                        if (StrUtil.isNotEmpty(name))
                            taskVo.setApprover(taskVo.getApprover().concat(name).concat(";"));
                    }
                    case TRANSFER -> {
                        if (StrUtil.isEmpty(taskVo.getTransferredBy())) {
                            taskVo.setTransferredBy("");
                        }
                        String name = getName(user.getProcessedBy());
                        if (StrUtil.isNotEmpty(name))
                            taskVo.setTransferredBy(taskVo.getTransferredBy().concat(name).concat(";"));
                    }
                    case DEPUTE -> {
                        if (StrUtil.isEmpty(taskVo.getDelegate())) {
                            taskVo.setDelegate("");
                        }
                        String name = getName(user.getProcessedBy());
                        if (StrUtil.isNotEmpty(name))
                            taskVo.setDelegate(taskVo.getDelegate().concat(name).concat(";"));
                    }
                }
            }
        }
        return page;
    }

    /**
     * 分页抄送任务列表
     */
    @GetMapping("/copyPage")
    public Page<FlowHisTask> copyPage(FlowTaskDto dto) {
        dto.setPermissionList(AbstractWarmFlowAdapter.permissionList());
        return executeService.copyPage(dto);
    }

    /**
     * 分页已办任务列表
     */
    @GetMapping("/donePage")
    public Page<FlowHisTask> donePage(FlowHisTaskDto dto) {
        dto.setPermissionList(AbstractWarmFlowAdapter.permissionList());
        Page<FlowHisTask> page = executeService.donePage(dto);
        List<FlowHisTask> list = page.getRecords();
        Map<Long, String> userMap = StreamUtils.toMap(sysUserDao.list(), SysUser::getId, SysUser::getNickname);

        if (CollectionUtils.isNotEmpty(list)) {
            for (FlowHisTask hisTaskVo : list) {
                if (StrUtil.isNotEmpty(hisTaskVo.getApprover())) {
                    String name = getName(hisTaskVo.getApprover());
                    hisTaskVo.setApprover(name);
                }
                if (StrUtil.isNotEmpty(hisTaskVo.getCollaborator())) {
                    hisTaskVo.setCollaborator(userMap.get(Long.valueOf(hisTaskVo.getCollaborator())));
                }
            }
        }
        return page;
    }

    /**
     * 查询已办任务历史记录
     */
    @GetMapping("/doneList/{instanceId}")
    public List<FlowHisTask> doneList(@PathVariable("instanceId") Long instanceId) {
        List<HisTask> flowHisTasks = hisTaskService.orderById().desc().list(new FlowHisTask().setInstanceId(instanceId));
        Map<Long, String> userMap = StreamUtils.toMap(sysUserDao.list(), SysUser::getId, SysUser::getNickname);

        List<FlowHisTask> flowHisTaskList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(flowHisTasks)) {
            for (HisTask hisTask : flowHisTasks) {
                if (StrUtil.isNotEmpty(hisTask.getApprover())) {
                    String name = getName(hisTask.getApprover());
                    hisTask.setApprover(name);
                }
                if (StrUtil.isNotEmpty(hisTask.getCollaborator())) {
                    hisTask.setCollaborator(userMap.get(Long.valueOf(hisTask.getCollaborator())));
                }
                FlowHisTask flowHisTask = new FlowHisTask();
                BeanUtils.copyProperties(hisTask, flowHisTask);
                flowHisTaskList.add(flowHisTask);
            }
        }
        return flowHisTaskList;
    }

    /**
     * 根据taskId查询代表任务
     */
    @GetMapping("/getTaskById/{taskId}")
    public Task getTaskById(@PathVariable("taskId") Long taskId) {
        return taskService.getById(taskId);
    }

    /**
     * 查询跳转任意节点列表
     */
    @GetMapping("/anyNodeList/{instanceId}")
    public List<Node> anyNodeList(@PathVariable("instanceId") Long instanceId) {
        Instance instance = insService.getById(instanceId);
        return nodeService.list(FlowFactory.newNode().setDefinitionId(instance.getDefinitionId()));
    }

    /**
     * 处理非办理的流程交互类型
     *
     * @param warmFlowInteractiveTypeVo 要转办用户
     * @return 是否成功
     */
    @PostMapping("/interactiveType")
    public Boolean interactiveType(WarmFlowInteractiveTypeVo warmFlowInteractiveTypeVo) {
        return hhDefService.interactiveType(warmFlowInteractiveTypeVo);
    }

    /**
     * 交互类型可以选择的用户
     *
     * @param vo 交互类型请求类
     * @return 是否成功
     */
    @GetMapping("/interactiveTypeSysUser")
    public Page<SysUserVo> interactiveTypeSysUser(WarmFlowInteractiveTypeVo vo) {
        Integer operatorType = vo.getOperatorType();
        Long taskId = vo.getTaskId();

        List<User> users = flowUserservice.listByAssociatedAndTypes(taskId);
        Set<Long> userIdSet = users.stream().map(User::getProcessedBy).map(Convert::toLong).collect(Collectors.toSet());

        SysUserSelectDto sysUserSelectDto = new SysUserSelectDto();
        sysUserSelectDto.setDeptId(vo.getDeptId());
        if (!Objects.equals(CooperateType.REDUCTION_SIGNATURE.getKey(), operatorType)) {
            sysUserSelectDto.setNotInUserIdList(userIdSet);
        } else {
            sysUserSelectDto.setInUserIdList(userIdSet);
            sysUserSelectDto.setNotInUserIdList(Collections.singletonList(LoginContext.getUserId()));
        }

        return sysUserDao.getPage(sysUserSelectDto);
    }

    /**
     * 激活流程
     */
    @GetMapping("/active/{instanceId}")
    public Boolean active(@PathVariable("instanceId") Long instanceId) {
        return insService.active(instanceId);
    }

    /**
     * 挂起流程
     */
    @GetMapping("/unActive/{instanceId}")
    public Boolean unActive(@PathVariable("instanceId") Long instanceId) {
        return insService.unActive(instanceId);
    }

    /**
     * 根据ID反显姓名
     **/
    @GetMapping(value = "/idReverseDisplayName/{ids}")
    public List<SysUser> idReverseDisplayName(@PathVariable Long[] ids) {
        return sysUserDao.listByIds(Arrays.asList(ids));
    }


    private String getName(String id) {
        Map<Long, String> userMap = StreamUtils.toMap(sysUserDao.list(), SysUser::getId, SysUser::getNickname);
        Map<Long, String> deptMap = StreamUtils.toMap(sysDeptDao.list(), SysDept::getId, SysDept::getName);
        Map<Long, String> roleMap = StreamUtils.toMap(sysRoleDao.list(), SysRole::getId, SysRole::getName);

        if (StrUtil.isNotBlank(id)) {
            if (id.contains("user:")) {
                String name = userMap.get(Long.valueOf(id.replace("user:", "")));
                if (StrUtil.isNotEmpty(name)) {
                    return "用户:" + name;
                }
            } else if (id.contains("dept:")) {
                String name = deptMap.get(Long.valueOf(id.replace("dept:", "")));
                if (StrUtil.isNotEmpty(name)) {
                    return "部门:" + name;
                }
            } else if (id.contains("role")) {
                String name = roleMap.get(Long.valueOf(id.replace("role:", "")));
                if (StrUtil.isNotEmpty(name)) {
                    return "角色:" + name;
                }
            } else {
                try {
                    long parseLong = Long.parseLong(id);
                    String name = userMap.get(parseLong);
                    if (StrUtil.isNotEmpty(name)) {
                        return "用户:" + name;
                    }
                } catch (NumberFormatException e) {
                    return id;
                }

            }
        }
        return "";
    }

}
