package com.cf.imes.module.system.service.dept;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cf.imes.framework.common.enums.CommonStatusEnum;
import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
import com.cf.imes.framework.security.core.LoginUser;
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
import com.cf.imes.framework.security.test.WithMockLoginUser;
import com.cf.imes.framework.test.core.ut.BaseMockitoUnitTest;
import com.cf.imes.module.system.common.WithMockLoginUserExtension;
import com.cf.imes.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
import com.cf.imes.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.dept.DeptDO;
import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO;
import com.cf.imes.module.system.dal.mysql.dept.DeptMapper;
import com.cf.imes.module.system.enums.ErrorCodeConstants;
import com.cf.imes.module.system.service.user.AdminUserService;
import com.cf.imes.module.system.util.redis.SystemRedisUtils;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import static com.cf.imes.framework.test.core.util.AssertUtils.assertPojoEquals;
import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceException;
import static com.cf.imes.framework.test.core.util.RandomUtils.*;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyCollection;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

/**
 * {@link DeptServiceImpl} 的单元测试类
 *
 * @author niudehua
 */
@ExtendWith(WithMockLoginUserExtension.class)
class DeptServiceImplTest extends BaseMockitoUnitTest {

    @InjectMocks
    private DeptServiceImpl deptService;

    @Mock
    private DeptMapper deptMapper;

    @Mock
    private AdminUserService userService;

    @Mock
    private SystemRedisUtils systemRedisUtils;

    @Test
    void testCreateDept() {
        // 准备参数
        DeptSaveReqVO reqVO = randomPojo(DeptSaveReqVO.class, o -> {
            o.setId(null); // 防止 id 被设置
            o.setParentId(DeptDO.PARENT_ID_ROOT);
            o.setStatus(randomCommonStatus());
        });

        // 模拟 Mapper 插入时生成 ID
        doAnswer(invocation -> {
            DeptDO deptDO = invocation.getArgument(0);
            deptDO.setId(100L); // 模拟自增主键
            return null;
        }).when(deptMapper).insert(any(DeptDO.class));
        // 调用
        Long deptId = deptService.createDept(reqVO);
        // 断言
        assertEquals(100L, deptId);
        verify(deptMapper).insert(argThat((DeptDO dept) ->
                dept.getParentId().equals(reqVO.getParentId())
                        && dept.getStatus().equals(reqVO.getStatus())
                        && dept.getOrganId().equals(reqVO.getOrganId())
                        && dept.getName().equals(reqVO.getName())
                        && dept.getPhone().equals(reqVO.getPhone())
        ));
    }

    @Test
    @WithMockLoginUser
    void testUpdateDept_enable() {
        Long deptId = 100L;
        // exist
        when(deptMapper.selectById(deptId)).thenReturn(new DeptDO());

        // 准备参数
        DeptSaveReqVO reqVO = randomPojo(DeptSaveReqVO.class, o -> {
            o.setId(deptId);
            o.setParentId(DeptDO.PARENT_ID_ROOT);
            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
        });

        // 调用
        deptService.updateDept(reqVO);
        // 校验是否更新
        verify(deptMapper, times(1)).updateById(any(DeptDO.class));
    }

    @Test
    @WithMockLoginUser
    void testUpdateDept_disable() {
        Long deptId = 100L;
        // exist
        when(deptMapper.selectById(deptId)).thenReturn(new DeptDO());
        // 准备参数
        DeptSaveReqVO reqVO = randomPojo(DeptSaveReqVO.class, o -> {
            o.setId(deptId);
            o.setParentId(DeptDO.PARENT_ID_ROOT);
            o.setStatus(CommonStatusEnum.DISABLE.getStatus());
        });

        // 调用
        deptService.updateDept(reqVO);
        // 校验是否更新
        verify(deptMapper, times(1)).updateById(any(DeptDO.class));
        verify(systemRedisUtils, times(1)).scanAndCompareDeptAndDelToken(deptId);
    }

