"""Web page monitoring functionality."""

import asyncio
import hashlib
import json
from datetime import datetime
from pathlib import Path
from typing import Callable, Optional

from .browser import Browser


class PageMonitor:
    """
    Monitor web pages for changes.
    
    Usage:
        monitor = PageMonitor()
        await monitor.watch(
            url="https://example.com",
            selector=".price",
            interval=60,
            on_change=lambda old, new: print(f"Price changed: {old} -> {new}")
        )
    """
    
    def __init__(self, headless: bool = True, model: Optional[str] = None):
        self.headless = headless
        self.model = model
        self._running = False
        self._history: dict[str, list] = {}
    
    async def watch(
        self,
        url: str,
        selector: Optional[str] = None,
        interval: int = 60,
        on_change: Optional[Callable[[str, str], None]] = None,
        on_check: Optional[Callable[[str], None]] = None,
        max_checks: Optional[int] = None,
    ) -> None:
        """
        Watch a page for changes.
        
        Args:
            url: URL to monitor
            selector: CSS selector to monitor (if None, monitors whole page)
            interval: Check interval in seconds
            on_change: Callback when change detected (old_value, new_value)
            on_check: Callback on each check (current_value)
            max_checks: Maximum number of checks (None for infinite)
        """
        self._running = True
        check_count = 0
        last_hash: Optional[str] = None
        last_value: Optional[str] = None
        
        print(f"🔍 开始监控: {url}")
        print(f"   检查间隔: {interval} 秒")
        if selector:
            print(f"   监控元素: {selector}")
        else:
            print(f"   监控: 整个页面")
        print(f"   最大检查次数: {max_checks if max_checks else '无限'}")
        print("-" * 60)
        
        while self._running:
            check_count += 1
            timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            
            try:
                async with Browser(headless=self.headless, model=self.model) as browser:
                    await browser.goto(url)
                    
                    # Get current value
                    if selector:
                        current_value = await browser.extract(selector)
                    else:
                        # Get page content hash
                        content = await browser._page.content()
                        current_value = hashlib.md5(content.encode()).hexdigest()[:16]
                    
                    # Calculate hash for comparison
                    current_hash = hashlib.md5(str(current_value).encode()).hexdigest()
                    
                    # Call on_check callback
                    if on_check:
                        on_check(current_value)
                    
                    # Check for changes
                    if last_hash is not None and current_hash != last_hash:
                        print(f"\n🔄 [{timestamp}] 检测到变化!")
                        print(f"   旧值: {last_value[:100] if last_value else 'N/A'}...")
                        print(f"   新值: {current_value[:100] if current_value else 'N/A'}...")
                        
                        # Save screenshot
                        result = await browser.screenshot()
                        print(f"   📸 截图: {result['path']}")
                        
                        # Call on_change callback
                        if on_change:
                            on_change(last_value or "", current_value or "")
                        
                        # Record change
                        self._record_change(url, last_value, current_value, result['path'])
                    else:
                        print(f"✅ [{timestamp}] 检查 #{check_count}: 无变化")
                    
                    last_hash = current_hash
                    last_value = current_value
                    
            except Exception as e:
                print(f"❌ [{timestamp}] 检查出错: {e}")
            
            # Check if max checks reached
            if max_checks and check_count >= max_checks:
                print(f"\n⏹️  已达到最大检查次数 ({max_checks})")
                break
            
            # Wait for next check
            if self._running:
                await asyncio.sleep(interval)
        
        print("\n⏹️  监控已停止")
    
    def stop(self) -> None:
        """Stop monitoring."""
        self._running = False
        print("⏹️  正在停止监控...")
    
    def _record_change(
        self,
        url: str,
        old_value: str,
        new_value: str,
        screenshot_path: str,
    ) -> None:
        """Record a change to history."""
        if url not in self._history:
            self._history[url] = []
        
        self._history[url].append({
            "timestamp": datetime.now().isoformat(),
            "old_value": old_value[:500] if old_value else "",
            "new_value": new_value[:500] if new_value else "",
            "screenshot": screenshot_path,
        })
    
    def save_history(self, filepath: Optional[str] = None) -> str:
        """
        Save monitoring history to file.
        
        Args:
            filepath: Output file path (default: project folder)
            
        Returns:
            Path to saved file
        """
        if filepath is None:
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            filepath = f"/mnt/fnos/SurfAI/项目文件/导出数据/monitor_history_{timestamp}.json"
        
        path = Path(filepath)
        path.parent.mkdir(parents=True, exist_ok=True)
        
        with open(path, "w", encoding="utf-8") as f:
            json.dump(self._history, f, ensure_ascii=False, indent=2)
        
        print(f"💾 历史记录已保存: {path}")
        return str(path)
    
    def get_history(self, url: Optional[str] = None) -> list:
        """
        Get monitoring history.
        
        Args:
            url: Specific URL (if None, returns all history)
            
        Returns:
            List of change records
        """
        if url:
            return self._history.get(url, [])
        
        # Return all history flattened
        all_history = []
        for url, changes in self._history.items():
            for change in changes:
                all_history.append({"url": url, **change})
        
        return sorted(all_history, key=lambda x: x["timestamp"])


async def monitor_page(
    url: str,
    selector: Optional[str] = None,
    interval: int = 60,
    duration: Optional[int] = None,
) -> None:
    """
    Simple wrapper to monitor a page for a duration.
    
    Args:
        url: URL to monitor
        selector: CSS selector to monitor
        interval: Check interval in seconds
        duration: Total duration in seconds (None for infinite)
    """
    monitor = PageMonitor()
    
    # Set max checks if duration specified
    max_checks = None
    if duration:
        max_checks = duration // interval
    
    try:
        await monitor.watch(
            url=url,
            selector=selector,
            interval=interval,
            max_checks=max_checks,
        )
    except KeyboardInterrupt:
        print("\n\n⏹️  用户中断监控")
    finally:
        monitor.save_history()
