"""Tests for scroll collection state and target generation."""
from __future__ import annotations

import pytest

from tools.scroll.collector import ScrollCollector


class TestNextTarget:
    def test_target_mode_distance_range(self):
        sc = ScrollCollector(mode="target", count=10, page_height=10000, viewport_height=900)
        for _ in range(20):
            result = sc.next_target(current_scrollY=2000)
            dist = abs(result["target_scrollY"] - 2000)
            assert 500 <= dist <= 3000
            assert result["direction"] in ("up", "down")

    def test_fast_mode_distance_range(self):
        sc = ScrollCollector(mode="fast", count=10, page_height=10000, viewport_height=900)
        for _ in range(20):
            result = sc.next_target(current_scrollY=5000)
            dist = abs(result["target_scrollY"] - 5000)
            assert 3000 <= dist <= 8000

    def test_precise_mode_distance_range(self):
        sc = ScrollCollector(mode="precise", count=10, page_height=10000, viewport_height=900)
        for _ in range(20):
            result = sc.next_target(current_scrollY=3000)
            dist = abs(result["target_scrollY"] - 3000)
            assert 200 <= dist <= 800

    def test_target_within_page_bounds(self):
        sc = ScrollCollector(mode="target", count=10, page_height=10000, viewport_height=900)
        result = sc.next_target(current_scrollY=1000)
        assert 0 <= result["target_scrollY"] <= 10000
        result = sc.next_target(current_scrollY=9000)
        assert 0 <= result["target_scrollY"] <= 10000

    def test_success_zone_by_mode(self):
        sc = ScrollCollector(mode="target", count=10, page_height=10000)
        assert sc.success_radius == 80
        sc2 = ScrollCollector(mode="fast", count=10, page_height=10000)
        assert sc2.success_radius == 120
        sc3 = ScrollCollector(mode="precise", count=10, page_height=10000)
        assert sc3.success_radius == 40

    def test_target_always_reachable(self):
        """Target must always be reachable: user can scroll to bring it into success zone."""
        sc = ScrollCollector(mode="target", count=10, page_height=10000, viewport_height=900)
        viewport_center = 450  # 900 / 2
        max_scroll_top = 10000 - 900  # 9100

        for current in [0, 100, 500, 2000, 5000, 8000, 9000]:
            for _ in range(10):
                result = sc.next_target(current_scrollY=current)
                target = result["target_scrollY"]
                # The scrollTop needed to bring target into viewport center
                needed_scroll = target - viewport_center + 25
                # Must be achievable (0 <= needed_scroll <= max_scroll_top)
                # With success_radius=80, there's a window, not exact match needed
                reachable_min = viewport_center - sc.success_radius
                reachable_max = max_scroll_top + viewport_center + sc.success_radius
                assert reachable_min <= target <= reachable_max, (
                    f"Target {target} not reachable from scrollY={current}"
                )
