from django.db.models import Manager, QuerySet
from returns.io import IOResult
from returns.maybe import Maybe
from returns.result import Result

class BaseReturnsQuerySet(QuerySet):
    """Base QuerySet with list of unsafe methods."""

    UNSAFE_METHODS: list[str]

class MaybeReturnsQuerySet(BaseReturnsQuerySet):
    """A subclass that includes Maybe-returning methods."""
    def first(self, *args, **kwargs) -> Maybe: ...
    def last(self, *args, **kwargs) -> Maybe: ...

class SafeReturnsQuerySet(MaybeReturnsQuerySet):
    """A subclass that overrides unsafe methods
    to return Result instead of raising exceptions.
    """
    def get(self, *args, **kwargs) -> Result: ...
    def earliest(self, *args, **kwargs) -> Result: ...
    def latest(self, *args, **kwargs) -> Result: ...
    def create(self, *args, **kwargs) -> Result: ...
    def get_or_create(self, *args, **kwargs) -> Result: ...
    def update_or_create(self, *args, **kwargs) -> Result: ...
    def delete(self, *args, **kwargs) -> Result: ...
    def bulk_create(self, *args, **kwargs) -> Result: ...

class ImpureReturnsQuerySet(MaybeReturnsQuerySet):
    """A subclass that overrides unsafe methods
    to return IOResult instead of raising exceptions.
    """
    def get(self, *args, **kwargs) -> IOResult: ...
    def earliest(self, *args, **kwargs) -> IOResult: ...
    def latest(self, *args, **kwargs) -> IOResult: ...
    def create(self, *args, **kwargs) -> IOResult: ...
    def get_or_create(self, *args, **kwargs) -> IOResult: ...
    def update_or_create(self, *args, **kwargs) -> IOResult: ...
    def delete(self, *args, **kwargs) -> IOResult: ...
    def bulk_create(self, *args, **kwargs) -> IOResult: ...

class IncrementedReturnsQuerySet(BaseReturnsQuerySet):
    """A subclass that includes safe versions (ending with _safe)
    of unsafe methods that can be used separately from the original methods.
    """
    def get(self, *args, **kwargs): ...
    def earliest(self, *args, **kwargs): ...
    def latest(self, *args, **kwargs): ...
    def create(self, *args, **kwargs): ...
    def get_or_create(self, *args, **kwargs): ...
    def update_or_create(self, *args, **kwargs): ...
    def delete(self, *args, **kwargs): ...
    def bulk_create(self, *args, **kwargs): ...

    # Safe versions return Result
    def get_safe(self, *args, **kwargs) -> Result: ...
    def earliest_safe(self, *args, **kwargs) -> Result: ...
    def latest_safe(self, *args, **kwargs) -> Result: ...
    def create_safe(self, *args, **kwargs) -> Result: ...
    def get_or_create_safe(self, *args, **kwargs) -> Result: ...
    def update_or_create_safe(self, *args, **kwargs) -> Result: ...
    def delete_safe(self, *args, **kwargs) -> Result: ...
    def bulk_create_safe(self, *args, **kwargs) -> Result: ...

    # Async safe versions return IOResult
    async def aget_safe(self, *args, **kwargs) -> IOResult: ...
    async def aearliest_safe(self, *args, **kwargs) -> IOResult: ...
    async def alatest_safe(self, *args, **kwargs) -> IOResult: ...
    async def acreate_safe(self, *args, **kwargs) -> IOResult: ...
    async def aget_or_create_safe(self, *args, **kwargs) -> IOResult: ...
    async def aupdate_or_create_safe(self, *args, **kwargs) -> IOResult: ...
    async def adelete_safe(self, *args, **kwargs) -> IOResult: ...
    async def abulk_create_safe(self, *args, **kwargs) -> IOResult: ...

    # Maybe methods
    def first_maybe(self, *args, **kwargs) -> Maybe: ...
    def last_maybe(self, *args, **kwargs) -> Maybe: ...

class ReturnsManager(Manager):
    """Manager that selects a QuerySet according to init params
    and defaults to IncrementedReturnsQuerySet.
    """
    def __init__(
        self, override_with_safe: bool = False, override_with_impure: bool = False
    ) -> None: ...
    def get_queryset(
        self,
    ) -> IncrementedReturnsQuerySet | SafeReturnsQuerySet | ImpureReturnsQuerySet: ...
