package com.jojubanking.boot.module.system.service.userinfo;

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;

import javax.annotation.Resource;

import com.jojubanking.boot.framework.test.core.ut.BaseDbUnitTest;

import com.jojubanking.boot.module.system.controller.app.userinfo.vo.*;
import com.jojubanking.boot.module.system.dal.dataobject.userinfo.UserInfoDO;
import com.jojubanking.boot.module.system.dal.mysql.userinfo.UserInfoMapper;
import com.jojubanking.boot.framework.common.pojo.PageResult;

import javax.annotation.Resource;
import org.springframework.context.annotation.Import;
import java.util.*;

import static cn.hutool.core.util.RandomUtil.*;
import static com.jojubanking.boot.module.system.enums.ErrorCodeConstants.*;
import static com.jojubanking.boot.framework.test.core.util.AssertUtils.*;
import static com.jojubanking.boot.framework.test.core.util.RandomUtils.*;
import static com.jojubanking.boot.framework.common.util.object.ObjectUtils.*;
import static com.jojubanking.boot.framework.common.util.date.DateUtils.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

/**
 * {@link UserInfoServiceImpl} 的单元测试类
 *
 * @author admin
 */
@Import(UserInfoServiceImpl.class)
public class UserInfoServiceImplTest extends BaseDbUnitTest {

    @Resource
    private UserInfoServiceImpl userInfoService;

    @Resource
    private UserInfoMapper userInfoMapper;

    @Test
    public void testCreateUserInfo_success() {
        // 准备参数
        AppUserInfoCreateReqVO reqVO = randomPojo(AppUserInfoCreateReqVO.class);

        // 调用
        Long userInfoId = userInfoService.createUserInfo(reqVO);
        // 断言
        assertNotNull(userInfoId);
        // 校验记录的属性是否正确
        UserInfoDO userInfo = userInfoMapper.selectById(userInfoId);
        assertPojoEquals(reqVO, userInfo);
    }

    @Test
    public void testUpdateUserInfo_success() {
        // mock 数据
        UserInfoDO dbUserInfo = randomPojo(UserInfoDO.class);
        userInfoMapper.insert(dbUserInfo);// @Sql: 先插入出一条存在的数据
        // 准备参数
        AppUserInfoUpdateReqVO reqVO = randomPojo(AppUserInfoUpdateReqVO.class, o -> {
            o.setId(dbUserInfo.getId()); // 设置更新的 ID
        });

        // 调用
        userInfoService.updateUserInfo(reqVO);
        // 校验是否更新正确
        UserInfoDO userInfo = userInfoMapper.selectById(reqVO.getId()); // 获取最新的
        assertPojoEquals(reqVO, userInfo);
    }

    @Test
    public void testUpdateUserInfo_notExists() {
        // 准备参数
        AppUserInfoUpdateReqVO reqVO = randomPojo(AppUserInfoUpdateReqVO.class);

        // 调用, 并断言异常
        assertServiceException(() -> userInfoService.updateUserInfo(reqVO), USER_INFO_NOT_EXISTS);
    }

    @Test
    public void testDeleteUserInfo_success() {
        // mock 数据
        UserInfoDO dbUserInfo = randomPojo(UserInfoDO.class);
        userInfoMapper.insert(dbUserInfo);// @Sql: 先插入出一条存在的数据
        // 准备参数
        Long id = dbUserInfo.getId();

        // 调用
        userInfoService.deleteUserInfo(id);
        // 校验数据不存在了
        assertNull(userInfoMapper.selectById(id));
    }

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

