package com.yimeng.okr.service;

import com.yimeng.okr.entity.SysDepartment;
import com.yimeng.okr.entity.SysUser;
import com.yimeng.okr.enums.UserRole;
import com.yimeng.okr.exception.BusinessException;
import com.yimeng.okr.mapper.SysDepartmentMapper;
import com.yimeng.okr.mapper.SysUserMapper;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class AuthorizationServiceTest {

    @Mock SysUserMapper userMapper;
    @Mock SysDepartmentMapper departmentMapper;
    @InjectMocks AuthorizationService authorizationService;

    @Test
    void requireCanViewUserDataRejectsPeerAccess() {
        when(userMapper.selectById(1L)).thenReturn(user(1L, UserRole.EMPLOYEE, 10L, null));
        when(userMapper.selectById(2L)).thenReturn(user(2L, UserRole.EMPLOYEE, 10L, 9L));

        BusinessException ex = assertThrows(BusinessException.class,
                () -> authorizationService.requireCanViewUserData(1L, 2L));

        assertEquals(403, ex.getCode());
    }

    @Test
    void requireCanViewUserDataAllowsDirectSuperiorAndHr() {
        when(userMapper.selectById(7L)).thenReturn(user(7L, UserRole.TEAM_LEADER, 10L, null));
        when(userMapper.selectById(8L)).thenReturn(user(8L, UserRole.EMPLOYEE, 10L, 7L));
        when(userMapper.selectById(9L)).thenReturn(user(9L, UserRole.HR_ADMIN, null, null));

        assertDoesNotThrow(() -> authorizationService.requireCanViewUserData(7L, 8L));
        assertDoesNotThrow(() -> authorizationService.requireCanViewUserData(9L, 8L));
    }

    @Test
    void requireCanManageUserDataAllowsDepartmentLeader() {
        when(userMapper.selectById(3L)).thenReturn(user(3L, UserRole.DEPT_LEADER, 20L, null));
        when(userMapper.selectById(4L)).thenReturn(user(4L, UserRole.EMPLOYEE, 20L, 5L));
        SysDepartment dept = new SysDepartment();
        dept.setId(20L);
        dept.setLeaderId(3L);
        when(departmentMapper.selectById(20L)).thenReturn(dept);

        assertDoesNotThrow(() -> authorizationService.requireCanManageUserData(3L, 4L));
    }

    private SysUser user(Long id, UserRole role, Long deptId, Long superiorId) {
        SysUser user = new SysUser();
        user.setId(id);
        user.setUsername("u" + id);
        user.setRealName("用户" + id);
        user.setRole(role);
        user.setDepartmentId(deptId);
        user.setSuperiorId(superiorId);
        return user;
    }
}
