package cn.iocoder.yudao.module.pms.service.iotprojectinfo;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.pms.controller.admin.iotprojectinfo.vo.IotProjectInfoPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotprojectinfo.vo.IotProjectInfoSaveReqVO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojectinfo.IotProjectInfoDO;
import cn.iocoder.yudao.module.pms.dal.mysql.iotprojectinfo.IotProjectInfoMapper;
import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO;
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.user.AdminUserMapper;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.module.system.service.dict.DictDataService;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_PROJECT_INFO_NOT_EXISTS;

/**
 * 项目信息 Service 实现类
 *
 * @author 超级管理员
 */
@Service
@Validated
public class IotProjectInfoServiceImpl implements IotProjectInfoService {

    @Resource
    private IotProjectInfoMapper iotProjectInfoMapper;
    @Resource
    private DeptMapper deptMapper;
    @Resource
    private AdminUserMapper userMapper;
    @Resource
    private DictDataService dictDataService;
    @Resource
    private DeptService deptService;

    @Override
    public Long createIotProjectInfo(IotProjectInfoSaveReqVO createReqVO) {
        // 插入
        IotProjectInfoDO iotProjectInfo = BeanUtils.toBean(createReqVO, IotProjectInfoDO.class);
        // 校验 项目信息中的 施工区域 如果施工区域值在 数据字典 dictType 中不存在 则新增到数据字典
        saveDictData(createReqVO.getDictType(), createReqVO.getLocation());
        iotProjectInfoMapper.insert(iotProjectInfo);
        // 返回
        return iotProjectInfo.getId();
    }

    @Override
    public void updateIotProjectInfo(IotProjectInfoSaveReqVO updateReqVO) {
        // 校验存在
        validateIotProjectInfoExists(updateReqVO.getId());
        // 校验 项目信息中的 施工区域 如果施工区域值在 数据字典 dictType 中不存在 则新增到数据字典
        saveDictData(updateReqVO.getDictType(), updateReqVO.getLocation());
        // 更新
        IotProjectInfoDO updateObj = BeanUtils.toBean(updateReqVO, IotProjectInfoDO.class);
        iotProjectInfoMapper.updateById(updateObj);
    }

    /**
     * 校验 项目信息中的 施工区域 如果施工区域值在 数据字典 dictType 中不存在 则新增到数据字典
     * @param dictType  label
     */
    public void saveDictData(String dictType, String label) {
        if (StrUtil.isNotBlank(dictType)) {
            AtomicBoolean existFlag = new AtomicBoolean(false);
            List<DictDataDO> dictDatas = dictDataService.getDictDataListByDictType(dictType);
            if (CollUtil.isNotEmpty(dictDatas)) {
                Set<Integer> dataValues = new HashSet<>();
                // 数据字典数据的排序字段
                Set<Integer> dataSorts = new HashSet<>();
                dictDatas.forEach(data -> {
                    if (data.getValue().matches("-?\\d+")) {
                        dataValues.add(Integer.valueOf(data.getValue()));
                    }
                    if (ObjUtil.isNotEmpty(data.getSort())) {
                        dataSorts.add(data.getSort());
                    }
                    if (StrUtil.isNotBlank(label) && label.equals(data.getLabel())) {
                        // 现在数据字典集合中已经包含了当前项目的 施工区域
                        existFlag.set(true);
                    }
                });
                if (!existFlag.get()) {
                    DictDataSaveReqVO reqVO = new DictDataSaveReqVO();
                    // 找出集合中最大的整数
                    if (CollUtil.isNotEmpty(dataValues)) {
                        Optional<Integer> maxValue = dataValues.stream()
                                .max(Comparator.naturalOrder());
                        reqVO.setValue(String.valueOf(maxValue.get()+1));
                    }
                    // 设置 数据字典值 的排序值
                    if (CollUtil.isNotEmpty(dataSorts)) {
                        Optional<Integer> maxSort = dataSorts.stream()
                                .max(Comparator.naturalOrder());
                        reqVO.setSort(maxSort.get()+1);
                    }
                    // 现在数据字典集合中未包含了当前项目的 施工区域 新增到数据字典
                    reqVO.setDictType(dictType);
                    reqVO.setLabel(label);
                    dictDataService.createDictData(reqVO);
                }
            }
        }
    }

    @Override
    public void deleteIotProjectInfo(Long id) {
        // 校验存在
        validateIotProjectInfoExists(id);
        // 删除
        iotProjectInfoMapper.deleteById(id);
    }

    private void validateIotProjectInfoExists(Long id) {
        if (iotProjectInfoMapper.selectById(id) == null) {
            throw exception(IOT_PROJECT_INFO_NOT_EXISTS);
        }
    }

