from datetime import date, time

from pydantic import BaseModel

from intranet.trip.src.lib.aviacenter import enums
from intranet.trip.src.lib.aviacenter.config import TimeSerializationConfig
from intranet.trip.src.lib.aviacenter.fields import boolint


class TimeInterval(BaseModel):
    from_time: time
    to_time: time

    Config = TimeSerializationConfig

    def dict(self, *args, **kwargs):
        res = super().dict(*args, **kwargs)
        res['from'] = res.pop('from_time')
        res['to'] = res.pop('to_time')
        return res


class AviaSort(BaseModel):
    field: enums.AviaSortField
    direction: enums.SortDirection


class HotelSort(BaseModel):
    field: enums.HotelSortField
    direction: enums.SortDirection


class TrainSort(BaseModel):
    field: enums.TrainSortField
    direction: enums.SortDirection


class AviaSearchSegment(BaseModel):
    from_id: str
    to_id: str
    date: date

    def dict(self, *args, **kwargs):
        res = super().dict(*args, **kwargs)
        res['from'] = res.pop('from_id')
        res['to'] = res.pop('to_id')
        return res


class AviaSearchRequest(BaseModel):
    """Форма поискового запроса для avia"""
    company_id: int
    adult: int = 1
    child: int = 0
    infant: int = 0
    class_avia: enums.ClassAvia = None
    is_direct_only: boolint = 0
    segments: list[AviaSearchSegment]
    airlines: list[str] = None
    is_async: boolint = 0

    def dict(self, *args, **kwargs):
        res = super().dict(*args, **kwargs)
        res['class'] = res.pop('class_avia')
        return res


class AviaSearchFilterSegment(BaseModel):
    departure_time_intervals: list[TimeInterval] = None
    arrival_time_intervals: list[TimeInterval] = None
    from_id: list[str] = None  # MOW, VKO
    to_id: list[str] = None  # SVX

    def dict(self, *args, **kwargs):
        res = super().dict(*args, **kwargs)
        res['from'] = res.pop('from_id', None)
        res['to'] = res.pop('to_id', None)
        return res


class AviaSearchFilter(BaseModel):
    is_refundable: boolint = None
    is_exchangeable: boolint = None
    is_restricted_by_travel_policy: boolint = None
    has_baggage: boolint = None
    maximum_transfers_count: int = None
    segments: list[AviaSearchFilterSegment] = None
    carriers: list[str] = None  # S7, SU, etc.
    sort: list[AviaSort] = None

    Config = TimeSerializationConfig


class HotelSearchGuest(BaseModel):
    citizenship: str


class HotelSearchRoom(BaseModel):
    guests: list[HotelSearchGuest]


class HotelSearchParams(BaseModel):
    city: int
    check_in: date
    check_out: date
    rooms: list[HotelSearchRoom]


class HotelSearchRequest(BaseModel):
    company_id: int
    search: HotelSearchParams


class HotelSearchFilter(BaseModel):
    is_restricted_by_travel_policy: boolint = None
    min_price: int = None  # общая цена за все дни
    max_price: int = None
    stars: list[str] = None
    hotel_categories: list[str] = None
    # Если передан флаг, получать только новые рекомендации, не полученные в предыдущем запросе
    new_data_only: boolint = 0
    sort: list[HotelSort] = None


class TrainSearchRequest(BaseModel):
    company_id: int
    from_id: int
    to_id: int
    date: date
    adult: int = 1
    child: int = 0
    infant: int = 0

    def dict(self, *args, **kwargs):
        res = super().dict(*args, **kwargs)
        res['from'] = res.pop('from_id')
        res['to'] = res.pop('to_id')
        return res


class TrainSearchFilter(BaseModel):
    is_restricted_by_travel_policy: boolint = None
    departure_time_intervals: list[TimeInterval] = None
    arrival_time_intervals: list[TimeInterval] = None
    from_stations: list[int] = None
    to_stations: list[int] = None
    carriers: list[str] = None
    train_categories: list[str] = None
    car_groups: list[str] = None
    train_names: list[str] = None
    sort: list[TrainSort] = None

    # Здесь это нужно из-за вот этой проблемы:
    # https://github.com/samuelcolvin/pydantic/issues/2277
    # Если коротко - при сериализации в json Config применяется только
    # от модели, на которой вызывается json(), а для всех вложенных моделей
    # также применяется Config основной родительской модели.
    # То есть, получается, что несмотря на определение Config внутри модели
    # TimeInterval, при сериализации модели TrainSearchFilter будет использован
    # конфиг именно из TrainSearchFilter даже для сериализации вложенного TimeInterval,
    # но при сериализации TimeInterval напрямую - используется его собственный конфиг.
    Config = TimeSerializationConfig

    def dict(self, *args, **kwargs):
        res = super().dict(*args, **kwargs)
        if 'from_stations' in res:
            res['from'] = res.pop('from_stations')
        if 'to_stations' in res:
            res['to'] = res.pop('to_stations')
        return res
