package com.atlassian.bitbucket.mesh.git.builder;

import com.atlassian.bitbucket.mesh.AbstractWiredTest;
import com.atlassian.bitbucket.mesh.config.ProcessConfig;
import com.atlassian.bitbucket.mesh.git.GitQuarantineRegistry;
import com.atlassian.bitbucket.mesh.git.binary.GitBinary;
import com.atlassian.bitbucket.mesh.layout.StorageLayout;
import com.atlassian.bitbucket.mesh.process.ProcessCreator;
import com.atlassian.bitbucket.mesh.process.ProcessParameters;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.Instant;

import static org.mockito.Mockito.verify;

public class DefaultGitProcessBuilderDeadlineTest extends AbstractWiredTest {

    @Resource
    private GitBinary binary;
    @Captor
    private ArgumentCaptor<ProcessParameters<?>> captor;
    @Mock
    private ProcessConfig processConfig;
    @Mock
    private ProcessCreator processCreator;
    @Mock
    private GitQuarantineRegistry quarantineRegistry;
    @Resource
    private StorageLayout storageLayout;

    @Test
    public void testWithDeadlineSet() {
        builder().gc()
                .withDeadline(Instant.now().plusSeconds(10))
                .build()
                .run();

        verify(processCreator).run(captor.capture());

        Duration duration = captor.getValue().getExecutionInterval();
        assertNotNull(duration);
        // allow 50ms difference because of the time between configuring and building
        assertEquals(10000.0, duration.toMillis(), 50.0);
    }

    @Test
    public void testWithDeadlineSetAfterExecutionInterval() {
        builder().gc()
                .withDeadline(Instant.now().plusSeconds(20L))
                .withExecutionInterval(Duration.ofSeconds(10L))
                .build()
                .run();

        verify(processCreator).run(captor.capture());

        Duration duration = captor.getValue().getExecutionInterval();
        assertNotNull(duration);
        assertEquals(10L, duration.getSeconds());
    }

    @Test
    public void testWithDeadlineSetBeforeExecutionInterval() {
        builder().gc()
                .withDeadline(Instant.now().plusSeconds(10L))
                .withExecutionInterval(Duration.ofSeconds(20L))
                .build()
                .run();

        verify(processCreator).run(captor.capture());

        Duration duration = captor.getValue().getExecutionInterval();
        assertNotNull(duration);
        // allow 50ms difference because of the time between configuring and building
        assertEquals(10000.0, duration.toMillis(), 50.0);
    }

    @Test
    public void testWithExecutionIntervalSet() {
        builder().gc()
                .withExecutionInterval(Duration.ofSeconds(10L))
                .build()
                .run();

        verify(processCreator).run(captor.capture());

        Duration duration = captor.getValue().getExecutionInterval();
        assertNotNull(duration);
        assertEquals(10L, duration.getSeconds());
    }

    @Test
    public void testWithoutDeadlineOrExecutionIntervalSet() {
        builder().gc().build().run();

        verify(processCreator).run(captor.capture());

        assertNull(captor.getValue().getExecutionInterval());
    }

    private DefaultGitProcessBuilder builder() {
        return new DefaultGitProcessBuilder(binary, processConfig, processCreator,
                quarantineRegistry, storageLayout, null);
    }
}
