from copy import deepcopy
from typing import Optional

from api_graphql.abc.query_abc import QueryABC
from core.database.abc.data_access_object_abc import DataAccessObjectABC
from core.logger import APILogger

logger = APILogger("api.api")


class DbModelQueryABC(QueryABC):

    def __init__(
        self,
        name: str = __name__,
        dao: DataAccessObjectABC = None,
        with_history: bool = False,
    ):
        QueryABC.__init__(self, name)

        self._dao: Optional[DataAccessObjectABC] = dao

        self.set_field("id", lambda x, *_: x.id)
        self.set_field("deleted", lambda x, *_: x.deleted)
        self.set_field("editor", lambda x, *_: x.editor)
        self.set_field("created", lambda x, *_: x.created)
        self.set_field("updated", lambda x, *_: x.updated)

        if with_history:
            self.set_field("history", self._resolve_history)

        self._history_reference_daos: dict[DataAccessObjectABC, str] = {}

    async def _resolve_history(self, x, *_):
        if self._dao is None:
            raise Exception("DAO not set for history query")

        history = sorted(
            [await self._dao.get_by_id(x.id), *await self._dao.get_history(x.id)],
            key=lambda h: h.updated,
            reverse=True,
        )
        return history

    def set_history_reference_dao(self, dao: DataAccessObjectABC, key: str = None):
        """
        Set the reference DAO for history resolution.
        :param dao:
        :param key: The key to use for resolving history.
        :return:
        """
        if key is None:
            key = "id"
        self._history_reference_daos[dao] = key
