"""Continuous screen monitoring with change detection."""

from __future__ import annotations

import hashlib
import logging
import os
import platform
import subprocess
import tempfile
import time
from pathlib import Path
from typing import Any

logger = logging.getLogger(__name__)


class ContinuousScreenMonitor:
    """Real-time screen monitoring with change detection."""

    CAPTURE_INTERVAL = 5.0
    MIN_TEXT_LENGTH = 20
    MAX_CAPTURES_PER_HOUR = 200

    BLOCKED_APPS = {
        "1Password",
        "Bitwarden",
        "LastPass",
        "Keychain Access",
        "Terminal",
    }

    def __init__(self, config: dict[str, Any] | None = None):
        self._config = config or {}
        self._last_hash = ""
        self._captures_this_hour = 0
        self._hour_start = time.time()

    def capture_and_compare(self) -> dict[str, Any] | None:
        """Capture screen, compare with previous, return text payload if changed."""
        now = time.time()
        if now - self._hour_start > 3600:
            self._captures_this_hour = 0
            self._hour_start = now
        if self._captures_this_hour >= self.MAX_CAPTURES_PER_HOUR:
            return None

        window_info = self._get_active_window()
        if not window_info:
            return None

        app_name = window_info.get("app", "")
        if app_name in self.BLOCKED_APPS:
            return None
        for blocked in self._config.get("blocked_apps", []):
            if str(blocked).lower() in app_name.lower():
                return None

        screenshot_data = self._capture_screenshot()
        if not screenshot_data:
            return None

        current_hash = hashlib.md5(screenshot_data).hexdigest()
        if current_hash == self._last_hash:
            return None

        self._last_hash = current_hash
        self._captures_this_hour += 1

        ocr_text = self._ocr_screenshot(screenshot_data)
        if not ocr_text or len(ocr_text) < self.MIN_TEXT_LENGTH:
            return None

        return {
            "text": ocr_text,
            "window_title": window_info.get("title", ""),
            "app_name": app_name,
            "timestamp": int(now * 1000),
            "content_type": "screen_capture",
        }

    @staticmethod
    def _get_active_window() -> dict[str, str] | None:
        """Get active window title and app name (macOS best-effort)."""
        if platform.system() != "Darwin":
            return None
        try:
            script = '''
            tell application "System Events"
                set frontApp to first application process whose frontmost is true
                set appName to name of frontApp
                set windowTitle to ""
                try
                    set windowTitle to name of first window of frontApp
                end try
                return appName & "|" & windowTitle
            end tell
            '''
            result = subprocess.run(
                ["osascript", "-e", script],
                capture_output=True,
                text=True,
                timeout=3,
            )
            if result.returncode == 0:
                parts = result.stdout.strip().split("|", 1)
                return {
                    "app": parts[0] if parts else "",
                    "title": parts[1] if len(parts) > 1 else "",
                }
        except Exception as exc:
            logger.debug("Failed to get active window: %s", exc)
        return None

    @staticmethod
    def _capture_screenshot() -> bytes | None:
        """Capture screenshot as PNG bytes (macOS best-effort)."""
        if platform.system() != "Darwin":
            return None
        tmp_path: Path | None = None
        try:
            fd, tmp_name = tempfile.mkstemp(suffix=".png")
            os.close(fd)
            tmp_path = Path(tmp_name)
            subprocess.run(
                ["screencapture", "-x", "-t", "png", str(tmp_path)],
                capture_output=True,
                timeout=5,
            )
            if tmp_path.exists():
                data = tmp_path.read_bytes()
                return data
        except Exception as exc:
            logger.debug("Screenshot capture failed: %s", exc)
        finally:
            if tmp_path is not None:
                tmp_path.unlink(missing_ok=True)
        return None

    @staticmethod
    def _ocr_screenshot(image_data: bytes) -> str:
        """Extract text from screenshot image with optional OCR stack."""
        tmp_path: Path | None = None
        try:
            import pytesseract
            from PIL import Image

            fd, tmp_name = tempfile.mkstemp(suffix=".png")
            os.close(fd)
            tmp_path = Path(tmp_name)
            tmp_path.write_bytes(image_data)
            text = pytesseract.image_to_string(Image.open(tmp_path))
            return text.strip()
        except Exception:
            return ""
        finally:
            if tmp_path is not None:
                tmp_path.unlink(missing_ok=True)
