package it.com.atlassian.stash.admin;

import com.atlassian.bitbucket.test.LicenseTestHelper;
import com.atlassian.bitbucket.test.ProductTopology;
import com.atlassian.bitbucket.test.ProductTopologyAdapter;
import com.atlassian.webdriver.bitbucket.page.LicenseEditPage;
import com.atlassian.webdriver.bitbucket.page.LicensePage;
import com.atlassian.webdriver.bitbucket.page.ProjectListPage;
import com.atlassian.webdriver.bitbucket.page.admin.AdminHomePage;
import com.atlassian.webdriver.bitbucket.page.admin.ServerSettingsPage;
import it.com.atlassian.stash.BaseBrowserFuncTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.Collection;

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;

public class LicenseTest extends BaseBrowserFuncTest {

    private String originalLicense;

    @Before
    public void setup() {
        originalLicense = LicenseTestHelper.getLicense();
    }

    @After
    public void tearDown() {
        LicenseTestHelper.setLicense(originalLicense);
    }

    @Test
    public void testViewAndEditLicense() {
        //Login and gather original values from the license page
        LicensePage licensePage = loginAsAdmin(LicensePage.class);
        String originalUserLimit = licensePage.getUserLimit();
        String originalLicensee = licensePage.getLicensee();
        assertNotSaved(licensePage);

        //Visit the edit page, then cancel and ensure nothing was saved
        LicenseEditPage editPage = licensePage.edit();
        licensePage = editPage.cancel();
        assertNotSaved(licensePage);

        //Attempt to set an invalid license and ensure it fails
        editPage = licensePage.edit();
        editPage.setLicense("invalidlicense");
        editPage = editPage.saveUnsuccessfully();
        assertEquals("The provided license is not valid and cannot be used.", editPage.getLicenseError());

        //Replace the existing license with a single-user test license and ensure it works
        editPage.setLicense(LicenseTestHelper.SINGLE_USER_LICENSE.get());
        licensePage = editPage.saveSuccessfully();
        assertSaved(licensePage);
        assertEquals("1", licensePage.getUserLimit());
        assertEquals("Single user license for testing", licensePage.getLicenseDescription());
        assertEquals("Stash Func Tests", licensePage.getLicensee());

        LicensePage finalLicensePage = licensePage;
        ProductTopology.get().accept(new ProductTopologyAdapter<Void>() {
            @Override
            public Void visitStashClusterPair() {
                assertEquals("Available", finalLicensePage.getClustering());
                return null;
            }
        });

        assertNotNull(licensePage.getOverLimitError());
        assertNull(licensePage.getExpiredEvalError());
        assertNull(licensePage.getEvalWarning());
        assertNull(licensePage.getMaintenanceExpiredError());

        //Restore the original license and ensure the original details match
        editPage = licensePage.edit();
        editPage.setLicense(originalLicense);
        licensePage = editPage.saveSuccessfully();
        assertSaved(licensePage);
        assertEquals(originalUserLimit, licensePage.getUserLimit());
        assertEquals(originalLicensee, licensePage.getLicensee());
    }

    @Test
    public void testLicenseBannerIsDisplayedToAllUsers() {
        LicensePage licensePage = loginAsAdmin(LicensePage.class);

        LicenseEditPage editPage = licensePage.edit();
        editPage.setLicense(LicenseTestHelper.SINGLE_USER_LICENSE.get());
        licensePage = editPage.saveSuccessfully();
        assertSaved(licensePage);

        ProjectListPage projectListPage = loginAsRegularUser(ProjectListPage.class);

        Collection<String> warnings = projectListPage.getAuiBannerMessages();
        assertTrue(!warnings.isEmpty()); //License is over limit

        assertThat(warnings, hasItem(
                allOf(
                    startsWith("You have more users than your license allows. Pushing will be disabled in"),
                    endsWith("hours. Purchase a license today")
                )
        ));
    }

    @Test
    public void testLicenseBannerIsStackedWithBaseUrlBanner() {
        AdminHomePage adminPage = loginAsAdmin(AdminHomePage.class);
        ServerSettingsPage serverSettings = adminPage.gotoServerSettingsPage();
        String baseUrl = serverSettings.getBaseUrl();

        try {
            //Different base URL from hosting URL gives a warning banner
            serverSettings.setBaseUrl(baseUrl + "blah").clickSave();

            LicensePage licensePage = adminPage.gotoLicensePage();

            LicenseEditPage editPage = licensePage.edit();
            editPage.setLicense(LicenseTestHelper.SINGLE_USER_LICENSE.get());
            licensePage = editPage.saveSuccessfully();

            Collection<String> warnings = licensePage.getAuiBannerMessages();
            assertTrue(warnings.size() > 1); //License is over limit, DB invalid

            assertThat(warnings, hasItem(
                    allOf(
                        startsWith("You have more users than your license allows. Pushing will be disabled in"),
                        endsWith("hours. Purchase a license today")
                    )
            ));
        } finally {
            BITBUCKET.visit(ServerSettingsPage.class).setBaseUrl(baseUrl).clickSave();
        }
    }

    private static void assertNotSaved(LicensePage licensePage) {
        assertFalse("Initial page should not have an 'updated' message", licensePage.isUpdated());
    }

    private static void assertSaved(LicensePage licensePage) {
        assertTrue("Edited page should have an 'updated' message", licensePage.isUpdated());
    }
}
