package com.atlassian.stash.internal.commit;

import com.atlassian.bitbucket.annotation.Dao;
import com.atlassian.bitbucket.annotation.DataSet;
import com.atlassian.bitbucket.commit.SimpleMinimalCommit;
import com.atlassian.stash.internal.AbstractDaoTest;
import com.atlassian.stash.internal.ApplicationConstants;
import com.atlassian.stash.internal.DataSets;
import com.atlassian.stash.internal.repository.HibernateRepositoryDao;
import com.atlassian.stash.internal.repository.InternalRepository;
import com.atlassian.stash.internal.repository.RepositoryDao;
import com.google.common.collect.ImmutableList;
import org.junit.Test;

import java.util.Collections;

@DataSet({DataSets.USERS, DataSets.PROJECTS, DataSets.REPOSITORIES, DataSets.COMMIT_DISCUSSIONS})
public class HibernateCommitDiscussionDaoTest extends AbstractDaoTest {

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

    @Test
    public void testCreate() {
        InternalRepository repository = repositoryDao.loadById(1);

        InternalCommitDiscussion discussion = new InternalCommitDiscussion.Builder(repository, "50a47186b05a4c3091a355d028b4150a545d4af7")
                .parents(Collections.singleton(
                        new SimpleMinimalCommit.Builder("c9eac1352953ff32838630148a0814756d29b641").build()))
                .build();
        InternalCommitDiscussion created = dao.create(discussion);

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

        assertNotEquals(ApplicationConstants.UNSAVED_ENTITY, discussion.getId());
        assertNotNull(discussion.getParticipants());
        assertNotNull(discussion.getWatchers());
        assertEquals(discussion.getId(), created.getId());

        InternalCommitDiscussion retrieved = dao.getById(created.getId());
        assertEquals("50a47186b05a4c3091a355d028b4150a545d4af7", retrieved.getCommitId());
        assertEquals(discussion.getId(), retrieved.getId());
        assertEquals("c9eac1352953ff32838630148a0814756d29b641", retrieved.getParentId());
        assertEquals(repository, retrieved.getRepository());
        assertFalse(retrieved.isMerge());
    }

    @Test
    public void testCreateWithMergeCommit() {
        InternalRepository repository = repositoryDao.loadById(1);

        InternalCommitDiscussion discussion = new InternalCommitDiscussion.Builder(repository, "c9eac1352953ff32838630148a0814756d29b641")
                .parents(ImmutableList.of(
                        new SimpleMinimalCommit.Builder("b8b50f32b13bd3859853272df84c609effa4df57").build(),
                        new SimpleMinimalCommit.Builder("13c330d1ea3cfe11349964e31aa5dea14f785639").build()))
                .build();
        InternalCommitDiscussion created = dao.create(discussion);

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

        assertNotEquals(ApplicationConstants.UNSAVED_ENTITY, discussion.getId());
        assertNotNull(discussion.getParticipants());
        assertNotNull(discussion.getWatchers());
        assertEquals(discussion.getId(), created.getId());

        InternalCommitDiscussion retrieved = dao.getById(created.getId());
        assertEquals("c9eac1352953ff32838630148a0814756d29b641", retrieved.getCommitId());
        assertEquals(discussion.getId(), retrieved.getId());
        assertEquals("b8b50f32b13bd3859853272df84c609effa4df57", retrieved.getParentId());
        assertEquals(repository, retrieved.getRepository());
        assertTrue(retrieved.isMerge());
    }

    @Test
    public void testCreateWithRootCommit() {
        InternalRepository repository = repositoryDao.loadById(1);

        InternalCommitDiscussion discussion = new InternalCommitDiscussion.Builder(repository, "ed4eac02cd99d55161866f316ef2618a06609ed8")
                .build();
        InternalCommitDiscussion created = dao.create(discussion);

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

        assertNotEquals(ApplicationConstants.UNSAVED_ENTITY, discussion.getId());
        assertNotNull(discussion.getParticipants());
        assertNotNull(discussion.getWatchers());
        assertEquals(discussion.getId(), created.getId());

        InternalCommitDiscussion retrieved = dao.getById(created.getId());
        assertEquals("ed4eac02cd99d55161866f316ef2618a06609ed8", retrieved.getCommitId());
        assertEquals(discussion.getId(), retrieved.getId());
        assertEquals(repository, retrieved.getRepository());
        assertFalse(retrieved.isMerge());
        assertNull(retrieved.getParentId());
    }

    @Test(expected = UnsupportedOperationException.class)
    public void testDelete() {
        InternalCommitDiscussion discussion = dao.getById(1L);
        assertNotNull(discussion);

        dao.delete(discussion);
    }

    @SuppressWarnings("ConstantConditions")
    @Test
    public void testFindByRepositoryAndCommit() {
        assertEquals(1L, dao.findByRepositoryAndCommit(1, "e53829aceffede831f69137bab313928fa932ce1").getId());
        assertNull(dao.findByRepositoryAndCommit(2, "e53829aceffede831f69137bab313928fa932ce1")); //Wrong repository
        assertNull(dao.findByRepositoryAndCommit(1, "e53829aceffede831f69137bab313928fa932ce2")); //Wrong hash
    }

    @Test(expected = UnsupportedOperationException.class)
    public void testUpdate() {
        InternalCommitDiscussion discussion = dao.getById(1L);
        assertNotNull(discussion);

        dao.update(discussion);
    }
}