    @Test
    @WithMockLoginUser
    void testUpdateDept_parentDeptUserOperNotAllow() {
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        // mock 数据
        DeptDO parentDeptDO = randomPojo(DeptDO.class, o -> o.setId(randomLongId()));
        DeptDO dbDeptDO = randomPojo(DeptDO.class, o -> {
            o.setId(loginUser.getDeptId());
            o.setParentId(parentDeptDO.getId());
        });

        // exist
        when(deptMapper.selectById(parentDeptDO.getId())).thenReturn(parentDeptDO);
        // 轮训子部门
        when(deptMapper.selectListByParentId(anyCollection())).thenReturn(List.of(dbDeptDO)).thenReturn(Collections.emptyList());

        // 准备参数
        DeptSaveReqVO reqVO = randomPojo(DeptSaveReqVO.class, o -> {
            o.setParentId(DeptDO.PARENT_ID_ROOT);
            o.setId(parentDeptDO.getId());
        });

        assertServiceException(() -> deptService.updateDept(reqVO),
                PARENT_DEPT_USER_OPER_NOT_ALLOW);
    }

    @Test
    @WithMockLoginUser
    void testDeleteDept_success() {
        Long deptId = 100L;
        // exist
        when(deptMapper.selectById(deptId)).thenReturn(new DeptDO());

        // 调用
        deptService.deleteDept(deptId);
        // 校验数据不存在了
        verify(deptMapper, times(1)).deleteById(deptId);
        verify(userService, times(1)).deleteDeptUsers(deptId);
        verify(systemRedisUtils, times(1)).scanAndCompareDeptAndDelToken(deptId);
    }

    @Test
    @WithMockLoginUser
    void testDeleteDept_deptUserOperNotAllow() {
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        // mock 数据
        DeptDO dbDeptDO = randomPojo(DeptDO.class, o -> o.setId(loginUser.getDeptId()));
        Long id = dbDeptDO.getId();
        when(deptMapper.selectById(id)).thenReturn(dbDeptDO);

        assertServiceException(() -> deptService.deleteDept(id),
                DEPT_USER_OPER_NOT_ALLOW);
    }

    @Test
    @WithMockLoginUser
    void testDeleteDept_deptUserExists(){
        // mock 数据
        DeptDO dbDeptDO = randomPojo(DeptDO.class);
        Long id = dbDeptDO.getId();
        when(deptMapper.selectById(id)).thenReturn(dbDeptDO);

        when(userService.getUserListByDeptIds(anyList()))
                .thenReturn(Collections.singletonList(new AdminUserDO()));

        assertServiceException(() -> deptService.deleteDept(id),
                DEPT_EXISTS_USER);
    }

    @Test
    void testDeleteDept_exitsChildren() {
        // mock 数据
        DeptDO parentDept = randomPojo(DeptDO.class);
        Long id = parentDept.getId();
        when(deptMapper.selectById(id)).thenReturn(parentDept);

        // 插入子部门
        when(deptMapper.selectCountByParentId(id)).thenReturn(1L);

        // 调用, 并断言异常
        assertServiceException(() -> deptService.deleteDept(parentDept.getId()), DEPT_EXITS_CHILDREN);
    }

    @Test
    void testValidateDeptExists_idIsNull() {
        // 调用，不抛异常
        assertDoesNotThrow(() -> deptService.validateDeptExists(null));
    }

    @Test
    void testValidateDeptExists_exists() {
        // mock 数据
        DeptDO deptDO = randomPojo(DeptDO.class);
        when(deptMapper.selectById(deptDO.getId())).thenReturn(deptDO);

        // 调用，不抛异常
        deptService.validateDeptExists(deptDO.getId());
    }

    @Test
    void testValidateDeptExists_notFound() {
        // 准备参数
        Long id = randomLongId();

        // 调用, 并断言异常
        assertServiceException(() -> deptService.validateDeptExists(id), DEPT_NOT_FOUND);
    }

    @Test
    void testValidateParentDept_parentError() {
        // 准备参数
        Long id = randomLongId();

        // 调用, 并断言异常
        assertServiceException(() -> deptService.validateParentDept(id, id),
                DEPT_PARENT_ERROR);

        assertDoesNotThrow(() -> deptService.validateParentDept(id, null));
    }

