package com.atlassian.stash.internal.commit;

import com.atlassian.bitbucket.annotation.Dao;
import com.atlassian.bitbucket.annotation.DataSet;
import com.atlassian.bitbucket.commit.CommitDiscussionParticipant;
import com.atlassian.stash.internal.AbstractDaoTest;
import com.atlassian.stash.internal.DataSets;
import com.atlassian.stash.internal.user.HibernateStashUserDao;
import com.atlassian.stash.internal.user.InternalApplicationUser;
import com.atlassian.stash.internal.user.StashUserDao;
import com.atlassian.bitbucket.util.Page;
import com.atlassian.bitbucket.util.PageUtils;
import com.google.common.collect.Iterables;
import org.junit.Test;

@DataSet({DataSets.USERS, DataSets.PROJECTS, DataSets.REPOSITORIES, DataSets.COMMIT_DISCUSSIONS})
@SuppressWarnings("ConstantConditions")
public class HibernateCommitDiscussionParticipantDaoTest extends AbstractDaoTest {

    @Dao
    private HibernateCommitDiscussionParticipantDao dao;
    @Dao(HibernateCommitDiscussionDao.class)
    private CommitDiscussionDao discussionDao;
    @Dao(HibernateStashUserDao.class)
    private StashUserDao userDao;

    @Test
    public void testCreate() {
        InternalCommitDiscussion discussion = discussionDao.loadById(2L); //User 3 is already a participant on 1
        InternalApplicationUser user = userDao.loadById(3);

        InternalCommitDiscussionParticipant participant = new InternalCommitDiscussionParticipant.Builder(discussion)
                .user(user)
                .build();
        InternalCommitDiscussionParticipant created = dao.create(participant);

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

        //Verify pointer chasing
        assertTrue(discussion.getParticipants().contains(created));

        InternalCommitDiscussionParticipant check = dao.getById(created.getId());
        assertNotNull(check.getId());
        assertEquals(check.getId(), participant.getId());
    }

    @Test
    public void testDelete() {
        InternalCommitDiscussion discussion = discussionDao.loadById(1L);
        assertEquals(3, discussion.getParticipants().size());

        CommitDiscussionParticipant participant = Iterables.getFirst(discussion.getParticipants(), null);
        assertNotNull(participant);
        dao.delete((InternalCommitDiscussionParticipant) participant);

        //Verify pointer chasing
        assertEquals(2, discussion.getParticipants().size());
        assertFalse(discussion.getParticipants().contains(participant));
    }

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

        flush();
        clear();

        InternalCommitDiscussion discussion = discussionDao.getById(2L);
        assertEquals(1, discussion.getParticipants().size());
        assertEquals(4L, ((InternalCommitDiscussionParticipant) Iterables.getOnlyElement(discussion.getParticipants())).getId());
    }

    @Test
    public void testDeleteByIdWithNonexistentId() {
        dao.deleteById(42L);
    }

    @Test
    public void testFindByDiscussion() {
        Page<InternalCommitDiscussionParticipant> page = dao.findByDiscussion(2L, PageUtils.newRequest(0, 1));

        assertEquals(1, page.getSize());
        assertFalse(page.getIsLastPage());
        assertEquals(1, page.getNextPageRequest().getStart());
        assertEquals(4L, Iterables.getOnlyElement(page.getValues()).getId());

        page = dao.findByDiscussion(2L, page.getNextPageRequest());
        assertEquals(1, page.getSize());
        assertEquals(5L, Iterables.getOnlyElement(page.getValues()).getId());
        assertTrue(page.getIsLastPage());
    }

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

        dao.update(participant);
    }
}