    @Override
    public IotProjectInfoDO getIotProjectInfo(Long id) {
        return iotProjectInfoMapper.selectById(id);
    }

    @Override
    public PageResult<IotProjectInfoDO> getIotProjectInfoPage(IotProjectInfoPageReqVO pageReqVO) {
        return iotProjectInfoMapper.selectPage(pageReqVO);
    }

    @Override
    public List<IotProjectInfoDO> getIotProjectInfos(IotProjectInfoPageReqVO pageReqVO) {
        return iotProjectInfoMapper.selectList(pageReqVO);
    }

    @Override
    public PageResult<IotProjectInfoDO> getIotProjectInfoPage1(IotProjectInfoPageReqVO pageReqVO, Collection<Long> deptIds) {
        // 查询当前人所属公司级组织的数据
        List<DeptDO> depts = companyLevelDepts();
        Set<Long> departmentIds = new HashSet<>();
        if (CollUtil.isNotEmpty(depts)) {
            depts.forEach(dept -> {
                departmentIds.add(dept.getId());
            });
        }
        // 查询当前登录人所属的项目部 根据项目部查询 对应的 合同信息 暂时只对瑞恒
        Set<Long> rhProjectDeptIds = projectLevelDepts();
        pageReqVO.setProjectDeptIds(rhProjectDeptIds);
        return iotProjectInfoMapper.selectPage1(pageReqVO, departmentIds);
    }

    @Override
    public List<IotProjectInfoDO> projectList() {
        // 查询当前用户所属部门的公司级组织
        List<DeptDO> companyLevelDepts = companyLevelDepts();
        Set<Long> deptIds = new HashSet<>();
        if (CollUtil.isNotEmpty(companyLevelDepts)) {
            companyLevelDepts.forEach(dept -> {
                deptIds.add(dept.getId());
            });
        }
        List<IotProjectInfoDO> allProjects = iotProjectInfoMapper.projectList();
        List<IotProjectInfoDO> resultProjects = new ArrayList<>();
        if (CollUtil.isNotEmpty(allProjects)) {
            allProjects.forEach(project -> {
                if (deptIds.contains(project.getDeptId())) {
                    resultProjects.add(project);
                }
            });
        }
        return resultProjects;
    }

    /**
     * 查询当前登录人所属部门的公司级组织
     * @return
     */
    public List<DeptDO> companyLevelDepts() {
        Set<Long> parentIds = new HashSet<>();
        parentIds.add(DeptDO.PARENT_ID_ROOT);

        // 查询当前登录人所属部门
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        AdminUserDO user = userMapper.selectById(userId);
        Long deptId = user.getDeptId();
        DeptDO dept = deptMapper.selectById(deptId);
        System.out.println("当前登录用户所属部门：" + dept.getName());

        // 用于存储最终需要返回的部门列表
        List<DeptDO> resultDepts = new ArrayList<>();

        DataPermissionUtils.executeIgnore(() -> {
            // 一级部门
            List<DeptDO> theFirstLevelDepts = deptMapper.selectListByParentId(parentIds);
            System.out.println("顶级部门数量：" + theFirstLevelDepts.size());
            if (CollUtil.isNotEmpty(theFirstLevelDepts)) {
                theFirstLevelDepts.forEach(department -> {
                    if (dept.getId().equals(department.getId())) {
                        // 当前登录人所属部门是 一级部门
                        // 此时需要返回一级部门的二级公司子部门
                        parentIds.clear();
                        parentIds.add(department.getId());
                        List<DeptDO> theSecondLevelDepts = deptMapper.selectListByParentId(parentIds);
                        System.out.println("二级部门数量：" + theSecondLevelDepts.size());
                        resultDepts.addAll(theSecondLevelDepts);
                    }
                    // 当前登录人所属部门是二级部门或二级部门的子部门
                    if (!dept.getId().equals(department.getId())) {
                        // 查询当前登录人所属部门的父部门 追溯到二级部门
                        // 递归查询当前登录人所属部门的父部门 直到找到 二级部门(parentId=department.getId())
                        // 如果 parentDept.getParentId().equals(department.getId()) 说明parentDept部门已经是二级部门了
                        DeptDO currentDept = dept;
                        if (currentDept.getParentId().equals(department.getId())) {
                            // 当前部门是二级部门(父部门是一级部门)
                            if (!resultDepts.contains(dept)) {
                                resultDepts.add(dept);
                            }
                        }
                        while (currentDept != null && !currentDept.getParentId().equals(DeptDO.PARENT_ID_ROOT)) {
                            DeptDO tempParentDept = deptMapper.selectById(currentDept.getParentId());
                            if (tempParentDept == null) {
                                break;
                            }
                            if (currentDept.getParentId().equals(department.getId())) {
                                // 当前部门是二级部门(父部门是一级部门)
                                if (!resultDepts.contains(dept)) {
                                    resultDepts.add(currentDept);
                                }
                                break;
                            }
                            currentDept = tempParentDept;
                        }
                    }
                });
            }

        });
        return resultDepts;
    }

