from datetime import datetime
from typing import Optional

from async_property import async_property

from core.database.abc.db_model_abc import DbModelABC
from core.typing import SerialId
from data.schemas.public.group import Group


class ShortUrl(DbModelABC):
    def __init__(
        self,
        id: SerialId,
        short_url: str,
        target_url: str,
        description: Optional[str],
        group_id: Optional[SerialId],
        domain_id: Optional[SerialId],
        loading_screen: Optional[str] = None,
        user_space_id: Optional[SerialId] = None,
        deleted: bool = False,
        editor_id: Optional[SerialId] = None,
        created: Optional[datetime] = None,
        updated: Optional[datetime] = None,
    ):
        DbModelABC.__init__(self, id, deleted, editor_id, created, updated)
        self._short_url = short_url
        self._target_url = target_url
        self._description = description
        self._group_id = group_id
        self._domain_id = domain_id

        if loading_screen is None or loading_screen == "":
            loading_screen = False
        self._loading_screen = loading_screen

        self._user_space_id = user_space_id

    @property
    def short_url(self) -> str:
        return self._short_url

    @short_url.setter
    def short_url(self, value: str):
        self._short_url = value

    @property
    def target_url(self) -> str:
        return self._target_url

    @target_url.setter
    def target_url(self, value: str):
        self._target_url = value

    @property
    def description(self) -> Optional[str]:
        return self._description

    @description.setter
    def description(self, value: Optional[str]):
        self._description = value

    @property
    def group_id(self) -> SerialId:
        return self._group_id

    @group_id.setter
    def group_id(self, value: SerialId):
        self._group_id = value

    @async_property
    async def group(self) -> Optional[Group]:
        if self._group_id is None:
            return None

        from data.schemas.public.group_dao import groupDao

        return await groupDao.get_by_id(self._group_id)

    @property
    def domain_id(self) -> SerialId:
        return self._domain_id

    @domain_id.setter
    def domain_id(self, value: SerialId):
        self._domain_id = value

    @async_property
    async def domain(self) -> Optional[Group]:
        if self._domain_id is None:
            return None

        from data.schemas.public.domain_dao import domainDao

        return await domainDao.get_by_id(self._domain_id)

    @async_property
    async def visit_count(self) -> int:
        from data.schemas.public.short_url_visit_dao import shortUrlVisitDao

        return await shortUrlVisitDao.count_by_id(self.id)

    @property
    def loading_screen(self) -> Optional[str]:
        return self._loading_screen

    @loading_screen.setter
    def loading_screen(self, value: Optional[str]):
        self._loading_screen = value

    @property
    def user_space_id(self) -> Optional[SerialId]:
        return self._user_space_id

    @async_property
    async def user_space(self):
        if self._user_space_id is None:
            return None

        from data.schemas.public.user_space_dao import userSpaceDao

        return await userSpaceDao.get_by_id(self._user_space_id)

    def to_dto(self) -> dict:
        return {
            "id": self.id,
            "target_url": self.target_url,
            "loadingScreen": self.loading_screen,
        }
