package com.atlassian.stash.internal.maintenance;

import com.atlassian.bitbucket.i18n.I18nService;
import com.atlassian.bitbucket.i18n.SimpleI18nService;
import com.atlassian.stash.internal.db.DatabaseAffixed;
import com.atlassian.stash.internal.migration.MigrationException;
import com.atlassian.bitbucket.util.Progress;
import com.google.common.collect.ImmutableList;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class ReleaseAffixedDatabaseStepTest {

    @Mock(name = "firstAffix")
    private DatabaseAffixed firstAffix;
    @Spy
    private I18nService i18nService = new SimpleI18nService();
    @Mock(name = "secondAffix")
    private DatabaseAffixed secondAffix;
    private ReleaseAffixedDatabaseStep step;

    @Before
    public void setup() {
        step = new ReleaseAffixedDatabaseStep(i18nService, ImmutableList.of(firstAffix, secondAffix));
    }

    @Test
    public void testGetProgress() {
        Progress progress = step.getProgress();
        assertNotNull(progress);
        assertEquals("bitbucket.migration.releasingdatabase", progress.getMessage());
        assertEquals(0, progress.getPercentage());
    }

    @Test
    public void testRun() {
        step.run();

        Progress progress = step.getProgress();
        assertNotNull(progress);
        assertEquals("bitbucket.migration.releasingdatabase", progress.getMessage());
        assertEquals(100, progress.getPercentage());
    }

    @Test
    public void testRunHandlesCancellation() {
        doAnswer(new Answer() {

            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                step.cancel();

                return null;
            }
        }).when(firstAffix).release();

        step.run();
        verify(firstAffix).release();
        verifyZeroInteractions(secondAffix);
    }

    @Test(expected = MigrationException.class)
    public void testRunHandlesExceptions() {
        doThrow(RuntimeException.class).when(secondAffix).release();

        try {
            step.run();
        } finally {
            verify(firstAffix).release();
            verify(secondAffix).release();
            verify(i18nService).createKeyedMessage(eq("bitbucket.migration.releasedatabasefailed"));
        }
    }
}