        // 调用, 并断言异常
        assertServiceException(() -> userInfoService.deleteUserInfo(id), USER_INFO_NOT_EXISTS);
    }

    @Test
    @Disabled  // TODO 请修改 null 为需要的值，然后删除 @Disabled 注解
    public void testGetUserInfoPage() {
        // mock 数据
        UserInfoDO dbUserInfo = randomPojo(UserInfoDO.class, o -> { // 等会查询到
            o.setOpenid(null);
            o.setName(null);
            o.setUser(null);
            o.setPassword(null);
            o.setPhone(null);
            o.setIdno(null);
            o.setEmail(null);
            o.setRemark(null);
            o.setHeadurl(null);
            o.setBirthdate(null);
            o.setNativeplace(null);
            o.setCountry(null);
            o.setProvince(null);
            o.setCity(null);
            o.setSex(null);
            o.setCreateTime(null);
        });
        userInfoMapper.insert(dbUserInfo);
        // 测试 openid 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setOpenid(null)));
        // 测试 name 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setName(null)));
        // 测试 user 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setUser(null)));
        // 测试 password 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setPassword(null)));
        // 测试 phone 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setPhone(null)));
        // 测试 idNo 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setIdno(null)));
        // 测试 email 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setEmail(null)));
        // 测试 remark 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setRemark(null)));
        // 测试 headUrl 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setHeadurl(null)));
        // 测试 birthDate 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setBirthdate(null)));
        // 测试 nativePlace 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setNativeplace(null)));
        // 测试 country 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setCountry(null)));
        // 测试 province 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setProvince(null)));
        // 测试 city 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setCity(null)));
        // 测试 sex 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setSex(null)));
        // 测试 createTime 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setCreateTime(null)));
        // 准备参数
        AppUserInfoPageReqVO reqVO = new AppUserInfoPageReqVO();
        reqVO.setOpenid(null);
        reqVO.setName(null);
        reqVO.setUser(null);
        reqVO.setPassword(null);
        reqVO.setPhone(null);
        reqVO.setIdno(null);
        reqVO.setEmail(null);
        reqVO.setRemark(null);
        reqVO.setHeadurl(null);
//        reqVO.setBirthDate((new Date[]{}));
        reqVO.setNativeplace(null);
        reqVO.setCountry(null);
        reqVO.setProvince(null);
        reqVO.setCity(null);
        reqVO.setSex(null);
        reqVO.setCreateTime((new Date[]{}));

        // 调用
        PageResult<UserInfoDO> pageResult = userInfoService.getUserInfoPage(reqVO);
        // 断言
        assertEquals(1, pageResult.getTotal());
        assertEquals(1, pageResult.getList().size());
        assertPojoEquals(dbUserInfo, pageResult.getList().get(0));
    }

    @Test
    @Disabled  // TODO 请修改 null 为需要的值，然后删除 @Disabled 注解
    public void testGetUserInfoList() {
        // mock 数据
        UserInfoDO dbUserInfo = randomPojo(UserInfoDO.class, o -> { // 等会查询到
            o.setOpenid(null);
            o.setName(null);
            o.setUser(null);
            o.setPassword(null);
            o.setPhone(null);
            o.setIdno(null);
            o.setEmail(null);
            o.setRemark(null);
            o.setHeadurl(null);
            o.setBirthdate(null);
            o.setNativeplace(null);
            o.setCountry(null);
            o.setProvince(null);
            o.setCity(null);
            o.setSex(null);
            o.setCreateTime(null);
        });
        userInfoMapper.insert(dbUserInfo);
        // 测试 openid 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setOpenid(null)));
        // 测试 name 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setName(null)));
        // 测试 user 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setUser(null)));
        // 测试 password 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setPassword(null)));
        // 测试 phone 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setPhone(null)));
        // 测试 idNo 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setIdno(null)));
        // 测试 email 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setEmail(null)));
        // 测试 remark 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setRemark(null)));
        // 测试 headUrl 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setHeadurl(null)));
        // 测试 birthDate 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setBirthdate(null)));
        // 测试 nativePlace 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setNativeplace(null)));
        // 测试 country 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setCountry(null)));
        // 测试 province 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setProvince(null)));
        // 测试 city 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setCity(null)));
        // 测试 sex 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setSex(null)));
        // 测试 createTime 不匹配
        userInfoMapper.insert(cloneIgnoreId(dbUserInfo, o -> o.setCreateTime(null)));
        // 准备参数
        AppUserInfoExportReqVO reqVO = new AppUserInfoExportReqVO();
        reqVO.setOpenid(null);
        reqVO.setName(null);
        reqVO.setUser(null);
        reqVO.setPassword(null);
        reqVO.setPhone(null);
        reqVO.setIdno(null);
        reqVO.setEmail(null);
        reqVO.setRemark(null);
        reqVO.setHeadurl(null);
//        reqVO.setBirthDate((new Date[]{}));
        reqVO.setNativeplace(null);
        reqVO.setCountry(null);
        reqVO.setProvince(null);
        reqVO.setCity(null);
        reqVO.setSex(null);
        reqVO.setCreateTime((new Date[]{}));

        // 调用
        List<UserInfoDO> list = userInfoService.getUserInfoList(reqVO);
        // 断言
        assertEquals(1, list.size());
        assertPojoEquals(dbUserInfo, list.get(0));
    }

}
