package com.atlassian.stash.internal.merge;

import com.atlassian.bitbucket.annotation.Dao;
import com.atlassian.bitbucket.annotation.DataSet;
import com.atlassian.bitbucket.util.Page;
import com.atlassian.bitbucket.util.PageUtils;
import com.atlassian.stash.internal.AbstractDaoTest;
import com.atlassian.stash.internal.DataSets;
import com.atlassian.stash.internal.repository.HibernateRepositoryDao;
import com.atlassian.stash.internal.repository.RepositoryDao;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import org.junit.Test;

import static java.util.stream.Collectors.toSet;

@DataSet({DataSets.PROJECTS, DataSets.REPOSITORIES, DataSets.REPOSITORY_MERGE_CONFIGS})
public class HibernateRepositoryMergeConfigDaoTest extends AbstractDaoTest {

    @Dao
    private HibernateRepositoryMergeConfigDao dao;
    @Dao(HibernateRepositoryDao.class)
    private RepositoryDao repositoryDao;

    @Test
    public void testCreate() {
        InternalRepositoryMergeConfig config = new InternalRepositoryMergeConfig(repositoryDao.loadById(2),
                "squash", ImmutableSet.of("squash", "squash-ff-only"));
        InternalRepositoryMergeConfig created = dao.create(config);
        assertEquals(config.getId(), created.getId());

        flush();
        evict(created, created.getId());

        InternalRepositoryMergeConfig verify = dao.getById(created.getId());
        assertEquals(config.getDefaultStrategyId(), verify.getDefaultStrategyId());
        assertEquals(config.getRepositoryId(), verify.getRepositoryId());
        assertEquals(config.getStrategyIds(), verify.getStrategyIds());
    }

    @Test
    public void testDelete() {
        InternalRepositoryMergeConfig config = dao.getById(1L);
        assertNotNull(config);
        dao.delete(config);

        flush();
        evict(config, config.getId());

        assertNull(dao.getById(1L));
    }

    @Test
    public void testDeleteById() {
        dao.deleteById(2L);

        flush();

        assertNull(dao.getById(2L));
    }

    @Test
    public void testFindAll() {
        Page<InternalRepositoryMergeConfig> page = dao.findAll(PageUtils.newRequest(0, 10));
        assertNotNull(page);
        assertEquals(2, page.getSize());
        assertTrue(page.getIsLastPage());
        assertEquals(ImmutableSet.of(1L, 2L), page.stream().map(InternalRepositoryMergeConfig::getId).collect(toSet()));
    }

    @Test
    public void testFindAllWithPredicate() {
        Page<InternalRepositoryMergeConfig> page = dao.findAll(PageUtils.newRequest(0, 10),
                config -> config.getId() % 2L == 1L);
        assertNotNull(page);
        assertEquals(1, page.getSize());
        assertTrue(page.getIsLastPage());
        assertEquals(1L, Iterables.getOnlyElement(page.getValues()).getId());
    }

    @Test
    public void testFindByRepository() {
        InternalRepositoryMergeConfig config = dao.findByRepository(5);
        assertNotNull(config);
        assertEquals("ff-only", config.getDefaultStrategyId());
        assertEquals(1L, config.getId());
        assertEquals(5, config.getRepositoryId());
        assertEquals(ImmutableSet.of("ff-only", "squash-ff-only"), config.getStrategyIds());
        assertSame(MergeConfigType.REPOSITORY, config.getType());

        config = dao.findByRepository(6);
        assertNotNull(config);
        assertEquals("default", config.getDefaultStrategyId());
        assertEquals(2L, config.getId());
        assertEquals(6, config.getRepositoryId());
        assertEquals(ImmutableSet.of("default"), config.getStrategyIds());
        assertSame(MergeConfigType.REPOSITORY, config.getType());

        assertNull(dao.findByRepository(1));
    }

    @Test
    public void testGetById() {
        InternalRepositoryMergeConfig config = dao.getById(1L);
        assertNotNull(config);
        assertEquals("ff-only", config.getDefaultStrategyId());
        assertEquals(1L, config.getId());
        assertEquals(5, config.getRepositoryId());
        assertEquals(ImmutableSet.of("ff-only", "squash-ff-only"), config.getStrategyIds());
        assertSame(MergeConfigType.REPOSITORY, config.getType());

        assertNull(dao.getById(10L));
    }

    @Test
    public void testUpdate() {
        InternalRepositoryMergeConfig initial = dao.getById(2L);
        initial.setDefaultStrategyId("rebase");
        initial.setStrategyIds(ImmutableSet.of("rebase"));
        dao.update(initial);

        flush();
        evict(initial, initial.getId());

        InternalRepositoryMergeConfig updated = dao.getById(2L);
        assertEquals(initial.getId(), updated.getId());
        assertEquals(initial.getRepositoryId(), updated.getRepositoryId());
        assertEquals("rebase", updated.getDefaultStrategyId());
        assertEquals(ImmutableSet.of("rebase"), updated.getStrategyIds());
    }
}