from typing import Type, Self, Callable

from api_graphql.abc.field_builder_abc import FieldBuilderABC
from api_graphql.abc.filter_abc import FilterABC
from api_graphql.field.dao_field import DaoField
from core.database.abc.data_access_object_abc import DataAccessObjectABC
from core.typing import T


class DaoFieldBuilder(FieldBuilderABC):

    def __init__(self, name: str):
        FieldBuilderABC.__init__(self, name)

        self._dao = None
        self._filter_type = None
        self._default_filter = None
        self._sort_type = None
        self._direct_result = False

    def with_dao(self, dao: DataAccessObjectABC) -> Self:
        assert dao is not None, "dao cannot be None"
        self._dao = dao
        return self

    def with_filter(self, filter_type: Type[FilterABC]) -> Self:
        assert filter_type is not None, "filter cannot be None"
        self._filter_type = filter_type
        return self

    def with_default_filter(self, filter: Callable) -> Self:
        assert filter is not None, "filter cannot be None"
        assert callable(filter), "filter must be callable"
        self._default_filter = filter
        return self

    def with_sort(self, sort_type: Type[T]) -> Self:
        assert sort_type is not None, "sort cannot be None"
        self._sort_type = sort_type
        return self

    def with_direct_result(self) -> Self:
        self._direct_result = True
        return self

    def build(self) -> DaoField:
        assert self._dao is not None, "dao cannot be None"
        return DaoField(
            self._name,
            self._require_any_permission,
            self._require_any,
            self._public,
            self._dao,
            self._filter_type,
            self._default_filter,
            self._sort_type,
            self._direct_result,
        )
