"""Unit tests for operation registry filtering."""

from __future__ import annotations

import zipfile
from pathlib import Path

from PIL import Image

from cascade_fm.operations.registry import (
    get_operation_group_label,
    list_hidden_operations_for_files,
    list_operations_for_files,
    list_operations_for_ui,
    operation_accepts_files,
)


def _create_image(path: Path) -> None:
    image = Image.new("RGB", size=(8, 8), color="red")
    image.save(path)


def test_operation_accepts_files_image_operation(tmp_path: Path) -> None:
    """Image operations should accept image files."""
    image_path = tmp_path / "photo.jpg"
    _create_image(image_path)

    assert operation_accepts_files("resize_image", [image_path]) is True


def test_operation_rejects_non_image_for_image_op(tmp_path: Path) -> None:
    """Image operations should reject non-image files."""
    text_path = tmp_path / "notes.txt"
    text_path.write_text("hello")

    assert operation_accepts_files("resize_image", [text_path]) is False


def test_list_operations_for_files_text_only(tmp_path: Path) -> None:
    """Text selections should exclude image-only operations."""
    text_path = tmp_path / "notes.txt"
    text_path.write_text("hello")

    operations = list_operations_for_files([text_path])

    assert "filter_extension" in operations
    assert "filter_name" in operations
    assert "rename_pattern" in operations
    assert "save_to" in operations
    assert "resize_image" not in operations
    assert "convert_image" not in operations


def test_list_operations_for_files_images_only(tmp_path: Path) -> None:
    """Image selections should include image operations."""
    image_path = tmp_path / "photo.jpg"
    _create_image(image_path)

    operations = list_operations_for_files([image_path])

    assert "filter_extension" in operations
    assert "filter_name" in operations
    assert "rename_pattern" in operations
    assert "save_to" in operations
    assert "resize_image" in operations
    assert "convert_image" in operations
    assert "strip_exif" in operations


def test_list_operations_for_files_mixed_types(tmp_path: Path) -> None:
    """Mixed file types should hide image-only operations."""
    image_path = tmp_path / "photo.jpg"
    _create_image(image_path)
    text_path = tmp_path / "notes.txt"
    text_path.write_text("hello")

    operations = list_operations_for_files([image_path, text_path])

    assert "filter_extension" in operations
    assert "filter_name" in operations
    assert "rename_pattern" in operations
    assert "save_to" in operations
    assert "resize_image" not in operations
    assert "convert_image" not in operations


def test_list_hidden_operations_for_files_text_only(tmp_path: Path) -> None:
    """Hidden list should include incompatible image-only operations."""
    text_path = tmp_path / "notes.txt"
    text_path.write_text("hello")

    hidden = list_hidden_operations_for_files([text_path])

    assert "resize_image" in hidden
    assert "convert_image" in hidden
    assert "rotate_image" in hidden
    assert "filter_extension" not in hidden
    assert "rename_pattern" not in hidden


def test_get_operation_group_label_any_files() -> None:
    """Wildcard operations should be grouped under Any Files."""
    assert get_operation_group_label("filter_extension") == "Any Files"


def test_get_operation_group_label_image_files() -> None:
    """Image-only operations should be grouped under Image Files."""
    assert get_operation_group_label("resize_image") == "Image Files"


def test_ui_operations_hide_legacy_and_show_unified_image_transform(tmp_path: Path) -> None:
    """UI operation list should hide legacy filter/granular image ops."""
    image_path = tmp_path / "photo.jpg"
    _create_image(image_path)

    operations = list_operations_for_ui([image_path])

    assert "image_transform" in operations
    assert "save_to" in operations
    assert "filter_extension" not in operations
    assert "filter_name" not in operations
    assert "resize_image" not in operations
    assert "convert_image" not in operations


def test_ui_operations_include_unarchive_for_zip(tmp_path: Path) -> None:
    """UI operation list should include unarchive for ZIP files."""
    archive = tmp_path / "sample.zip"
    with zipfile.ZipFile(archive, "w") as zf:
        zf.writestr("x.txt", "x")

    operations = list_operations_for_ui([archive])
    assert "unarchive" in operations


def test_ui_operations_include_unarchive_for_gzip_suffix(tmp_path: Path) -> None:
    """UI operation list should include unarchive for .gz files via suffix fallback."""
    archive = tmp_path / "nested_archive.gz"
    archive.write_text("payload")

    operations = list_operations_for_ui([archive])
    assert "unarchive" in operations


def test_ui_operations_hide_unarchive_without_selection() -> None:
    """UI operation list should hide unarchive when no files are selected."""
    operations = list_operations_for_ui([])
    assert "unarchive" not in operations


def test_ui_operations_hide_image_transform_without_selection() -> None:
    """UI operation list should hide image_transform when no files are selected."""
    operations = list_operations_for_ui([])
    assert "image_transform" not in operations


def test_ui_operations_include_create_archive_with_selection(tmp_path: Path) -> None:
    """UI operation list should include create_archive for selected files."""
    text_path = tmp_path / "notes.txt"
    text_path.write_text("hello")

    operations = list_operations_for_ui([text_path])
    assert "create_archive" in operations


def test_ui_operations_show_create_archive_without_selection() -> None:
    """UI operation list should show create_archive when no files are selected."""
    operations = list_operations_for_ui([])
    assert "create_archive" in operations
