"""Query pattern abstractions for CQRS.

This module provides base classes and protocols for implementing
query use cases in CQRS architecture.
"""

from abc import ABC, abstractmethod
from typing import Any, Generic, TypeVar

from spakky.core.common.mutability import immutable


@immutable
class AbstractQuery(ABC):
    """Base class for query DTOs.

    Queries represent intent to read system state without modification.
    """

    ...


QueryT_contra = TypeVar("QueryT_contra", bound=AbstractQuery, contravariant=True)
"""Contravariant type variable for query types."""

ResultT_co = TypeVar("ResultT_co", bound=Any, covariant=True)
"""Covariant type variable for result types."""


class IQueryUseCase(ABC, Generic[QueryT_contra, ResultT_co]):
    """Protocol for synchronous query use cases."""

    @abstractmethod
    def run(self, query: QueryT_contra) -> ResultT_co:
        """Execute query and return result.

        Args:
            query: The query to execute.

        Returns:
            Query result.
        """
        ...


class IAsyncQueryUseCase(ABC, Generic[QueryT_contra, ResultT_co]):
    """Protocol for asynchronous query use cases."""

    @abstractmethod
    async def run(self, query: QueryT_contra) -> ResultT_co:  # pyrefly: ignore
        """Execute query asynchronously and return result.

        Args:
            query: The query to execute.

        Returns:
            Query result.
        """
        ...
