package vassistent.service;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import vassistent.model.AppState;
import vassistent.model.ProblemLevel;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

/**
 * Unit tests for {@link EvaluationService}.
 */
@ExtendWith(MockitoExtension.class)
class EvaluationServiceTest {

    @Mock
    private StatisticsService statisticsService;

    @Mock
    private AnimationFileService animationFileService;

    private AppState appState;
    private EvaluationService evaluationService;

    /**
     * Creates the service under test with mocked dependencies.
     */
    @BeforeEach
    void setUp() {
        appState = new AppState();
        evaluationService = new EvaluationService(
                statisticsService,
                appState,
                animationFileService
        );
    }

    /**
     * Verifies threshold mapping and animation side-effect for multiple ratio values.
     *
     * @param ratio ratio returned by statistics service
     * @param expectedLevel expected mapped problem level name
     */
    @ParameterizedTest
    @CsvSource({
            "0.00, NONE",
            "0.49, NONE",
            "0.50, WARNING",
            "0.79, WARNING",
            "0.80, HIGH",
            "0.89, HIGH",
            "0.90, DISASTER",
            "1.00, DISASTER"
    })
    void evaluate_mapsThresholdsAndWritesAnimation(double ratio, String expectedLevel) {
        ProblemLevel level = ProblemLevel.valueOf(expectedLevel);
        when(statisticsService.getRatio(20)).thenReturn(ratio);

        evaluationService.evaluate();

        assertEquals(level, appState.getProblemLevel());
        verify(animationFileService).wirteAnimationState(level);
    }

    /**
     * Verifies that evaluation always queries the ratio with a fixed window size of 20.
     */
    @Test
    void evaluate_usesFixedRatioWindow() {
        when(statisticsService.getRatio(20)).thenReturn(0.1);

        evaluationService.evaluate();

        verify(statisticsService).getRatio(20);
    }
}
