# qa-copilot/visual_regression.py
"""
Visual regression testing via screenshot comparison (#15).

Compares current screenshots against saved baselines using pixel-level diff.
Generates highlighted diff images showing changed regions.

Requires: Pillow (pip install Pillow)
"""
from __future__ import annotations

import os
from pathlib import Path

try:
    from PIL import Image, ImageChops
    _HAS_PILLOW = True
except ImportError:
    _HAS_PILLOW = False

SCRIPT_DIR = Path(__file__).parent
_DEFAULT_BASELINES = str(SCRIPT_DIR / "baselines")


def save_baseline(name: str, image: "Image.Image", baselines_dir: str = _DEFAULT_BASELINES) -> str:
    os.makedirs(baselines_dir, exist_ok=True)
    path = os.path.join(baselines_dir, f"{name}.png")
    image.save(path)
    return path


def compare(name: str, current: "Image.Image", threshold: float = 0.5, baselines_dir: str = _DEFAULT_BASELINES) -> dict:
    if not _HAS_PILLOW:
        return {"error": "Pillow not installed (pip install Pillow)"}
    baseline_path = os.path.join(baselines_dir, f"{name}.png")
    if not os.path.exists(baseline_path):
        return {"error": f"No baseline found for '{name}'. Save one first."}
    baseline = Image.open(baseline_path).convert("RGB")
    if current.size != baseline.size:
        current = current.resize(baseline.size, Image.LANCZOS)
    current_rgb = current.convert("RGB")
    diff = ImageChops.difference(baseline, current_rgb)
    diff_gray = diff.convert("L")
    pixels = list(diff_gray.getdata())
    total_pixels = len(pixels)
    changed_pixels = sum(1 for p in pixels if p > 10)
    diff_percent = round((changed_pixels / total_pixels) * 100, 2) if total_pixels else 0.0
    match = diff_percent <= threshold
    diff_dir = os.path.join(baselines_dir, "diffs")
    os.makedirs(diff_dir, exist_ok=True)
    diff_path = os.path.join(diff_dir, f"{name}_diff.png")
    highlight = current_rgb.copy()
    highlight_pixels = highlight.load()
    diff_pixels = diff_gray.load()
    w, h = highlight.size
    for x in range(w):
        for y in range(h):
            if diff_pixels[x, y] > 10:
                highlight_pixels[x, y] = (255, 0, 0)
    highlight.save(diff_path)
    return {"match": match, "diff_percent": diff_percent, "diff_path": diff_path, "baseline_path": baseline_path}


def compare_files(name: str, current_path: str, threshold: float = 0.5, baselines_dir: str = _DEFAULT_BASELINES) -> dict:
    if not _HAS_PILLOW:
        return {"error": "Pillow not installed"}
    if not os.path.exists(current_path):
        return {"error": f"Screenshot not found: {current_path}"}
    current = Image.open(current_path)
    return compare(name, current, threshold=threshold, baselines_dir=baselines_dir)
