package cn.iocoder.yudao.module.server.service.workorderLog;

import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.server.controller.admin.workorderType.vo.WorkorderTypeListReqVO;
import cn.iocoder.yudao.module.server.controller.admin.workorderType.vo.WorkorderTypeSaveReqVO;
import cn.iocoder.yudao.module.server.dal.dataobject.workorderInfos.WorkorderInfosDO;
import cn.iocoder.yudao.module.server.dal.dataobject.workorderLog.WorkorderLogDO;
import cn.iocoder.yudao.module.server.dal.dataobject.workorderLog.WorkorderLogVO;
import cn.iocoder.yudao.module.server.dal.dataobject.workorderType.WorkorderTypeDO;
import cn.iocoder.yudao.module.server.dal.mysql.workorderInfos.WorkorderInfosMapper;
import cn.iocoder.yudao.module.server.dal.mysql.workorderLog.WorkorderLogMapper;
import cn.iocoder.yudao.module.server.dal.mysql.workorderType.WorkorderTypeMapper;
import cn.iocoder.yudao.module.server.service.workorderType.WorkorderTypeService;
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptRespVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper;
import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.server.enums.ErrorCodeConstants.*;

/**
 * 工单类型 Service 实现类
 *
 * @author wyj
 */
@Service
@Validated
@Slf4j
public class WorkorderLogServiceImpl implements WorkorderLogService {

    @Resource
    private WorkorderLogMapper workorderLogMapper;

    @Resource
    private WorkorderTypeMapper workorderTypeMapper;

    @Resource
    private WorkorderInfosMapper workorderInfosMapper;

    @Resource
    private AdminUserMapper adminUserMapper;

    @Resource
    private DeptMapper deptMapper;

    @Resource
    private UserRoleMapper userRoleMapper;

    @Override
    public Long createWorkorderLog(WorkorderLogDO workorderLogDO) {
        // 插入
        workorderLogMapper.insert(workorderLogDO);
        // 返回
        return workorderLogDO.getId();
    }

    @Override
    public void updateWorkorderType(WorkorderTypeSaveReqVO updateReqVO) {
        // 校验存在
        validateWorkorderTypeExists(updateReqVO.getId());
        // 校验父栏目id的有效性
        validateParentWorkorderType(updateReqVO.getId(), updateReqVO.getParentId());
        // 校验工单类型名称的唯一性
        validateWorkorderTypeNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName());

