package com.ruoyi.web.modules.app.service.impl;

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

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import com.ruoyi.common.constant.UserConstants;
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.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.web.modules.app.domain.AppUserRegisterBody;
import com.ruoyi.web.modules.app.support.AppUserRegisterRules;

@ExtendWith(MockitoExtension.class)
@DisplayName("AppUserRegisterServiceImpl")
class AppUserRegisterServiceImplTest
{

    @Mock
    private ISysUserService userService;

    @Mock
    private ISysRoleService roleService;

    @InjectMocks
    private AppUserRegisterServiceImpl service;

    @Test
    @DisplayName("用户名可用")
    void usernameAvailable()
    {
        when(userService.checkUserNameUnique(any())).thenReturn(UserConstants.UNIQUE);
        assertTrue(service.isUsernameAvailable("newuser01"));
    }

    @Test
    @DisplayName("用户名已占用")
    void usernameTaken()
    {
        when(userService.checkUserNameUnique(any())).thenReturn(UserConstants.NOT_UNIQUE);
        assertFalse(service.isUsernameAvailable("exists"));
    }

    @Test
    @DisplayName("用户名格式非法")
    void usernameFormatInvalid()
    {
        assertThrows(ServiceException.class, () -> service.isUsernameAvailable("a"));
    }

    @Test
    @DisplayName("注册成功并绑定角色2")
    void registerSuccess()
    {
        when(userService.checkUserNameUnique(any())).thenReturn(UserConstants.UNIQUE);
        SysRole role = new SysRole();
        role.setRoleId(AppUserRegisterRules.DEFAULT_ROLE_ID);
        when(roleService.selectRoleById(AppUserRegisterRules.DEFAULT_ROLE_ID)).thenReturn(role);
        when(userService.insertUser(any())).thenAnswer(inv -> {
            SysUser u = inv.getArgument(0);
            u.setUserId(99L);
            return 1;
        });

        AppUserRegisterBody body = new AppUserRegisterBody();
        body.setNickName("牧民甲");
        body.setUserName("herder01");
        body.setPassword("abc12345");

        Long userId = service.register(body);
        assertEquals(99L, userId.longValue());

        ArgumentCaptor<SysUser> captor = ArgumentCaptor.forClass(SysUser.class);
        verify(userService).insertUser(captor.capture());
        SysUser saved = captor.getValue();
        assertEquals("herder01", saved.getUserName());
        assertEquals("牧民甲", saved.getNickName());
        assertEquals(AppUserRegisterRules.DEFAULT_DEPT_ID, saved.getDeptId().longValue());
        assertEquals(1, saved.getRoleIds().length);
        assertEquals(AppUserRegisterRules.DEFAULT_ROLE_ID, saved.getRoleIds()[0].longValue());
    }

    @Test
    @DisplayName("注册时用户名重复")
    void registerDuplicateUserName()
    {
        when(userService.checkUserNameUnique(any())).thenReturn(UserConstants.NOT_UNIQUE);
        AppUserRegisterBody body = new AppUserRegisterBody();
        body.setNickName("昵称");
        body.setUserName("dup");
        body.setPassword("123456");
        assertThrows(ServiceException.class, () -> service.register(body));
    }
}
