package it.com.atlassian.stash.audit;

import com.atlassian.bitbucket.test.DefaultFuncTestData;
import com.atlassian.bitbucket.test.RefRestrictionTestHelper;
import com.atlassian.webdriver.bitbucket.page.admin.repo.AuditPage;
import it.com.atlassian.stash.BaseBrowserFuncTest;
import org.hamcrest.Matcher;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import org.junit.rules.TestRule;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import static com.atlassian.bitbucket.test.TestRuleOrderingSyntax.outerRules;
import static com.atlassian.webdriver.bitbucket.page.admin.repo.AuditPage.AuditRow;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.hasSize;
import static org.junit.Assert.*;

public class AuditPageTest extends BaseBrowserFuncTest {

    private static final String PROJECT_KEY = "audit_project";
    private static final String REPO_KEY = "audit_repo";

    // Intentionally not annotated with @Rule as it is referred in the RuleChain below
    private RefRestrictionTestHelper restrictedRefs = new RefRestrictionTestHelper(PROJECT_KEY, REPO_KEY);

    @Override
    protected List<TestRule> getRetryRuleChain() {
        return outerRules(super.getRetryRuleChain()).
               around(restrictedRefs);
    }

    @Before
    public void onSetup() {
        testContext.project(PROJECT_KEY);
        testContext.repository(PROJECT_KEY, REPO_KEY);
    }

    @Test
    public void testAuditingTable() {
        AuditPage auditPage = loginAsAdmin(AuditPage.class, PROJECT_KEY, REPO_KEY);
        // Ideally a separate test - but save having to launch the browser twice
        restrictedRefs.createRestrictedRef(RefRestrictionTestHelper.RefMatcherType.PATTERN, "a/b", RefRestrictionTestHelper.RestrictionType.READ_ONLY, Arrays.asList(DefaultFuncTestData.getAdminUser()), Arrays.<String>asList());
        auditPage = BITBUCKET.visit(AuditPage.class, PROJECT_KEY, REPO_KEY);
        assertFalse(auditPage.isEmpty());
        Iterator<AuditRow> rows = auditPage.getEntries().iterator();
        checkRow(rows.next(), DefaultFuncTestData.getAdminUser(), "RefRestrictionAddedEvent", Matchers.containsString("a/b"));
    }

    @Test
    public void testAuditingTablePaging() {
        for (int i = 0; i < 50; i++) {
            restrictedRefs.createRestrictedRef(RefRestrictionTestHelper.RefMatcherType.PATTERN, "a/" + i, RefRestrictionTestHelper.RestrictionType.READ_ONLY, Arrays.asList(DefaultFuncTestData.getAdminUser()), Arrays.<String>asList());
        }
        AuditPage auditPage = loginAsAdmin(AuditPage.class, PROJECT_KEY, REPO_KEY);
        int firstPageSize = auditPage.getEntries().size();
        assertEquals(25, firstPageSize);
        auditPage.scrollUntilNoMoreResults();
        assertThat(auditPage.getEntries(), hasSize(greaterThan(firstPageSize)));
    }

    private void checkRow(AuditRow next, String username, String action, Matcher<String> details) {
        assertEquals(username, next.getUser().getUsername());
        assertEquals(action, next.getAction());
        assertThat(next.getDetails(), details);
    }
}
