"""
Unit test: Humanized Scroll Speed Variations.

Validates that different scroll behavior branches produce
gestures with different timing characteristics.
"""

from unittest.mock import MagicMock, patch

import pytest

from GramAddict.core.physics.biomechanics import PhysicsBody
from GramAddict.core.physics.sendevent_injector import SendEventInjector


@pytest.fixture(autouse=True)
def reset_singletons():
    PhysicsBody.reset()
    SendEventInjector.reset()
    yield
    PhysicsBody.reset()
    SendEventInjector.reset()


@patch("GramAddict.core.physics.humanized_input.SendEventInjector")
def test_humanized_scroll_speeds(MockInjector):
    mock_injector = MagicMock()
    MockInjector.get_instance.return_value = mock_injector

    device = MagicMock()
    device.get_info.return_value = {"displayHeight": 2400, "displayWidth": 1080}

    from GramAddict.core.physics.humanized_input import humanized_scroll

    # First scroll
    humanized_scroll(device)
    assert mock_injector.inject_gesture.called

    # Verify gesture data was passed correctly
    args = mock_injector.inject_gesture.call_args
    points = args[0][0]
    timing = args[0][1]

    # Points must be valid (x, y, pressure) tuples
    for p in points:
        assert len(p) == 3, f"Expected (x, y, pressure), got {p}"

    # Timing intervals must all be positive
    for t in timing:
        assert t > 0, f"Timing interval must be positive, got {t}"


@patch("GramAddict.core.physics.humanized_input.SendEventInjector")
def test_humanized_scroll_skip_is_strictly_forward(MockInjector):
    """
    Ensures that when is_skip=True (e.g. for aggressive ad skipping),
    the generated gesture is purely forward (bottom to top swipe),
    and does NOT contain backwards 'Doomscroll corrections' or
    biomechanical 'reading pauses'.
    """
    mock_injector = MagicMock()
    MockInjector.get_instance.return_value = mock_injector

    device = MagicMock()
    device.get_info.return_value = {"displayHeight": 2400, "displayWidth": 1080}

    from GramAddict.core.physics.humanized_input import humanized_scroll

    # Run multiple times to overcome randomness in play_choice / do_correction
    for _ in range(50):
        mock_injector.reset_mock()
        humanized_scroll(device, is_skip=True)

        args = mock_injector.inject_gesture.call_args
        points = args[0][0]
        timing = args[0][1]

        # In a forward scroll (bottom to top), the Y coordinate must go from a higher number to a lower number.
        start_y = points[0][1]
        end_y = points[-1][1]

        # End Y MUST be less than Start Y (meaning we scrolled down the feed, swiping finger up)
        assert end_y < start_y, f"Expected end_y ({end_y}) to be < start_y ({start_y}) for a skip."

        # Verify no long pauses (reading pause adds 0.5s to 2.0s to timing)
        for t in timing:
            assert (
                t < 500
            ), "Found a massive pause in a skip gesture, meaning a reading_pause or dwell was incorrectly inserted!"
