package org.apache.eventmesh.dashboard.console.unit.group;

import org.apache.eventmesh.dashboard.console.EventMeshDashboardApplication;
import org.apache.eventmesh.dashboard.console.entity.group.GroupEntity;
import org.apache.eventmesh.dashboard.console.mapper.group.OprGroupMapper;

import java.util.ArrayList;
import java.util.List;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = EventMeshDashboardApplication.class)
public class TestGroupMapper {

    @Autowired
    private OprGroupMapper groupMapper;

    public List<GroupEntity> insertGroupData(String name) {
        List<GroupEntity> groupEntities = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            GroupEntity groupEntity = new GroupEntity(null, (long) i, name, 0, null, 1, "OK", null, null);
            groupMapper.addGroup(groupEntity);
            groupEntities.add(groupEntity);
        }
        return groupEntities;
    }

    public List<GroupEntity> getRemovedTimeList(String name) {
        GroupEntity groupEntity = new GroupEntity();
        groupEntity.setName(name);
        List<GroupEntity> groupEntities = groupMapper.selectGroup(groupEntity);
        for (GroupEntity groupEntity1 : groupEntities) {
            groupEntity1.setCreateTime(null);
            groupEntity1.setUpdateTime(null);
        }
        return groupEntities;
    }

    @Test
    public void testAddGroup() {
        List<GroupEntity> groupEntities = this.insertGroupData("addGroup");
        GroupEntity groupEntity = new GroupEntity();
        groupEntity.setName("addGroup");
        List<GroupEntity> groupEntities1 = groupMapper.selectGroup(groupEntity);
        Assert.assertEquals(groupEntities, this.getRemovedTimeList("addGroup"));
    }

    @Test
    public void testUpdateGroupById() {
        List<GroupEntity> groupEntities = this.insertGroupData("updateById2");
        GroupEntity groupEntity = groupEntities.get(9);
        groupEntity.setType(3);
        groupEntity.setMembers("1,");
        groupEntity.setState("fail");
        groupEntity.setMemberCount(1);
        groupMapper.updateGroup(groupEntity);
        Assert.assertEquals(groupEntities, this.getRemovedTimeList("updateById2"));
    }

    @Test
    public void testDeleteGroupById() {
        List<GroupEntity> groupEntities = this.insertGroupData("deleteById");
        GroupEntity groupEntity = groupEntities.get(9);
        groupMapper.deleteGroup(groupEntity);
        groupEntities.remove(9);
        Assert.assertEquals(groupEntities, this.getRemovedTimeList("deleteById"));
    }

    @Test
    public void testSelectGroupById() {
        List<GroupEntity> groupEntities = this.insertGroupData("selectById");
        GroupEntity groupEntity = groupMapper.selectGroupById(groupEntities.get(0));
        groupEntity.setCreateTime(null);
        groupEntity.setUpdateTime(null);
        Assert.assertEquals(groupEntities.get(0), groupEntity);
    }

    @Test
    public void testSelectGroupByClusterId() {
        List<GroupEntity> groupEntities = this.insertGroupData("selectByUnique");
        GroupEntity groupEntity1 = new GroupEntity();
        groupEntity1.setClusterId(groupEntities.get(0).getClusterId());
        groupEntity1.setName(groupEntities.get(0).getName());
        GroupEntity groupEntity = groupMapper.selectGroupByUnique(groupEntity1);
        groupEntity.setCreateTime(null);
        groupEntity.setUpdateTime(null);
        Assert.assertEquals(groupEntities.get(0), groupEntity);
    }

    @Test
    public void testSelectGroup() {
        List<GroupEntity> groupEntities = this.insertGroupData("selectByDynamic1");
        Assert.assertEquals(groupEntities, this.getRemovedTimeList("Dynamic1"));
    }
}
