package com.ruoyi.web.modules.diagnosis.support;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.mapper.SysRoleMapper;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.web.modules.diagnosis.MedicalResourceTestSamples;
import com.ruoyi.web.modules.diagnosis.domain.BizMedicalResource;
import org.junit.jupiter.api.DisplayName;
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;

@ExtendWith(MockitoExtension.class)
@DisplayName("MedicalResourceAccountAssigner")
class MedicalResourceAccountAssignerTest
{
    @Mock
    private ISysUserService sysUserService;

    @Mock
    private ISysConfigService configService;

    @Mock
    private SysRoleMapper sysRoleMapper;

    @InjectMocks
    private MedicalResourceAccountAssigner assigner;

    @Test
    @DisplayName("兽医绑定 vet 角色")
    void createAccountVet()
    {
        BizMedicalResource resource = MedicalResourceTestSamples.sampleVetDraft();
        resource.setId(12L);
        resource.setResourceName("张兽医");
        resource.setTownDeptId(201L);
        SysRole role = new SysRole();
        role.setRoleId(100L);
        when(sysRoleMapper.checkRoleKeyUnique(MedicalResourceRules.ROLE_KEY_VET)).thenReturn(role);
        when(sysUserService.checkUserNameUnique(any())).thenReturn(true);
        when(configService.selectConfigByKey("sys.user.initPassword")).thenReturn("123456");
        when(sysUserService.insertUser(any())).thenAnswer(inv -> {
            SysUser u = inv.getArgument(0);
            u.setUserId(1L);
            return 1;
        });

        SysUser user = assigner.createAccount(resource, "admin");
        assertEquals("zsy12", user.getUserName());
        verify(sysRoleMapper).checkRoleKeyUnique(MedicalResourceRules.ROLE_KEY_VET);
        verify(sysUserService).insertUser(argThat(u -> Long.valueOf(201L).equals(u.getDeptId())));
    }

    @Test
    @DisplayName("兽医无乡镇时不写 deptId")
    void createAccountVetWithoutTown()
    {
        BizMedicalResource resource = MedicalResourceTestSamples.sampleVetDraft();
        resource.setId(12L);
        resource.setResourceName("张兽医");
        resource.setTownDeptId(null);
        SysRole role = new SysRole();
        role.setRoleId(100L);
        when(sysRoleMapper.checkRoleKeyUnique(MedicalResourceRules.ROLE_KEY_VET)).thenReturn(role);
        when(sysUserService.checkUserNameUnique(any())).thenReturn(true);
        when(configService.selectConfigByKey("sys.user.initPassword")).thenReturn("123456");
        when(sysUserService.insertUser(any())).thenAnswer(inv -> {
            SysUser u = inv.getArgument(0);
            u.setUserId(1L);
            return 1;
        });

        assigner.createAccount(resource, "admin");
        verify(sysUserService).insertUser(argThat(u -> u.getDeptId() == null));
    }

    @Test
    @DisplayName("已分配时同步更新用户部门")
    void syncLinkedUserDept()
    {
        BizMedicalResource resource = MedicalResourceTestSamples.sampleVetDraft();
        resource.setAccountAssigned(MedicalResourceRules.ACCOUNT_ASSIGNED_YES);
        resource.setSysUserId(9L);
        resource.setTownDeptId(202L);
        when(sysUserService.updateUserProfile(any())).thenReturn(1);
        assigner.syncLinkedUserDept(resource);
        verify(sysUserService).updateUserProfile(argThat(u ->
                Long.valueOf(9L).equals(u.getUserId()) && Long.valueOf(202L).equals(u.getDeptId())));
    }

    @Test
    @DisplayName("机构绑定 ins 角色")
    void createAccountOrg()
    {
        BizMedicalResource resource = MedicalResourceTestSamples.sampleOrgDraft();
        resource.setId(8L);
        resource.setResourceName("巴青县动物医院");
        SysRole role = new SysRole();
        role.setRoleId(102L);
        when(sysRoleMapper.checkRoleKeyUnique(MedicalResourceRules.ROLE_KEY_INS)).thenReturn(role);
        when(sysUserService.checkUserNameUnique(any())).thenReturn(true);
        when(configService.selectConfigByKey("sys.user.initPassword")).thenReturn("123456");
        when(sysUserService.insertUser(any())).thenAnswer(inv -> {
            SysUser u = inv.getArgument(0);
            u.setUserId(2L);
            return 1;
        });

        assigner.createAccount(resource, "admin");
        verify(sysRoleMapper).checkRoleKeyUnique(MedicalResourceRules.ROLE_KEY_INS);
    }

    @Test
    @DisplayName("角色不存在")
    void roleMissing()
    {
        BizMedicalResource resource = MedicalResourceTestSamples.sampleVetDraft();
        resource.setId(1L);
        when(sysUserService.checkUserNameUnique(any())).thenReturn(true);
        when(sysRoleMapper.checkRoleKeyUnique(MedicalResourceRules.ROLE_KEY_VET)).thenReturn(null);
        assertThrows(ServiceException.class, () -> assigner.createAccount(resource, "admin"));
    }
}
