"""Tests for RUF074 (incorrect-decorator-order)."""

from abc import abstractmethod, abstractproperty, abstractclassmethod, abstractstaticmethod
from contextlib import contextmanager, asynccontextmanager
from functools import cache, cached_property, lru_cache, wraps
import abc
import functools

# ===== Errors =====

# --- Core: abstractmethod above descriptors ---

class AbstractAboveProperty:
    @abstractmethod  # RUF074
    @property
    def foo(self): ...

class AbstractAboveClassmethod:
    @abstractmethod  # RUF074
    @classmethod
    def foo(cls): ...

class AbstractAboveStaticmethod:
    @abstractmethod  # RUF074
    @staticmethod
    def foo(): ...

# --- Core: contextmanager above classmethod ---

class ContextManagerAboveClassmethod:
    @contextmanager  # RUF074
    @classmethod
    def foo(cls): ...

class AsyncContextManagerAboveClassmethod:
    @asynccontextmanager  # RUF074
    @classmethod
    def foo(cls): ...

# --- Functools: caching decorators above descriptors ---

class CacheAboveProperty:
    @cache  # RUF074
    @property
    def foo(self): ...

class LruCacheAboveProperty:
    @lru_cache  # RUF074
    @property
    def foo(self): ...

class CacheAboveClassmethod:
    @cache  # RUF074
    @classmethod
    def foo(cls): ...

class LruCacheAboveClassmethod:
    @lru_cache  # RUF074
    @classmethod
    def foo(cls): ...

class CacheAboveCachedProperty:
    @cache  # RUF074
    @cached_property
    def foo(self): ...

class LruCacheAboveCachedProperty:
    @lru_cache  # RUF074
    @cached_property
    def foo(self): ...

# --- Qualified imports ---

class QualifiedAbstractAboveProperty:
    @abc.abstractmethod  # RUF074
    @property
    def foo(self): ...

class QualifiedLruCacheAboveProperty:
    @functools.lru_cache  # RUF074
    @property
    def foo(self): ...

# --- Decorator call form ---

class LruCacheCallAboveProperty:
    @lru_cache()  # RUF074
    @property
    def foo(self): ...

class LruCacheCallWithArgsAboveProperty:
    @lru_cache(maxsize=128)  # RUF074
    @property
    def foo(self): ...

# --- Multiple violations on same function (adjacent pairs only) ---

class MultipleViolations:
    @abstractmethod  # RUF074
    @property
    @contextmanager  # RUF074
    @classmethod
    def foo(cls): ...

class CachedPropertyAboveAbstractmethod:
    @cached_property  # RUF074
    @abstractmethod
    def foo(self): ...

class AbstractAbovePropertySetter:
    @property
    @abstractmethod
    def foo(self): ...

    @abstractmethod  # RUF074
    @foo.setter
    def foo(self, val): ...

class AbstractAbovePropertyDeleter:
    @property
    @abstractmethod
    def foo(self): ...

    @abstractmethod  # RUF074
    @foo.deleter
    def foo(self): ...

# ===== No errors =====

# --- Correct orderings ---

class CorrectPropertyAboveAbstractmethod:
    @property
    @abstractmethod
    def foo(self): ...

class CorrectClassmethodAboveAbstractmethod:
    @classmethod
    @abstractmethod
    def foo(cls): ...

class CorrectStaticmethodAboveAbstractmethod:
    @staticmethod
    @abstractmethod
    def foo(): ...

class CorrectContextmanagerAboveStaticmethod:
    @contextmanager
    @staticmethod
    def foo(): ...

class CorrectAsyncContextmanagerAboveStaticmethod:
    @asynccontextmanager
    @staticmethod
    def foo(): ...

class CorrectStaticmethodAboveContextmanager:
    @staticmethod
    @contextmanager
    def foo(): ...

class CorrectClassmethodAboveContextmanager:
    @classmethod
    @contextmanager
    def foo(cls): ...

class CorrectPropertyAboveCache:
    @property
    @cache
    def foo(self): ...

class CorrectPropertyAboveLruCache:
    @property
    @lru_cache
    def foo(self): ...

class CorrectAbstractmethodAboveCachedProperty:
    @abstractmethod
    @cached_property
    def foo(self): ...

# --- Non-adjacent known-bad pair (only adjacent pairs are checked) ---

class InterleavedDecorator:
    @abstractmethod
    @some_other_decorator
    @property
    def foo(self): ...

# --- Single decorators ---

class SingleAbstractmethod:
    @abstractmethod
    def foo(self): ...

class SingleProperty:
    @property
    def foo(self): ...

# --- Unrelated decorators only ---

class UnrelatedDecorators:
    @some_decorator
    @another_decorator
    def foo(self): ...

# --- Same decorator twice ---

class DuplicateDecorator:
    @abstractmethod
    @abstractmethod
    def foo(self): ...

# --- functools.wraps is not checked ---

class WrapsWithAnything:
    @wraps(some_func)
    @property
    def foo(self): ...

    @abstractmethod
    @wraps(some_func)
    def bar(self): ...

class ClassmethodAboveCachedProperty:
    @classmethod
    @cached_property
    def foo(cls): ...

class DeprecatedAbstractPropertyBelowAbstractmethod:
    @abstractmethod
    @abstractproperty
    def foo(self): ...

class DeprecatedAbstractClassmethodBelowAbstractmethod:
    @abstractmethod
    @abstractclassmethod
    def foo(cls): ...

class DeprecatedAbstractStaticmethodBelowAbstractmethod:
    @abstractmethod
    @abstractstaticmethod
    def foo(): ...

class CorrectPropertySetterAboveAbstractmethod:
    @property
    @abstractmethod
    def foo(self): ...

    @foo.setter
    @abstractmethod
    def foo(self, val): ...