    @Override
    public Set<Long> customLevelDepts() {
        // 找到当前登录人所属部门及子部门列表
        // 查询当前登录人所属部门
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        AdminUserDO user = userMapper.selectById(userId);
        Long deptId = user.getDeptId();
        DeptDO dept = deptMapper.selectById(deptId);

        // 找到当前登录人所属部门及子部门
        Set<Long> allChildDeptIds = deptService.getChildDeptIdListFromCache(deptId);
        allChildDeptIds.add(deptId);

        // 查询当前登录人所属的公司级别的部门
        DataPermissionUtils.executeIgnore(() -> {
            // 查询各专业公司下的所有 部门id集合
            // 如果集合包含 当前登录人的 deptId 则确定当前登录人所属的专业公司
            Set<Long> rhChildDeptIds = deptService.getChildDeptIdListFromCache(157l);
            rhChildDeptIds.add(157l);
            Set<Long> ryChildDeptIds = deptService.getChildDeptIdListFromCache(158l);
            ryChildDeptIds.add(158l);
            Set<Long> rdChildDeptIds = deptService.getChildDeptIdListFromCache(163l);
            rdChildDeptIds.add(163l);
            Set<Long> fiveChildDeptIds = deptService.getChildDeptIdListFromCache(388l);
            fiveChildDeptIds.add(388l);
            if (rhChildDeptIds.contains(deptId)) {
                // 当前登录所属公司为 瑞恒
                allChildDeptIds.add(157l);
            }
            if (ryChildDeptIds.contains(deptId)) {
                // 当前登录所属公司为 瑞鹰
                allChildDeptIds.add(158l);
            }
            if (rdChildDeptIds.contains(deptId)) {
                // 当前登录所属公司为 瑞都
                allChildDeptIds.add(163l);
            }
            if (fiveChildDeptIds.contains(deptId)) {
                // 当前登录所属公司为 5#公司
                allChildDeptIds.add(388l);
            }
        });

        return allChildDeptIds;
    }

    @Override
    public Set<Long> projectLevelDepts() {
        Set<Long> projectDeptIds = new HashSet<>();
        // 查询当前登录人信息
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        AdminUserDO user = userMapper.selectById(userId);
        Long deptId = user.getDeptId();
        DeptDO dept = deptMapper.selectById(deptId);
        // 查询瑞恒下所有部门 只有当前登录人所属部门属于瑞恒 才使用 数据权限过滤
        Set<Long> allRhChildDeptIds = deptService.getChildDeptIdListFromCache(157l);
        allRhChildDeptIds.add(157l);
        // 只有瑞恒才需要此数据权限校验
        if (ObjUtil.isNotEmpty(dept) && allRhChildDeptIds.contains(deptId)) {
            if ("2".equals(dept.getType())) {
                // 当前登录人所属部门是 项目部
                projectDeptIds.add(dept.getId());
            } else if ("3".equals(dept.getType())) {
                // 查询上级部门可能存在数据权限
                DataPermissionUtils.executeIgnore(() -> {
                    // 当前登录人所属部门是 施工队伍 查询上级部门
                    DeptDO parentDept = deptMapper.selectById(dept.getParentId());
                    if (ObjUtil.isNotEmpty(parentDept) && "2".equals(parentDept.getType())) {
                        projectDeptIds.add(parentDept.getId());
                    }
                });
            } else if ("1".equals(dept.getType())) {
                // 当前登录人所属部门是 专业公司 查询公司下所有 项目部类型的部门
                List<DeptDO> allRhDepts =deptService.getDeptList(allRhChildDeptIds);
                if (CollUtil.isNotEmpty(allRhDepts)) {
                    allRhDepts.forEach(tempDept -> {
                        if ("2".equals(tempDept.getType())) {
                            projectDeptIds.add(tempDept.getId());
                        }
                    });
                }
            } else {
                // 部门没有类型 则查询 下级部门是否存在 项目部类型 的部门 新疆分公司
                Set<Long> allChildDeptIds = deptService.getChildDeptIdListFromCache(dept.getId());
                if (CollUtil.isNotEmpty(allChildDeptIds)) {
                    List<DeptDO> allRhDepts = deptService.getDeptList(allChildDeptIds);
                    if (CollUtil.isNotEmpty(allRhDepts)) {
                        allRhDepts.forEach(tempDept -> {
                            if ("2".equals(tempDept.getType())) {
                                projectDeptIds.add(tempDept.getId());
                            }
                        });
                    }
                }
            }
        }
        return projectDeptIds;
    }

}