from abc import abstractmethod
from asyncio import iscoroutinefunction

from ariadne import SubscriptionType
from graphql import GraphQLResolveInfo

from api_graphql.abc.query_abc import QueryABC
from api_graphql.field.subscription_field_builder import SubscriptionFieldBuilder
from core.logger import APILogger

logger = APILogger(__name__)


class SubscriptionABC(SubscriptionType, QueryABC):

    @abstractmethod
    def __init__(self):
        SubscriptionType.__init__(self)

    def subscribe(self, builder: SubscriptionFieldBuilder):
        field = builder.build()

        async def wrapper(_, info: GraphQLResolveInfo, *args, **kwargs):
            # rebuild args for resolvers
            args = [_, info, *args]
            if not field.public:
                r = info.context.get("request")
                await self._authorize(r)

            if (
                field.require_any is None
                and not field.public
                and field.require_any_permission
            ):
                await self._require_any_permission(field.require_any_permission)

            result = (
                await field.resolver(*args, **kwargs)
                if iscoroutinefunction(field.resolver)
                else field.resolver(*args, **kwargs)
            )

            if field.require_any is not None:
                await self._require_any(
                    result,
                    *field.require_any,
                    *args,
                    **kwargs,
                )

            return result

        self.set_field(field.name, wrapper)
        self.set_source(field.name, field.generator)
