from typing import Optional, List, Any
from datetime import datetime

from ....core.scope import Scope
from ....core.enums.state import State
from ....core.interfaces.dto import Dto
from ....core.enums.status import Status
from ....core.interfaces.core import Core
from ....enums.domain.clients import ClientPlan
from ....core.enums.grant_type import GrantType

from .domain import ClientDomain, ClientDomainDto
from .service import ClientService, ClientServiceDto


class Client[Properties: Any](Core[Properties]):
  name: str
  plan: ClientPlan

  url: Optional[str]
  logo: Optional[str]
  site: Optional[str]
  slogan: Optional[str]

  state: State
  status: Status

  api_key: str
  client_id: str
  client_secret: str
  expiration_date: datetime

  access_token_ttl: Optional[int]
  refresh_token_ttl: Optional[int]

  scopes: List[Scope]
  whitelist: Optional[List[str]]
  coworkers: Optional[List[str]]
  grant_types: List[GrantType]

  domains: List[ClientDomain]
  services: Optional[List[ClientService]]


# ----------------------------------------
# Data Transfer Object Interface
# ----------------------------------------


class ClientDto[Properties: Any](Dto[Properties]):
  name: str
  plan: ClientPlan

  url: Optional[str]
  logo: Optional[str]
  site: Optional[str]
  slogan: Optional[str]

  state: State
  status: Status

  api_key: str
  client_id: str
  client_secret: str
  expiration_date: datetime

  access_token_ttl: Optional[int]
  refresh_token_ttl: Optional[int]

  scopes: List[Scope]
  whitelist: Optional[List[str]]
  coworkers: Optional[List[str]]
  grant_types: List[GrantType]

  domains: List[ClientDomainDto]
  services: Optional[List[ClientServiceDto]]
