#!/usr/bin/env python3
"""
Scroll Page Primitive Operation

This module provides page scrolling functionality for browser automation.
Simulates human-like scrolling behavior with natural overshooting and recovery.
"""

import asyncio
import random
import time 
from typing import Dict, Any
from patchright.async_api import Page


class ScrollPage:
    """
    Scroll Page with Human-like Behavior

    Implements realistic scrolling behavior:
    - Overshoots the target distance for natural feel
    - Mouse movement during scroll
    - Slight scroll back (overshoot recovery)
    - Natural delays between actions

    Usage:
        scroller = ScrollPage()
        result = await scroller.scroll(page, distance=1000, slowmo=1000)
    """

    def __init__(self):
        """Initialize the scroll page handler."""
        print("📜 ScrollPage initialized")

    async def scroll(self, page: Page, distance: int = 1000, slowmo: int = 1000) -> Dict[str, Any]:
        """
        Scroll the page vertically by a specified distance.

        Args:
            page (Page): Playwright page to use
            distance (int): Distance in pixels to scroll down (default: 1000)
            slowmo (int): Delay in milliseconds for waiting after scroll (default: 1000)

        Returns:
            Dict containing scroll result and page information
        """
        try:
            print(f"📜 Scrolling page by {distance} pixels")

            # Overshoot for natural feel
            actual_distance = distance * random.uniform(1.1, 1.2)
            await self._human_scroll(page, actual_distance)
            await asyncio.sleep(0.5)

            # Move mouse to simulate user activity
            await page.mouse.move(random.randint(100, 300), random.randint(100, 300), steps=5)

            # Slight scroll back (overshoot recovery)
            await self._human_scroll(page, -actual_distance * random.uniform(0.1, 0.2))
            await asyncio.sleep(0.5)

            # Wait for page to stabilize
            await asyncio.sleep(slowmo / 1000)

            result = {
                "success": True,
                "scrolled_distance": actual_distance,
                "url": page.url
            }

            print(f"✅ Page scrolled by {actual_distance:.0f} pixels")
            return result

        except Exception as e:
            error_result = {
                "success": False,
                "error": str(e)
            }
            print(f"❌ Page scroll failed: {e}")
            return error_result

    async def _human_scroll(self, page: Page, distance: int) -> int:
        """
        Calculate a human-like scroll distance with overshoot.

        Args:
            distance (int): Intended scroll distance

        Returns:
            int: Adjusted scroll distance with overshoot
        """

        hd = distance // 2

        for d in range(abs(distance)):
            await page.mouse.wheel(0, 1 if distance > 0 else -1)
            # scroll speed variation
            # almost sigmoid curve
            time.sleep(0.01 + (0.02 * (1 / (1 + pow(2.71828, -((d - hd) / (hd / 10)))))))

