package cn.iocoder.yudao.module.bpm.service.oa;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.workorderassignrule.BpmOAWorkOrderAssignRulePageReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.workorderassignrule.BpmOAWorkOrderAssignRuleRespVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.workorderassignrule.BpmOAWorkOrderAssignRuleSaveReqVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAWorkOrderAssignRuleDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAWorkOrderAssignRuleMapper;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_WORK_TASK_NOT_EXISTS;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.THE_WORK_ORDER_RULE_TYPE_ALREADY_EXISTS_PLEASE_DO_NOT_ADD_IT_REPEATEDLY;

/**
 * BPM OA 工单分配规则 Service 实现类
 *
 * @author 系统
 */
@Service
@Validated
public class BpmOAWorkOrderAssignRuleServiceImpl implements BpmOAWorkOrderAssignRuleService {

    @Resource
    private BpmOAWorkOrderAssignRuleMapper workOrderAssignRuleMapper;

    @Resource
    private AdminUserApi userApi;

    @Resource
    private DeptApi deptApi;

    @Resource
    private DictDataApi dictDataApi;

    private static final String WORK_ORDER_TYPE = "work_order_type";
    private static final String WORK_ORDER_ASSIGN_RULE_STATUS = "work_order_assign_rule_status";

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createWorkOrderAssignRule(BpmOAWorkOrderAssignRuleSaveReqVO createReqVO) {
        // 插入
        BpmOAWorkOrderAssignRuleDO workOrderAssignRule = BeanUtils.toBean(createReqVO, BpmOAWorkOrderAssignRuleDO.class);
        // -- 判断系统中是否已经存在该规则 - 如果存在提示已存在 - 请勿重复添加
        BpmOAWorkOrderAssignRuleDO bpmOAWorkOrderAssignRuleDO = workOrderAssignRuleMapper.selectOne(new LambdaQueryWrapperX<BpmOAWorkOrderAssignRuleDO>()
                .eq(BpmOAWorkOrderAssignRuleDO::getWorkOrderType, workOrderAssignRule.getWorkOrderType()));
        if (bpmOAWorkOrderAssignRuleDO != null) {
            throw exception(THE_WORK_ORDER_RULE_TYPE_ALREADY_EXISTS_PLEASE_DO_NOT_ADD_IT_REPEATEDLY);
        }
        workOrderAssignRuleMapper.insert(workOrderAssignRule);

        // 返回
        return workOrderAssignRule.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateWorkOrderAssignRule(BpmOAWorkOrderAssignRuleSaveReqVO updateReqVO) {
        // 校验存在
        validateWorkOrderAssignRuleExists(updateReqVO.getId());
        // 更新
        BpmOAWorkOrderAssignRuleDO updateObj = BeanUtils.toBean(updateReqVO, BpmOAWorkOrderAssignRuleDO.class);
        workOrderAssignRuleMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteWorkOrderAssignRule(Long id) {
        // 校验存在
        validateWorkOrderAssignRuleExists(id);

        // 删除
        workOrderAssignRuleMapper.deleteById(id);
    }

    private BpmOAWorkOrderAssignRuleDO validateWorkOrderAssignRuleExists(Long id) {
        BpmOAWorkOrderAssignRuleDO workOrderAssignRule = workOrderAssignRuleMapper.selectById(id);
        if (workOrderAssignRule == null) {
            throw exception(OA_WORK_TASK_NOT_EXISTS);
        }
        return workOrderAssignRule;
    }

    @Override
    public BpmOAWorkOrderAssignRuleDO getWorkOrderAssignRule(Long id) {
        return workOrderAssignRuleMapper.selectById(id);
    }

    @Override
    public PageResult<BpmOAWorkOrderAssignRuleRespVO> getWorkOrderAssignRulePage(BpmOAWorkOrderAssignRulePageReqVO pageReqVO) {
        PageResult<BpmOAWorkOrderAssignRuleDO> pageResult = workOrderAssignRuleMapper.selectPage(pageReqVO);
        return new PageResult<>(convertList(pageResult.getList()), pageResult.getTotal());
    }

    @Override
    public List<BpmOAWorkOrderAssignRuleRespVO> getWorkOrderAssignRuleList(BpmOAWorkOrderAssignRulePageReqVO exportReqVO) {
        List<BpmOAWorkOrderAssignRuleDO> list = workOrderAssignRuleMapper.selectList(new LambdaQueryWrapperX<BpmOAWorkOrderAssignRuleDO>()
                .likeIfPresent(BpmOAWorkOrderAssignRuleDO::getWorkOrderType, exportReqVO.getWorkOrderType())
                .eqIfPresent(BpmOAWorkOrderAssignRuleDO::getDeptId, exportReqVO.getDeptId())
                .eqIfPresent(BpmOAWorkOrderAssignRuleDO::getAssigneeUserId, exportReqVO.getAssigneeUserId())
                .betweenIfPresent(BpmOAWorkOrderAssignRuleDO::getCreateTime, exportReqVO.getCreateTime()));
        return convertList(list);
    }

    @Override
    public List<BpmOAWorkOrderAssignRuleDO> getEnabledRulesByType(String workOrderType) {
        return workOrderAssignRuleMapper.selectRulesByType(workOrderType);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRuleStatus(Collection<Long> ids, Integer status) {
        // 批量更新状态
        ids.forEach(id -> {
            BpmOAWorkOrderAssignRuleDO updateObj = new BpmOAWorkOrderAssignRuleDO();
            updateObj.setId(id);
            workOrderAssignRuleMapper.updateById(updateObj);
        });
    }

    private List<BpmOAWorkOrderAssignRuleRespVO> convertList(List<BpmOAWorkOrderAssignRuleDO> list) {
        if (list.isEmpty()) {
            return java.util.Collections.emptyList();
        }

        // 获取用户信息
        Map<Long, AdminUserRespDTO> userMap = convertMap(
                userApi.getUserList(list.stream().map(BpmOAWorkOrderAssignRuleDO::getAssigneeUserId).collect(Collectors.toSet())).getCheckedData(),
                AdminUserRespDTO::getId);

        // 获取部门信息
        Map<Long, DeptRespDTO> deptMap = convertMap(
                deptApi.getDeptList(list.stream().map(BpmOAWorkOrderAssignRuleDO::getDeptId).collect(Collectors.toSet())).getCheckedData(),
                DeptRespDTO::getId);

        // 获取字典信息
        Map<String, DictDataRespDTO> workOrderTypeMap = convertMap(
                dictDataApi.getDictDataList(WORK_ORDER_TYPE).getCheckedData(),
                DictDataRespDTO::getValue);

        Map<String, DictDataRespDTO> statusMap = convertMap(
                dictDataApi.getDictDataList(WORK_ORDER_ASSIGN_RULE_STATUS).getCheckedData(),
                DictDataRespDTO::getValue);

        return list.stream().map(rule -> {
            BpmOAWorkOrderAssignRuleRespVO respVO = BeanUtils.toBean(rule, BpmOAWorkOrderAssignRuleRespVO.class);

            // 填充用户名称
            if (userMap.containsKey(rule.getAssigneeUserId())) {
                respVO.setAssigneeUserName(userMap.get(rule.getAssigneeUserId()).getNickname());
            }

            // 填充部门名称
            if (deptMap.containsKey(rule.getDeptId())) {
                respVO.setDeptName(deptMap.get(rule.getDeptId()).getName());
            }

            // 填充工单类型名称
            if (workOrderTypeMap.containsKey(rule.getWorkOrderType())) {
                respVO.setWorkOrderTypeName(workOrderTypeMap.get(rule.getWorkOrderType()).getLabel());
            }
            return respVO;
        }).collect(Collectors.toList());
    }

}
