"""File filtering operations."""

from __future__ import annotations

from pathlib import Path
from typing import Any

from cascade_fm.core.cache.cache_none import NoCacheMixin
from cascade_fm.operations.base import Operation


class FilterExtension(NoCacheMixin, Operation):
    """Filter files by extension."""

    @property
    def name(self) -> str:
        """Unique identifier for this operation."""
        return "filter_extension"

    @property
    def label(self) -> str:
        """Human-readable label shown in UI."""
        return "Filter by Extension"

    @property
    def description(self) -> str:
        """Brief description of what this operation does."""
        return "Keep only files with specific extensions"

    def _can_execute_without_params(self) -> bool:
        """Filter can execute without params (pass-through mode)."""
        return True

    def _execute_impl(self, files: list[Path], **params: Any) -> list[Path]:
        """Filter files by extension.

        Args:
            files: List of input file paths.
            **params: May contain 'extensions' - list of extensions to keep
                     (e.g., ['.jpg', '.png'] or ['jpg', 'png'])
                     If empty, passes through all files.

        Returns:
            List of filtered file paths.
        """
        extensions = params.get("extensions", [])

        # Empty extensions = pass through all files
        if not extensions:
            return files

        # Normalize extensions (ensure leading dot)
        normalized = []
        for ext in extensions:
            ext = ext.strip()
            if not ext:
                continue
            if not ext.startswith("."):
                ext = f".{ext}"
            normalized.append(ext.lower())

        if not normalized:
            return files  # No valid extensions = pass through

        # Filter files
        filtered = []
        for file_path in files:
            file_ext = file_path.suffix.lower()
            if file_ext in normalized:
                filtered.append(file_path)

        return filtered

    def validate_params(self, **params: Any) -> tuple[bool, str | None]:
        """Validate parameters.

        Args:
            **params: May contain 'extensions' as list of strings.

        Returns:
            Tuple of (is_valid, error_message).
        """
        extensions = params.get("extensions")

        # Empty params is valid (pass-through mode)
        if not extensions:
            return True, None

        if not isinstance(extensions, list):
            return False, "extensions must be a list"

        for ext in extensions:
            if not isinstance(ext, str):
                return False, f"Invalid extension type: {type(ext).__name__}"

        return True, None


class FilterName(NoCacheMixin, Operation):
    """Filter files by name pattern."""

    @property
    def name(self) -> str:
        """Unique identifier for this operation."""
        return "filter_name"

    @property
    def label(self) -> str:
        """Human-readable label shown in UI."""
        return "Filter by Name"

    @property
    def description(self) -> str:
        """Brief description of what this operation does."""
        return "Keep only files matching a name pattern"

    def _can_execute_without_params(self) -> bool:
        """Filter can execute without params (pass-through mode)."""
        return True

    def _execute_impl(self, files: list[Path], **params: Any) -> list[Path]:
        """Filter files by name pattern.

        Args:
            files: List of input file paths.
            **params: May contain 'pattern' - glob pattern to match
                     If empty, passes through all files.

        Returns:
            List of filtered file paths.
        """
        from fnmatch import fnmatch

        pattern = params.get("pattern", "")

        # Empty pattern = pass through all files
        if not pattern:
            return files

        # Filter files
        filtered = []
        for file_path in files:
            if fnmatch(file_path.name, pattern):
                filtered.append(file_path)

        return filtered

    def validate_params(self, **params: Any) -> tuple[bool, str | None]:
        """Validate parameters.

        Args:
            **params: May contain 'pattern' as string.

        Returns:
            Tuple of (is_valid, error_message).
        """
        pattern = params.get("pattern")

        # Empty params is valid (pass-through mode)
        if not pattern:
            return True, None

        if not isinstance(pattern, str):
            return False, "pattern must be a string"

        return True, None
