package com.jy.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.jy.framework.model.constants.CommonConstant;
import com.jy.framework.utils.AssertUtil;
import com.jy.framework.utils.tree.TreeUtil;
import com.jy.system.dao.SysDeptDao;
import com.jy.system.dao.SysUserDao;
import com.jy.system.model.dto.SysDeptDto;
import com.jy.system.model.dto.SysDeptSelectDto;
import com.jy.system.model.entity.SysDept;
import com.jy.system.model.vo.SysDeptVo;
import com.jy.system.service.SysDeptService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * <p>
 * 部门 服务实现类
 * </p>
 *
 * @author
 * @since 2024-06-20
 */
@Service
public class SysDeptServiceImpl implements SysDeptService {

    @Resource
    private SysDeptDao sysDeptDao;

    @Resource
    private SysUserDao sysUserDao;

    @Override
    public List<SysDeptVo> getList(SysDeptSelectDto dto) {
        return sysDeptDao.getList(dto);
    }

    @Override
    public List<SysDeptVo> getTree(SysDeptSelectDto dto) {
        List<SysDeptVo> list = sysDeptDao.getList(dto);
        return TreeUtil.build(list);
    }

    @Override
    public SysDeptVo getDetail(Long id) {
        SysDeptVo vo = sysDeptDao.getDetail(id);
        AssertUtil.notNull(vo, "未知数据");
        return vo;
    }

    @Override
    public void add(SysDeptDto dto) {
        // 验证部门编码是否存在
        boolean codeExists = sysDeptDao.codeExists(dto.getCode());
        AssertUtil.eqFalse(codeExists, "部门编码已存在");

        // 验证同级部门名称是否存在
        boolean peerDeptExists = sysDeptDao.peerDeptExists(dto.getParentId(), dto.getName());
        AssertUtil.eqFalse(peerDeptExists, "同级部门名称已存在");

        // 赋值祖级列表
        setAncestors(dto);

        // 新增部门
        sysDeptDao.save(dto);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(SysDeptDto dto) {
        // 原数据
        SysDept oldSysDept = sysDeptDao.getById(dto.getId());
        AssertUtil.notNull(oldSysDept, "未知数据");

        // 验证同级部门是否存在
        boolean peerDeptExists = sysDeptDao.peerDeptExists(dto.getParentId(), dto.getName(), dto.getId());
        AssertUtil.eqFalse(peerDeptExists, "同级部门名称已存在");

        // 修改上级部门逻辑
        updateParent(oldSysDept, dto);

        // 启用禁用部门逻辑
        updateStatus(oldSysDept, dto);

        // 部门编码无法修改
        dto.setCode(null);

        // 更新部门
        sysDeptDao.updateById(dto);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(Long id) {
        // 验证子部门是否存在
        boolean childrenExists = sysDeptDao.childrenExists(id);
        AssertUtil.eqFalse(childrenExists, "存在子部门，无法删除");

        // 验证是否存在用户
        boolean deptExistsUser = sysUserDao.deptExists(id);
        AssertUtil.eqFalse(deptExistsUser, "存在用户，无法删除");

        // 删除部门
        sysDeptDao.removeById(id);
    }

    /**
     * 修改上级部门逻辑
     *
     * @param oldSysDept 原数据
     * @param newSysDept 新数据
     */
    private void updateParent(SysDept oldSysDept, SysDept newSysDept) {
        // 如果未修改父级部门
        if (ObjectUtil.equal(oldSysDept.getParentId(), newSysDept.getParentId())) {
            newSysDept.setAncestors(oldSysDept.getAncestors());
            return;
        }

        // 赋值祖级列表
        setAncestors(newSysDept);

        // 修改子部门祖籍列表
        String oldChildrenAncestors = oldSysDept.getAncestors() + StringPool.COMMA + oldSysDept.getId();
        String newChildrenAncestors = newSysDept.getAncestors() + StringPool.COMMA + newSysDept.getId();
        sysDeptDao.updateAncestors(oldChildrenAncestors, newChildrenAncestors);
    }

    /**
     * 赋值祖级列表
     *
     * @param sysDept 部门数据
     */
    private void setAncestors(SysDept sysDept) {
        // 如果是顶级部门
        if (ObjectUtil.equal(sysDept.getParentId(), CommonConstant.PARENT_ID)) {
            sysDept.setAncestors(CommonConstant.PARENT_ID_STR);
            return;
        }

        // 获取上级部门
        SysDept parentSysDept = sysDeptDao.getById(sysDept.getParentId());
        AssertUtil.notNull(parentSysDept, "上级部门不存在");
        AssertUtil.equals(parentSysDept.getStatus(), CommonConstant.ENABLE, "上级部门已禁用");

        // 赋值祖级列表
        sysDept.setAncestors(parentSysDept.getAncestors() + StringPool.COMMA + parentSysDept.getId());
    }

    /**
     * 启用禁用部门逻辑
     *
     * @param oldSysDept 原数据
     * @param newSysDept 新数据
     */
    private void updateStatus(SysDept oldSysDept, SysDept newSysDept) {
        // 如果原数据已经是禁用状态或新数据是启用状态，不进行验证
        if (CommonConstant.DISABLE.equals(oldSysDept.getStatus()) || CommonConstant.ENABLE.equals(newSysDept.getStatus())) {
            return;
        }

        // 验证子部门是否禁用
        boolean existsEnable = sysDeptDao.childrenEnableExists(newSysDept.getId());
        AssertUtil.eqFalse(existsEnable, "包含未禁用的子部门");

        // 验证是否存在用户
        boolean existsUser = sysUserDao.deptExists(newSysDept.getId());
        AssertUtil.eqFalse(existsUser, "存在已分配用户，无法禁用");
    }

}
