"""
Sarmat.
Ядро пакета.
Описание бизнес логики.
Модели.
Модели для построения маршрутной сети.
"""
from dataclasses import dataclass
from datetime import time, date
from typing import List, Optional

from sarmat.core.constants import JourneyType, RoadType, RouteType, StationType

from .geo_models import DirectionModel, DestinationPointModel, RoadNameModel
from .sarmat_models import BaseIdModel, BaseModel, CustomAttributesModel, DurationModel


@dataclass
class BaseStationModel(BaseModel):
    """Станции (пункты посадки-высадки пассажиров) (основные атрибуты)"""

    station_type: StationType           # тип станции
    name: str                           # наименование
    point: DestinationPointModel        # ближайший населенный пункт
    address: str = ''                   # почтовый адрес


@dataclass
class StationModel(BaseIdModel, CustomAttributesModel, BaseStationModel):
    """Станции (пункты посадки-высадки пассажиров)"""


@dataclass
class BaseRoadModel(BaseModel):
    """Дороги (основные атрибуты)"""

    start_point: DestinationPointModel          # начало дороги
    end_point: DestinationPointModel            # конец дороги
    direct_travel_time_min: int                 # время прохождения в прямом направлении
    reverse_travel_time_min: int                # время прохождения в обратном направлении
    direct_len_km: float                        # расстояние в прямом направлении
    reverse_len_km: float                       # расстояние в обратном направлении
    road_type: RoadType                         # тип дорожного покрытия
    road_name: Optional[RoadNameModel] = None   # классификация дороги


@dataclass
class RoadModel(BaseIdModel, CustomAttributesModel, BaseRoadModel):
    """Дороги"""


@dataclass
class BaseRouteItemModel(BaseModel):
    """Состав маршрута (основные атрибуты)"""

    length_from_last_km: float                      # расстояние от предыдущего пункта
    travel_time_min: int                            # время движения от предыдущего пункта в минутах
    road: Optional[RoadModel] = None                # дорога
    position: int = 1                               # порядок следования
    station: Optional[StationModel] = None          # станция
    point: Optional[DestinationPointModel] = None   # ближайший населенный пункт
    stop_time_min: Optional[int] = None             # время стоянки в минутах


@dataclass
class RouteItemModel(BaseIdModel, CustomAttributesModel, BaseRouteItemModel):
    """Состав маршрута"""


@dataclass
class CommonRouteModel(BaseModel):
    """Общие атрибуты для маршрута и рейса"""

    route_type: RouteType                               # тип маршрута
    name: str                                           # наименование
    first_station: StationModel                         # станция отправления
    structure: List[RouteItemModel]                     # состав маршрута
    direction: Optional[List[DirectionModel]] = None    # направления
    comments: Optional[str] = None                      # комментарий к маршруту
    number: Optional[int] = None                        # номер маршрута
    literal: str = ''                                   # литера
    is_active: bool = True                              # признак активности маршрута


@dataclass
class BaseRouteModel(BaseModel):
    """Описание маршрута (основные атрибуты)"""


@dataclass
class RouteModel(BaseIdModel, CustomAttributesModel, CommonRouteModel, BaseRouteModel):
    """Описание маршрута"""


@dataclass
class BaseJourneyModel(BaseModel):
    """Атрибуты рейса (основные атрибуты)"""

    journey_type: JourneyType                           # тип рейса
    departure_time: time                                # время отправления


@dataclass
class JourneyModel(BaseIdModel, CustomAttributesModel, CommonRouteModel, BaseJourneyModel):
    """Атрибуты рейса"""

    is_chartered: bool = False                          # признак заказного рейса
    need_control: bool = False                          # признак именной продажи и мониторинга
    season_begin: Optional[date] = None                 # начало сезона
    season_end: Optional[date] = None                   # окончание сезона


@dataclass
class BaseJourneyBunchItemModel(BaseModel):
    """Атрибуты элемента из связки рейсов (основные атрибуты)"""

    journey: JourneyModel           # рейс
    stop_duration: DurationModel    # время простоя
    position: int                   # номер в последовательности


@dataclass
class JourneyBunchItemModel(BaseIdModel, CustomAttributesModel, BaseJourneyBunchItemModel):
    """Атрибуты элемента из связки рейсов"""


@dataclass
class BaseJourneyBunchModel(BaseModel):
    """Атрибуты связки рейсов (основные атрибуты)"""

    journeys: List[JourneyBunchItemModel]     # элементы связки
    name: Optional[str] = None                # наименование связки


@dataclass
class JourneyBunchModel(BaseIdModel, CustomAttributesModel, BaseJourneyBunchModel):
    """Атрибуты связки рейсов"""