        // 更新
        WorkorderTypeDO updateObj = BeanUtils.toBean(updateReqVO, WorkorderTypeDO.class);
        workorderTypeMapper.updateById(updateObj);
    }

    @Override
    public void deleteWorkorderType(Long id) {
        // 校验存在
        validateWorkorderTypeExists(id);
        // 校验是否有子工单类型
        if (workorderTypeMapper.selectCountByParentId(id) > 0) {
            throw exception(WORKORDER_TYPE_EXITS_CHILDREN);
        }
        // 删除
        workorderTypeMapper.deleteById(id);
    }

    private void validateWorkorderTypeExists(Long id) {
        if (workorderTypeMapper.selectById(id) == null) {
            throw exception(WORKORDER_TYPE_NOT_EXISTS);
        }
    }

    private void validateParentWorkorderType(Long id, Long parentId) {
        if (parentId == null || WorkorderTypeDO.PARENT_ID_ROOT.equals(parentId)) {
            return;
        }
        // 1. 不能设置自己为父工单类型
        if (Objects.equals(id, parentId)) {
            throw exception(WORKORDER_TYPE_PARENT_ERROR);
        }
        // 2. 父工单类型不存在
        WorkorderTypeDO parentWorkorderType = workorderTypeMapper.selectById(parentId);
        if (parentWorkorderType == null) {
            throw exception(WORKORDER_TYPE_PARENT_NOT_EXITS);
        }
        // 3. 递归校验父工单类型，如果父工单类型是自己的子工单类型，则报错，避免形成环路
        if (id == null) { // id 为空，说明新增，不需要考虑环路
            return;
        }
        for (int i = 0; i < Short.MAX_VALUE; i++) {
            // 3.1 校验环路
            parentId = parentWorkorderType.getParentId();
            if (Objects.equals(id, parentId)) {
                throw exception(WORKORDER_TYPE_PARENT_IS_CHILD);
            }
            // 3.2 继续递归下一级父工单类型
            if (parentId == null || WorkorderTypeDO.PARENT_ID_ROOT.equals(parentId)) {
                break;
            }
            parentWorkorderType = workorderTypeMapper.selectById(parentId);
            if (parentWorkorderType == null) {
                break;
            }
        }
    }

    private void validateWorkorderTypeNameUnique(Long id, Long parentId, String name) {
        WorkorderTypeDO workorderType = workorderTypeMapper.selectByParentIdAndName(parentId, name);
        if (workorderType == null) {
            return;
        }
        // 如果 id 为空，说明不用比较是否为相同 id 的工单类型
        if (id == null) {
            throw exception(WORKORDER_TYPE_NAME_DUPLICATE);
        }
        if (!Objects.equals(workorderType.getId(), id)) {
            throw exception(WORKORDER_TYPE_NAME_DUPLICATE);
        }
    }

    @Override
    public WorkorderTypeDO getWorkorderType(Long id) {
        return workorderTypeMapper.selectById(id);
    }

    @Override
    public List<WorkorderLogVO> getWorkorderLogList(Long workorderId) {
        LambdaQueryWrapper<WorkorderLogDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(WorkorderLogDO::getWorkorderId,workorderId);
        List<WorkorderLogDO> list = workorderLogMapper.selectList(wrapper);
        ArrayList<WorkorderLogVO> resultList = new ArrayList<>();
        for (WorkorderLogDO workorderLogDO : list) {
            WorkorderLogVO workorderLogVO = BeanUtils.toBean(workorderLogDO, WorkorderLogVO.class);
            //查询用户名称
            AdminUserDO adminUserDO = adminUserMapper.selectByIdWithoutPermission(Long.valueOf(workorderLogDO.getCreator()));
            //查询部门名称
//            DeptDO deptDO = deptMapper.selectById(adminUserDO.getDeptId());
            DeptDO deptDO = deptMapper.selectByIdWithoutPermission(adminUserDO.getDeptId());
            workorderLogVO.setCreator(adminUserDO.getNickname());
            workorderLogVO.setDeptName(deptDO.getName());
            workorderLogVO.setPhone(deptDO.getPhone());
            //获取负责人名称
            if(deptDO.getLeaderUserId() !=null) {
                AdminUserDO adminUser = adminUserMapper.selectByIdWithoutPermission(deptDO.getLeaderUserId());
                workorderLogVO.setName(adminUser.getNickname());
            }
            resultList.add(workorderLogVO);
        }
        //获取最后一条审批记录的工单信息
        WorkorderLogDO workorderLogDO = list.get(list.size() - 1);
        WorkorderInfosDO workorderInfosDO = workorderInfosMapper.selectById(workorderLogDO.getWorkorderId());
        //获取下一级的审批人信息
        if(workorderInfosDO.getStatus().equals("70") || workorderInfosDO.getStatus().equals("0")) {
            return resultList;
        }
        WorkorderLogVO infosDO =nextRecord(workorderInfosDO);
        resultList.add(infosDO);
        return resultList;
    }

    @Override
    public List<DeptRespVO> getRejectList(Long workorderId) {
        // 获取当前用户对象
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        List<DeptRespVO> deptList = new ArrayList<>();
        //查询当前用户对于该工单最早日志记录
        LambdaQueryWrapper<WorkorderLogDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(WorkorderLogDO::getCreator,loginUser.getId())
                .eq(WorkorderLogDO::getWorkorderId,workorderId)
                .orderByAsc(WorkorderLogDO::getCreateTime);
        List<WorkorderLogDO> workorderLogDOS = workorderLogMapper.selectList(wrapper);
        if (workorderLogDOS.size() == 0){
            //查询所有的日志
            LambdaQueryWrapper<WorkorderLogDO> wrapper1 = new LambdaQueryWrapper<>();
            wrapper1.eq(WorkorderLogDO::getWorkorderId,workorderId);
            workorderLogDOS = workorderLogMapper.selectList(wrapper1);
        }
        //查询在这之前的信息
        LambdaQueryWrapper<WorkorderLogDO> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.eq(WorkorderLogDO::getWorkorderId,workorderId)
                .lt(WorkorderLogDO::getCreateTime, workorderLogDOS.get(0).getCreateTime());
        List<WorkorderLogDO> list = workorderLogMapper.selectList(wrapper2);
        if(list.size() == 0) {
            list = workorderLogDOS;
        }
        for (WorkorderLogDO workorderLogDO : list) {
            //查询创建人信息
            AdminUserDO adminUserDO = adminUserMapper.selectByIdWithoutPermission(Long.valueOf(workorderLogDO.getCreator()));
//            DeptDO deptDO = deptMapper.selectById(adminUserDO.getDeptId());
            DeptDO deptDO = deptMapper.selectByIdWithoutPermission(adminUserDO.getDeptId());
            deptList.add(BeanUtils.toBean(deptDO,DeptRespVO.class));
        }
        deptList = deptList.stream()
                .filter(distinctByKey(DeptRespVO::getId))  // 按 id 去重
                .collect(Collectors.toList());
        //如果当前用户的部门存在与集合中，需要去除
        deptList.removeIf(dept ->
                dept.getId().toString().equals(loginUser.getInfo().get("deptId"))
        );
        return deptList;
    }

    public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Set<Object> seen = ConcurrentHashMap.newKeySet();
        return t -> seen.add(keyExtractor.apply(t));
    }

    private WorkorderLogVO nextRecord(WorkorderInfosDO workorderInfosDO) {
        // 获取当前用户对象
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        LambdaQueryWrapper<UserRoleDO> userRoleWrapper = new LambdaQueryWrapper<>();
        WorkorderLogVO workorderLogVO = new WorkorderLogVO();
        AdminUserDO adminUserDO = null;
        DeptDO deptDO = null;
        UserRoleDO userRoleDO = new UserRoleDO();
        //获取下一级的审批人信息
        switch (workorderInfosDO.getStatus()){
            case "21":
                //用户确认
//                userRoleWrapper.eq(UserRoleDO::getRoleId,161)
//                        .eq(UserRoleDO::getUserId,loginUser.getId());
//                userRoleDO = userRoleMapper.selectOne(userRoleWrapper);
                break;
            case "31":
                //三处核实
                userRoleWrapper.eq(UserRoleDO::getRoleId,163);
                userRoleDO = userRoleMapper.selectOne(userRoleWrapper);
                break;
            case "41":
                //公开处审核
                userRoleWrapper.eq(UserRoleDO::getRoleId,164);
                userRoleDO = userRoleMapper.selectOne(userRoleWrapper);
                break;
            case "51":
                //运营商确认
                break;
            case "60":
                //运营商处理工单
                break;
            default:
                log.info("未查询到下级审批人");
                return workorderLogVO;
        }
        if(workorderInfosDO.getStatus().equals("60") || workorderInfosDO.getStatus().equals("51")) {
            //判断流程类型
            WorkorderTypeDO workorderTypeDO = workorderTypeMapper.selectById(workorderInfosDO.getCategoryId());
            //如果工单表中的打回原因为空则，退回到了协助的运维商，否则退回到了工单发起的运维商
            if(StrUtil.isEmpty(workorderInfosDO.getRejectReason())) {
                LambdaQueryWrapper<AdminUserDO> wrapper = new LambdaQueryWrapper<>();
//                deptDO = deptMapper.selectById(workorderInfosDO.getTechOperatorId());
                deptDO = deptMapper.selectByIdWithoutPermission(workorderInfosDO.getTechOperatorId());
                wrapper.eq(AdminUserDO::getDeptId, workorderInfosDO.getTechOperatorId());
//            adminUserDO = adminUserMapper.selectOne(wrapper);
                workorderLogVO.setStatus(workorderInfosDO.getStatus());
                workorderLogVO.setDeptName(deptDO.getName());
                workorderLogVO.setPhone(deptDO.getPhone());
                //获取负责人名称
                if(deptDO.getLeaderUserId() !=null) {
                    AdminUserDO adminUser = adminUserMapper.selectByIdWithoutPermission(deptDO.getLeaderUserId());
                    workorderLogVO.setName(adminUser.getNickname());
                }
//            workorderLogVO.setCreator(adminUserDO.getNickname());
            }else {
                //退回到了工单发起的运维商
                //查询工单创建人
                adminUserDO = adminUserMapper.selectByIdWithoutPermission(Long.valueOf(workorderInfosDO.getCreator()));
//                deptDO = deptMapper.selectById(adminUserDO.getDeptId());
                deptDO = deptMapper.selectByIdWithoutPermission(adminUserDO.getDeptId());
                workorderLogVO.setStatus(workorderInfosDO.getStatus());
                workorderLogVO.setDeptName(deptDO.getName());
                workorderLogVO.setPhone(deptDO.getPhone());
                //获取负责人名称
                if(deptDO.getLeaderUserId() !=null) {
                    AdminUserDO adminUser = adminUserMapper.selectByIdWithoutPermission(deptDO.getLeaderUserId());
                    workorderLogVO.setName(adminUser.getNickname());
                }
            }

        }
        else if(workorderInfosDO.getStatus().equals("21")) {
            adminUserDO = adminUserMapper.selectByIdWithoutPermission(loginUser.getId());
//            deptDO = deptMapper.selectById(workorderInfosDO.getUserId());
            deptDO = deptMapper.selectByIdWithoutPermission(workorderInfosDO.getUserId());
            workorderLogVO.setStatus(workorderInfosDO.getStatus());
            workorderLogVO.setDeptName(deptDO.getName());
            workorderLogVO.setPhone(deptDO.getPhone());
            workorderLogVO.setCreator(adminUserDO.getNickname());
            //获取负责人名称
            if(deptDO.getLeaderUserId() !=null) {
                AdminUserDO adminUser = adminUserMapper.selectByIdWithoutPermission(deptDO.getLeaderUserId());
                workorderLogVO.setName(adminUser.getNickname());
            }
        }else {
            adminUserDO = adminUserMapper.selectByIdWithoutPermission(userRoleDO.getUserId());
//            deptDO = deptMapper.selectById(adminUserDO.getDeptId());
            deptDO = deptMapper.selectByIdWithoutPermission(adminUserDO.getDeptId());
            workorderLogVO.setStatus(workorderInfosDO.getStatus());
            workorderLogVO.setDeptName(deptDO.getName());
            workorderLogVO.setPhone(deptDO.getPhone());
            workorderLogVO.setCreator(adminUserDO.getNickname());
            //获取负责人名称
            if(deptDO.getLeaderUserId() !=null) {
                AdminUserDO adminUser = adminUserMapper.selectByIdWithoutPermission(deptDO.getLeaderUserId());
                workorderLogVO.setName(adminUser.getNickname());
            }
        }
        return workorderLogVO;
    }

}