    @Test
    void testValidateParentDept_parentNotExists() {
        Long id = randomLongId();
        Long parentId = randomLongId(); // 假设不存在的 ID
        assertServiceException(() -> deptService.validateParentDept(id, parentId),
                DEPT_PARENT_NOT_EXITS);
    }

    @Test
    void testValidateParentDept_parentDisabled() {
        DeptDO parentDept = randomPojo(DeptDO.class);
        parentDept.setStatus(CommonStatusEnum.DISABLE.getStatus());
        when(deptMapper.selectById(parentDept.getId())).thenReturn(parentDept);

        Long id = randomLongId();
        Long parentId = parentDept.getId();

        assertServiceException(() -> deptService.validateParentDept(id, parentId),
                PARENT_DEPT_DISABLE, parentDept.getName());
    }

    @Test
    void testValidateParentDept_multiLevelParentDisabled() {
        // 构造三级部门：grandParent -> parent -> child
        DeptDO grandParent = randomPojo(DeptDO.class);
        grandParent.setStatus(CommonStatusEnum.DISABLE.getStatus());
        when(deptMapper.selectById(grandParent.getId())).thenReturn(grandParent);

        DeptDO parent = randomPojo(DeptDO.class, o -> o.setParentId(grandParent.getId()));
        parent.setStatus(CommonStatusEnum.ENABLE.getStatus());
        when(deptMapper.selectById(parent.getId())).thenReturn(parent);

        Long id = randomLongId();
        Long parentId = parent.getId();

        assertServiceException(() -> deptService.validateParentDept(id, parentId),
                PARENT_DEPT_DISABLE, grandParent.getName());
    }

    @Test
    void testValidateParentDept_validHierarchy() {
        DeptDO grandParent = randomPojo(DeptDO.class);
        grandParent.setStatus(CommonStatusEnum.ENABLE.getStatus());
        when(deptMapper.selectById(grandParent.getId())).thenReturn(grandParent);

        DeptDO parent = randomPojo(DeptDO.class, o -> o.setParentId(grandParent.getId()));
        parent.setStatus(CommonStatusEnum.ENABLE.getStatus());
        when(deptMapper.selectById(parent.getId())).thenReturn(parent);

        Long id = randomLongId();
        Long parentId = parent.getId();

        // 不抛异常
        deptService.validateParentDept(id, parentId);
    }

    @Test
    void testValidateParentDept_parentIsChild() {
        // mock 数据（父节点）
        DeptDO parentDept = randomPojo(DeptDO.class);
        parentDept.setStatus(CommonStatusEnum.ENABLE.getStatus());

        // mock 数据（子节点）
        DeptDO childDept = randomPojo(DeptDO.class, o -> {
            o.setParentId(parentDept.getId());
        });
        childDept.setStatus(CommonStatusEnum.ENABLE.getStatus());
        when(deptMapper.selectById(anyLong())).thenReturn(parentDept).thenReturn(childDept).thenReturn(null);

        // 准备参数
        Long id = parentDept.getId();
        Long parentId = childDept.getId();

        // 调用, 并断言异常
        assertServiceException(() -> deptService.validateParentDept(id, parentId), DEPT_PARENT_IS_CHILD);
    }

    @Test
    void testValidateNameUnique_duplicate() {
        // mock 数据
        DeptDO deptDO = randomPojo(DeptDO.class);
        when(deptMapper.selectByParentIdAndName(anyLong(), anyString(), anyLong())).thenReturn(deptDO);

        // 准备参数
        Long id = randomLongId();
        Long parentId = deptDO.getParentId();
        String name = deptDO.getName();
        Long organId = deptDO.getOrganId();

        // 调用, 并断言异常
        assertServiceException(() -> deptService.validateDeptNameUnique(id, parentId, name, organId),
                DEPT_NAME_DUPLICATE);
    }

    @Test
    void testValidateDeptNameUnique_newDeptDuplicate() {
        // mock 数据
        DeptDO deptDO = randomPojo(DeptDO.class);
        when(deptMapper.selectByParentIdAndName(anyLong(), anyString(), anyLong())).thenReturn(deptDO);

        // 准备参数：id = null，模拟新增
        Long id = null;
        Long parentId = deptDO.getParentId();
        String name = deptDO.getName();
        Long organId = deptDO.getOrganId();

        // 调用，并断言异常
        assertServiceException(() -> deptService.validateDeptNameUnique(id, parentId, name, organId),
                DEPT_NAME_DUPLICATE);
    }

