import enum
from typing import Optional, List
from pydantic import BaseModel


# Company / Priority / Department / Duty / Employee / Occupant / Module / Endpoint are changeable dynamics
# domain: Optional[str] = "app.evyos.com.tr"
# lang: Optional[str] = "TR"
# timezone: Optional[str] = "GMT+3"
# full_name: Optional[str] = None


class UserType(enum.Enum):

    employee = 1
    occupant = 2


class Credentials(BaseModel):

    person_id: int
    person_name: str


class ApplicationToken(BaseModel):
    # Application Token Object -> is the main object for the user

    user_type: int = UserType.occupant.value
    credential_token: str = ""

    user_uu_id: str
    user_id: int

    person_id: int
    person_uu_id: str

    request: Optional[dict] = None  # Request Info of Client
    expires_at: Optional[float] = None  # Expiry timestamp


class OccupantToken(BaseModel):

    # Selection of the occupant type for a build part is made by the user

    living_space_id: int  # Internal use
    living_space_uu_id: str  # Outer use

    occupant_type_id: int
    occupant_type_uu_id: str
    occupant_type: str

    build_id: int
    build_uuid: str
    build_part_id: int
    build_part_uuid: str

    responsible_company_id: Optional[int] = None
    responsible_company_uuid: Optional[str] = None
    responsible_employee_id: Optional[int] = None
    responsible_employee_uuid: Optional[str] = None

    reachable_event_codes: Optional[dict[str, str]] = (
        None  # ID list of reachable modules
    )
    reachable_app_codes: Optional[dict[str, str]] = None  # ID list of reachable modules


class CompanyToken(BaseModel):

    # Selection of the company for an employee is made by the user
    company_id: int
    company_uu_id: str

    department_id: int  # ID list of departments
    department_uu_id: str  # ID list of departments

    duty_id: int
    duty_uu_id: str

    staff_id: int
    staff_uu_id: str

    employee_id: int
    employee_uu_id: str

    bulk_duties_id: int

    reachable_event_codes: Optional[dict[str, str]] = (
        None  # ID list of reachable modules
    )
    reachable_app_codes: Optional[dict[str, str]] = None  # ID list of reachable modules


class OccupantTokenObject(ApplicationToken):
    # Occupant Token Object -> Requires selection of the occupant type for a specific build part

    available_occupants: dict = None
    selected_occupant: Optional[OccupantToken] = None  # Selected Occupant Type

    @property
    def is_employee(self) -> bool:
        return False

    @property
    def is_occupant(self) -> bool:
        return True


class EmployeeTokenObject(ApplicationToken):
    #  Full hierarchy Employee[staff_id] -> Staff -> Duty -> Department -> Company

    companies_id_list: List[int]  # List of company objects
    companies_uu_id_list: List[str]  # List of company objects

    duty_id_list: List[int]  # List of duty objects
    duty_uu_id_list: List[str]  # List of duty objects

    selected_company: Optional[CompanyToken] = None  # Selected Company Object

    @property
    def is_employee(self) -> bool:
        return True

    @property
    def is_occupant(self) -> bool:
        return False
