package com.atlassian.bitbucket.mesh;

import com.atlassian.bitbucket.mesh.layout.StorageLayout;
import org.apache.commons.io.FileUtils;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import org.springframework.core.io.ClassPathResource;

import java.io.File;
import java.io.IOException;

import static com.atlassian.bitbucket.mesh.IncompatibleSidecarDatabaseResetter.LEGACY_DB_FILE;
import static com.atlassian.bitbucket.mesh.MeshConstants.PROFILE_SIDECAR;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class IncompatibleSidecarDatabaseResetterTest {

    @Rule
    public TemporaryFolder folder = new TemporaryFolder();

    @Mock
    private Environment environment;
    @Mock
    private StorageLayout storageLayout;
    private IncompatibleSidecarDatabaseResetter underTest;

    @Test
    public void testCompatibleH2DatabaseFile() throws IOException {
        when(environment.acceptsProfiles(Profiles.of(PROFILE_SIDECAR))).thenReturn(true);
        when(storageLayout.getHomeDir()).thenReturn(folder.getRoot().toPath());
        underTest = new IncompatibleSidecarDatabaseResetter(environment, storageLayout);
        File dbFile = new File(folder.getRoot(), "mesh.mv.db");
        FileUtils.copyFile(new ClassPathResource("h2/mesh-2.2.x.mv.db").getFile(), dbFile);

        underTest.mayReset();

        assertTrue(dbFile.exists());
        assertFalse(new File(folder.getRoot(), LEGACY_DB_FILE).exists());
    }

    @Test
    public void testIncompatibleH2DatabaseFileForNonSidecar_1_X() throws IOException {
        when(environment.acceptsProfiles(Profiles.of(PROFILE_SIDECAR))).thenReturn(false);
        underTest = new IncompatibleSidecarDatabaseResetter(environment, storageLayout);
        File dbFile = new File(folder.getRoot(), "mesh.mv.db");
        FileUtils.copyFile(new ClassPathResource("h2/mesh-1.x.mv.db").getFile(), dbFile);

        underTest.mayReset();

        assertTrue(dbFile.exists());
        assertFalse(new File(folder.getRoot(), LEGACY_DB_FILE).exists());
    }

    @Test
    public void testIncompatibleH2DatabaseFileForNonSidecar_2_1() throws IOException {
        when(environment.acceptsProfiles(Profiles.of(PROFILE_SIDECAR))).thenReturn(false);
        underTest = new IncompatibleSidecarDatabaseResetter(environment, storageLayout);
        File dbFile = new File(folder.getRoot(), "mesh.mv.db");
        FileUtils.copyFile(new ClassPathResource("h2/mesh-2.1.x.mv.db").getFile(), dbFile);

        underTest.mayReset();

        assertTrue(dbFile.exists());
        assertFalse(new File(folder.getRoot(), LEGACY_DB_FILE).exists());
    }

    @Test
    public void testIncompatibleH2DatabaseFileForSidecar_1_X() throws IOException {
        when(storageLayout.getHomeDir()).thenReturn(folder.getRoot().toPath());
        when(environment.acceptsProfiles(Profiles.of(PROFILE_SIDECAR))).thenReturn(true);
        underTest = new IncompatibleSidecarDatabaseResetter(environment, storageLayout);
        File dbFile = new File(folder.getRoot(), "mesh.mv.db");
        FileUtils.copyFile(new ClassPathResource("h2/mesh-1.x.mv.db").getFile(), dbFile);

        underTest.mayReset();

        assertFalse(dbFile.exists());
        assertTrue(new File(folder.getRoot(), LEGACY_DB_FILE).exists());
    }

    @Test
    public void testIncompatibleH2DatabaseFileForSidecar_2_1() throws IOException {
        when(storageLayout.getHomeDir()).thenReturn(folder.getRoot().toPath());
        when(environment.acceptsProfiles(Profiles.of(PROFILE_SIDECAR))).thenReturn(true);
        underTest = new IncompatibleSidecarDatabaseResetter(environment, storageLayout);
        File dbFile = new File(folder.getRoot(), "mesh.mv.db");
        FileUtils.copyFile(new ClassPathResource("h2/mesh-2.1.x.mv.db").getFile(), dbFile);

        underTest.mayReset();

        assertFalse(dbFile.exists());
        assertTrue(new File(folder.getRoot(), LEGACY_DB_FILE).exists());
    }

    @Test
    public void testIncompatibleH2DatabaseFileNotResetWhenLegacyFilePresent() throws IOException {
        when(storageLayout.getHomeDir()).thenReturn(folder.getRoot().toPath());
        when(environment.acceptsProfiles(Profiles.of(PROFILE_SIDECAR))).thenReturn(true);
        underTest = new IncompatibleSidecarDatabaseResetter(environment, storageLayout);
        File dbFile = new File(folder.getRoot(), "mesh.mv.db");
        FileUtils.copyFile(new ClassPathResource("h2/mesh-1.x.mv.db").getFile(), dbFile);

        underTest.mayReset();
        FileUtils.copyFile(new ClassPathResource("h2/mesh-1.x.mv.db").getFile(), dbFile);
        underTest.mayReset();

        assertTrue(dbFile.exists());
    }
}