    @Test
    void testValidateDeptNameUnique_updateSameDept() {
        // mock 数据
        DeptDO deptDO = randomPojo(DeptDO.class);
        when(deptMapper.selectByParentIdAndName(anyLong(), anyString(), anyLong())).thenReturn(deptDO);

        // 准备参数：id 相同，表示更新自己
        Long id = deptDO.getId();
        Long parentId = deptDO.getParentId();
        String name = deptDO.getName();
        Long organId = deptDO.getOrganId();

        // 调用，不抛异常
        deptService.validateDeptNameUnique(id, parentId, name, organId);
    }


    @Test
    void testGetDept() {
        // mock 数据
        DeptDO deptDO = randomPojo(DeptDO.class);
        when(deptMapper.selectById(deptDO.getId())).thenReturn(deptDO);
        // 准备参数
        Long id = deptDO.getId();

        // 调用
        DeptDO dbDept = deptService.getDept(id);
        // 断言
        assertEquals(deptDO, dbDept);
    }

    @Test
    void testGetDeptList_ids() {
        // mock 数据
        DeptDO deptDO01 = randomPojo(DeptDO.class);
        DeptDO deptDO02 = randomPojo(DeptDO.class);
        when(deptMapper.selectByIds(anyList())).thenReturn(List.of(deptDO01, deptDO02));

        // 准备参数
        List<Long> ids = Arrays.asList(deptDO01.getId(), deptDO02.getId());

        // 调用
        List<DeptDO> deptDOList = deptService.getDeptList(ids);
        // 断言
        assertEquals(2, deptDOList.size());
        assertEquals(deptDO01, deptDOList.get(0));
        assertEquals(deptDO02, deptDOList.get(1));
    }

    @Test
    void testGetDeptList_emptyids() {
        assertEquals(0, deptService.getDeptList(Collections.emptyList()).size());
    }

    @Test
    @WithMockLoginUser(isSuperAdmin = true)
    void testGetDeptList_superadmin_reqVO() {
        Long organId = SecurityFrameworkUtils.getUserOrganId();
        // mock 数据
        DeptDO dept = randomPojo(DeptDO.class, o -> { // 等会查询到
            o.setName("开发部");
            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
            o.setOrganId(organId);
        });

        // 准备参数
        DeptListReqVO reqVO = new DeptListReqVO();
        reqVO.setName("开");
        reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
        reqVO.setOrganId(organId);

        when(deptMapper.selectList(reqVO, organId)).thenReturn(Arrays.asList(dept));

        // 调用
        List<DeptDO> sysDeptDOS = deptService.getDeptList(reqVO);
        // 断言
        assertEquals(1, sysDeptDOS.size());
        assertPojoEquals(dept, sysDeptDOS.get(0));
    }

    @Test
    @WithMockLoginUser
    void testGetDeptList_commonuser_reqVO() {
        Long organId = SecurityFrameworkUtils.getUserOrganId();
        // mock 数据
        DeptDO dept = randomPojo(DeptDO.class, o -> { // 等会查询到
            o.setName("开发部");
            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
            o.setOrganId(organId);
        });

        // 准备参数
        DeptListReqVO reqVO = new DeptListReqVO();
        reqVO.setName("开");
        reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());

        when(deptMapper.selectList(reqVO, organId)).thenReturn(Arrays.asList(dept));

