"""Screenshot capture and analysis for AiCippy CLI.

Cross-platform screenshot capture with automatic analysis via the AI agent.
Supports macOS (screencapture), Linux (scrot/gnome-screenshot), Windows (PowerShell).
"""

from __future__ import annotations

import platform
import shutil
import subprocess
from datetime import datetime
from pathlib import Path
from typing import Final

from aicippy.utils.logging import get_logger

logger = get_logger(__name__)

# Screenshot output directory (relative to working directory)
SCREENSHOTS_FOLDER: Final[str] = "screenshots"
DEFAULT_TIMEOUT: Final[int] = 30


def _capture_macos(output_path: Path, region: bool, window: bool) -> bool:
    """Capture screenshot on macOS."""
    executable = shutil.which("screencapture")
    if not executable:
        logger.warning("screenshot_tool_missing", tool="screencapture")
        return False

    cmd = [executable]
    if region:
        cmd.append("-s")  # Interactive selection
    elif window:
        cmd.append("-w")  # Window capture
    cmd.append(str(output_path))

    try:
        result = subprocess.run(  # noqa: S603
            cmd,
            capture_output=True,
            timeout=DEFAULT_TIMEOUT,
            check=False,
        )
    except subprocess.TimeoutExpired:
        logger.warning("screenshot_timeout_macos")
        return False
    else:
        if result.returncode != 0:
            logger.warning(
                "screenshot_failed_macos",
                returncode=result.returncode,
                stderr=result.stderr.decode(),
            )
            return False
        return True


def _capture_linux(output_path: Path, region: bool) -> bool:
    """Capture screenshot on Linux using various tools."""
    for tool_name, args in [
        ("scrot", ["-s"] if region else []),
        ("gnome-screenshot", ["-a"] if region else ["-f"]),
        ("import", [] if region else ["-window", "root"]),
    ]:
        executable = shutil.which(tool_name)
        if not executable:
            continue

        cmd = [executable, *args, str(output_path)]
        try:
            result = subprocess.run(  # noqa: S603
                cmd,
                capture_output=True,
                timeout=DEFAULT_TIMEOUT,
                check=False,
            )
            if result.returncode == 0:
                return True
        except (FileNotFoundError, subprocess.TimeoutExpired):
            continue

    logger.warning("screenshot_failed_linux_no_tool")
    return False


def _capture_windows(output_path: Path) -> bool:
    """Capture screenshot on Windows using PowerShell."""
    executable = shutil.which("powershell")
    if not executable:
        logger.warning("screenshot_tool_missing", tool="powershell")
        return False

    ps_script = f"""
Add-Type -AssemblyName System.Windows.Forms
$screen = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds
$bitmap = New-Object System.Drawing.Bitmap($screen.Width, $screen.Height)
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
$graphics.CopyFromScreen($screen.Location, [System.Drawing.Point]::Empty, $screen.Size)
$bitmap.Save('{output_path}')
$graphics.Dispose()
$bitmap.Dispose()
"""
    try:
        result = subprocess.run(  # noqa: S603
            [executable, "-Command", ps_script],
            capture_output=True,
            timeout=DEFAULT_TIMEOUT,
            check=False,
        )
    except subprocess.TimeoutExpired:
        logger.warning("screenshot_timeout_windows")
        return False
    else:
        if result.returncode != 0:
            logger.warning(
                "screenshot_failed_windows",
                returncode=result.returncode,
            )
            return False
        return True


def capture_screenshot(
    output_dir: Path | None = None,
    region: bool = False,
    window: bool = False,
) -> Path | None:
    """Capture a screenshot using OS-native tools.

    Args:
        output_dir: Directory to save screenshot. Defaults to cwd/screenshots/.
        region: If True, capture a selected region (macOS/Linux only).
        window: If True, capture the focused window (macOS only).

    Returns:
        Path to the saved screenshot file, or None if capture failed.

    """
    if output_dir is None:
        output_dir = Path.cwd() / SCREENSHOTS_FOLDER

    output_dir.mkdir(parents=True, exist_ok=True)

    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    filename = f"screenshot_{timestamp}.png"
    output_path = output_dir / filename

    system = platform.system().lower()
    success = False

    if system == "darwin":
        success = _capture_macos(output_path, region, window)
    elif system == "linux":
        success = _capture_linux(output_path, region)
    elif system == "windows":
        success = _capture_windows(output_path)
    else:
        logger.warning("screenshot_unsupported_platform", system=system)
        return None

    if success and output_path.exists() and output_path.stat().st_size > 0:
        logger.info(
            "screenshot_captured",
            path=str(output_path),
            size=output_path.stat().st_size,
        )
        return output_path

    if success:
        logger.warning("screenshot_file_empty_or_missing", path=str(output_path))
    return None


def get_screenshot_tools() -> list[str]:
    """Return list of available screenshot tools on this system."""
    system = platform.system().lower()
    tools: list[str] = []

    if system == "darwin":
        tools.append("screencapture (macOS built-in)")
    elif system == "linux":
        for tool in ["scrot", "gnome-screenshot", "import"]:
            executable = shutil.which(tool)
            if not executable:
                continue
            try:
                result = subprocess.run(  # noqa: S603
                    [executable, "--version"],
                    capture_output=True,
                    timeout=5,
                    check=False,
                )
            except (FileNotFoundError, subprocess.TimeoutExpired):
                continue
            else:
                if result.returncode == 0:
                    tools.append(tool)
    elif system == "windows":
        tools.append("PowerShell (.NET System.Windows.Forms)")

    return tools