        // 调用
        List<DeptDO> sysDeptDOS = deptService.getDeptList(reqVO);
        // 断言
        assertEquals(1, sysDeptDOS.size());
        assertPojoEquals(dept, sysDeptDOS.get(0));
    }

    @Test
    void testGetChildDeptList() {
        // mock 数据（1 级别子节点）
        DeptDO dept1 = randomPojo(DeptDO.class, o -> o.setName("1"));

        // mock 数据（2 级子节点）
        DeptDO dept1a = randomPojo(DeptDO.class, o -> o.setName("1-a").setParentId(dept1.getId()));

        when(deptMapper.selectListByParentId(any())).thenReturn(Arrays.asList(dept1, dept1a)).thenReturn(null);

        // 准备参数
        Long id = dept1.getParentId();

        // 调用
        List<DeptDO> result = deptService.getChildDeptList(id);
        // 断言
        assertEquals(2, result.size());
        assertPojoEquals(dept1, result.get(0));
        assertPojoEquals(dept1a, result.get(1));
    }

    @Test
    void testGetChildDeptListFromCache() {
        // mock 数据（1 级别子节点）
        DeptDO dept1 = randomPojo(DeptDO.class, o -> o.setName("1"));
        deptMapper.insert(dept1);

        // mock 数据（2 级子节点）
        DeptDO dept1a = randomPojo(DeptDO.class, o -> o.setName("1-a").setParentId(dept1.getId()));
        deptMapper.insert(dept1a);

        when(deptMapper.selectListByParentId(any())).thenReturn(Arrays.asList(dept1, dept1a)).thenReturn(null);
        // 准备参数
        Long id = dept1.getParentId();

        // 调用
        Set<Long> result = deptService.getChildDeptIdListFromCache(id);
        // 断言
        assertEquals(2, result.size());
        assertTrue(result.contains(dept1.getId()));
        assertTrue(result.contains(dept1a.getId()));
    }

    @Test
    void testValidDept_NotFound() {
        // 部门不存在
        assertServiceException(() -> deptService.validDept(1L), DEPT_NOT_FOUND);
    }

    @Test
    void testValidDept_Disabled() {
        // 部门状态不可用
        DeptDO disableDbDeptDO = randomPojo(DeptDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
        when(deptMapper.selectById(disableDbDeptDO.getId())).thenReturn(disableDbDeptDO);
        assertServiceException(() -> deptService.validDept(disableDbDeptDO.getId()), DEPT_DISABLE, disableDbDeptDO.getName());
    }

    @Test
    void testValidDept_ParentNotFound() {
        DeptDO enabledbDeptDO = randomPojo(DeptDO.class, o -> {
            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
        });
        when(deptMapper.selectById(enabledbDeptDO.getId())).thenReturn(enabledbDeptDO);
        assertServiceException(() -> deptService.validDept(enabledbDeptDO.getId()), DEPT_PARENT_NOT_EXITS);
    }

    @Test
    void testValidDept_ParentDisabled() {
        DeptDO disabledParentDetpDO = randomPojo(DeptDO.class, o -> {
            o.setStatus(CommonStatusEnum.DISABLE.getStatus());
        });
        DeptDO enabledbDeptDO = randomPojo(DeptDO.class, o -> {
            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
            o.setParentId(disabledParentDetpDO.getId());
        });

        when(deptMapper.selectById(any())).thenReturn(enabledbDeptDO).thenReturn(disabledParentDetpDO);
        assertServiceException(() -> deptService.validDept(enabledbDeptDO.getId()), DEPT_DISABLE, disabledParentDetpDO.getName());
    }

    @Test
    void testValidDept_success() {
        DeptDO parentDetpDO = randomPojo(DeptDO.class, o -> {
            o.setId(null);
            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
            o.setParentId(DeptDO.PARENT_ID_ROOT);
        });

        DeptDO enabledbDeptDO = randomPojo(DeptDO.class, o -> {
            o.setId(null);
            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
            o.setParentId(parentDetpDO.getId());
        });
        when(deptMapper.selectById(any())).thenReturn(enabledbDeptDO).thenReturn(parentDetpDO);

        // 调用，无需断言
        assertDoesNotThrow(()-> deptService.validDept(enabledbDeptDO.getId()));
    }

    @Test
    void removeUnowndDept_empty() {
        List<DeptDO> deptDOS = deptService.removeUnowndDept(Collections.emptyList());
        assertEquals(0, deptDOS.size());
    }

    @Test
    void removeUnowndDept_success() {
        DeptDO oneParent = randomPojo(DeptDO.class, o -> o.setParentId(DeptDO.PARENT_ID_ROOT));
        DeptDO onechild1 = randomPojo(DeptDO.class, o -> o.setParentId(oneParent.getId()));
        DeptDO onechild2 = randomPojo(DeptDO.class, o -> o.setParentId(oneParent.getId()));
        List<DeptDO> paramDeptList = List.of(oneParent, onechild1, onechild2);
        List<DeptDO> deptDOS = deptService.removeUnowndDept(paramDeptList);
        assertEquals(deptDOS.size(), paramDeptList.size());
    }

    @Test
    void removeUnowndDept_ParentNotFound() {
        DeptDO oneParent = randomPojo(DeptDO.class, o -> o.setParentId(DeptDO.PARENT_ID_ROOT));
        DeptDO one = randomPojo(DeptDO.class, o -> o.setParentId(oneParent.getId()));
        DeptDO two = randomPojo(DeptDO.class);
        List<DeptDO> paramDeptList = List.of(oneParent, one, two);
        List<DeptDO> deptDOS = deptService.removeUnowndDept(paramDeptList);
        assertNotEquals(deptDOS.size(), paramDeptList.size());
    }

    @Test
    void getAllInvalidDeptIds_success() {
        Long organId = randomLongId();
        DeptDO oneParent = randomPojo(DeptDO.class, o -> {
            o.setId(randomLongId());
            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
            o.setOrganId(organId);
            o.setParentId(DeptDO.PARENT_ID_ROOT);
        });
        Long parentId = oneParent.getId();
        DeptDO one = randomPojo(DeptDO.class, o -> {
            o.setStatus(randomCommonStatus());
            o.setOrganId(organId);
            o.setParentId(parentId);
        });
        DeptDO two = randomPojo(DeptDO.class, o -> {
            o.setStatus(randomCommonStatus());
            o.setOrganId(organId);
            o.setParentId(parentId);
        });
        DeptDO three = randomPojo(DeptDO.class, o -> {
            o.setStatus(randomCommonStatus());
            o.setOrganId(organId);
            o.setParentId(parentId);
        });
        List<DeptDO> deptDOS = List.of(oneParent, one, two, three);
        // 批量插入
        when(deptMapper.selectList(any())).thenReturn(deptDOS);

        long disableCount = deptDOS.stream().filter(o -> CommonStatusEnum.DISABLE.getStatus().equals(o.getStatus())).count();

        Set<Long> allInvalidDeptIds = deptService.getAllInvalidDeptIds(organId);

        assertEquals(disableCount, allInvalidDeptIds.size());
//
//
    }

    @Test
    @WithMockLoginUser(organId = 100L)
    void getAllInvalidDeptIds_outerOrganIdNull(){
        OrganContextHolder.setOrganId(SecurityFrameworkUtils.getUserOrganId());

        deptService.getAllInvalidDeptIds(null);

        verify(deptMapper).selectList(any(LambdaQueryWrapper.class));
    }

    @Test
    void testDeptNotExist_shouldReturn() {
        // 不插入任何部门，确保 deptId 不存在
        Long nonExistDeptId = 9999L;

        assertDoesNotThrow(() -> deptService.validUserLoginDept(nonExistDeptId));
    }

    @Test
    void testDeptDisabled_shouldThrow() {
        // 插入禁用部门
        DeptDO dept = new DeptDO();
        dept.setName("测试部-禁用");
        dept.setStatus(CommonStatusEnum.DISABLE.getStatus());

        Long id = dept.getId();
        when(deptMapper.selectById(id)).thenReturn(dept);

        ServiceException ex = assertThrows(ServiceException.class,
                () -> deptService.validUserLoginDept(id));

        assertEquals(ErrorCodeConstants.DEPT_NOT_ALLOWED_LOGIN.getCode(), ex.getCode());
        assertTrue(ex.getArgs()[0].toString().contains("测试部-禁用"));
    }

    @Test
    void testDeptEnabled_shouldPass() {
        // 插入启用部门
        DeptDO dept = new DeptDO();
        dept.setName("测试部-启用");
        dept.setStatus(CommonStatusEnum.ENABLE.getStatus());
        dept.setParentId(DeptDO.PARENT_ID_ROOT);

        Long id = dept.getId();
        when(deptMapper.selectById(id)).thenReturn(dept);

        assertDoesNotThrow(() -> deptService.validUserLoginDept(id));
    }

    @Test
    void testParentDeptDisabled_shouldThrow() {
        // 上级部门禁用
        DeptDO parent = new DeptDO();
        parent.setId(100L);
        parent.setName("上级部门-禁用");
        parent.setStatus(CommonStatusEnum.DISABLE.getStatus());

        // 子部门启用
        DeptDO child = new DeptDO();
        child.setName("子部门");
        child.setStatus(CommonStatusEnum.ENABLE.getStatus());
        child.setParentId(parent.getId());

        when(deptMapper.selectById(any())).thenReturn(child).thenReturn(parent);

        Long childId = child.getId();
        ServiceException ex = assertThrows(ServiceException.class,
                () -> deptService.validUserLoginDept(childId));

        assertEquals(ErrorCodeConstants.DEPT_DISABLE.getCode(), ex.getCode());
        assertTrue(ex.getArgs()[0].toString().contains("上级部门-禁用"));
    }

    @Test
    void testParentDeptEnabled_shouldPass() {
        // 上级部门启用
        DeptDO parent = new DeptDO();
        parent.setId(100L);
        parent.setName("上级部门-启用");
        parent.setStatus(CommonStatusEnum.ENABLE.getStatus());
        parent.setParentId(DeptDO.PARENT_ID_ROOT);

        // 子部门启用
        DeptDO child = new DeptDO();
        child.setName("子部门");
        child.setStatus(CommonStatusEnum.ENABLE.getStatus());
        child.setParentId(parent.getId());
        when(deptMapper.selectById(any())).thenReturn(child).thenReturn(parent);

        assertDoesNotThrow(() -> deptService.validUserLoginDept(child.getId()));
    }

    @Test
    void testMultiLevelParentDeptDisabled_shouldThrow() {
        // 顶级部门禁用
        DeptDO top = new DeptDO();
        top.setId(100L);
        top.setName("顶级部门-禁用");
        top.setStatus(CommonStatusEnum.DISABLE.getStatus());

        // 中间部门启用，指向顶级
        DeptDO middle = new DeptDO();
        middle.setId(200L);
        middle.setName("中间部门-启用");
        middle.setStatus(CommonStatusEnum.ENABLE.getStatus());
        middle.setParentId(top.getId());

        // 子部门启用，指向中间部门
        DeptDO child = new DeptDO();
        child.setName("子部门-启用");
        child.setStatus(CommonStatusEnum.ENABLE.getStatus());
        child.setParentId(middle.getId());

        when(deptMapper.selectById(any())).thenReturn(child).thenReturn(middle).thenReturn(top);

        Long childId = child.getId();
        ServiceException ex = assertThrows(ServiceException.class,
                () -> deptService.validUserLoginDept(childId));

        assertEquals(ErrorCodeConstants.DEPT_DISABLE.getCode(), ex.getCode());
        assertTrue(ex.getArgs()[0].toString().contains("顶级部门-禁用"));
    }

    @Test
    void testMultiLevelAllEnabled_shouldPass() {
        // 顶级部门启用
        DeptDO top = new DeptDO();
        top.setId(100L);
        top.setName("顶级部门-启用");
        top.setStatus(CommonStatusEnum.ENABLE.getStatus());
        top.setParentId(DeptDO.PARENT_ID_ROOT);

        // 中间部门启用
        DeptDO middle = new DeptDO();
        middle.setId(200L);
        middle.setName("中间部门-启用");
        middle.setStatus(CommonStatusEnum.ENABLE.getStatus());
        middle.setParentId(top.getId());

        // 子部门启用
        DeptDO child = new DeptDO();
        child.setName("子部门-启用");
        child.setStatus(CommonStatusEnum.ENABLE.getStatus());
        child.setParentId(middle.getId());

        when(deptMapper.selectById(any())).thenReturn(child).thenReturn(middle).thenReturn(top);

        // 方法正常执行，不抛异常
        assertDoesNotThrow(() -> deptService.validUserLoginDept(child.getId()));
    }
}
