from datetime import date
from pydantic import BaseModel, Field, validator, root_validator
import urllib

from intranet.trip.src.enums import (
    Provider,
    PTStatus,
    TripDaysOffCompensations,
    ServiceStatus,
    ConferenceParticiationType,
)
from intranet.trip.src.models.document import Document
from intranet.trip.src.models.person import Person
from intranet.trip.src.models.purpose import Purpose
from intranet.trip.src.models.service import Service
from intranet.trip.src.models.common import City, RouteMixin, RoutePoint, build_complex_route
from intranet.trip.src.lib.utils import unify_values

from intranet.trip.src.config import settings


class TravelDetails(BaseModel):
    trip_id: int
    person_id: int
    tracker_issue: str = None
    is_created_on_provider: bool
    need_visa_assistance: bool
    taxi_date_from: date = None
    taxi_date_to: date = None
    is_taxi_activated: bool
    is_drive_activated: bool
    taxi_access_phone: str = None
    drive_org_id: str = None
    drive_user_id: str = None
    comment: str = None
    city: City = None


class PersonConfDetails(BaseModel):
    trip_id: int
    person_id: int
    role: ConferenceParticiationType
    presentation_topic: str = None
    is_hr_approved: bool = False
    is_paid_by_host: bool = False
    is_another_city: bool = False
    tracker_issue: str = None
    promo_code: str = None
    discount: str = None
    price: str = None
    badge_position: str = None
    badge_name: str = None
    comment: str = None


class PersonTripActions(BaseModel):
    edit: bool
    cancel: bool
    search_service: bool
    create_service: bool
    send_to_verification: bool
    execute_services: bool
    execute_extra_services: bool
    create_manager_chat: bool
    read: bool
    join_chat: bool
    approve: bool


class PersonTrip(BaseModel, RouteMixin):
    trip_id: int = None
    person_id: int = None
    person: Person = None
    provider: Provider = None
    status: PTStatus
    is_approved: bool = None
    is_authorized: bool = None
    is_hidden: bool = None
    is_offline: bool = None
    need_visa: bool = None
    with_days_off: bool = None
    gap_date_from: date = None
    gap_date_to: date = None
    description: str = None
    chat_id: str = None
    manager_chat_id: str = None
    compensation_type: TripDaysOffCompensations = None
    assignment: int = None

    city_from: str = None
    country_from: str = None

    manager_id: int = None
    manager: Person = None

    purposes: list[Purpose] = None
    travel_details: TravelDetails = None
    conf_details: PersonConfDetails = None
    documents: list[Document] = None
    services: list[Service] = None

    aeroclub_trip_id: int = None
    aeroclub_journey_id: int = None
    aeroclub_city_from_id: int = Field(None, deprecated=True)
    provider_city_from_id: str = None
    aeroclub_last_message_id: int = None

    # поля берутся из групповой командировки
    city_to: str = None
    country_to: str = None
    aeroclub_city_to_id: int = Field(None, deprecated=True)
    provider_city_to_id: str = None
    trip_author_id: int = None

    actions: PersonTripActions = None

    route: list[RoutePoint] = None

    @property
    def travel_tracker_issue(self):
        if self.travel_details and self.travel_details.tracker_issue:
            return self.travel_details.tracker_issue
        return

    @property
    def conf_tracker_issue(self):
        if self.conf_details and self.conf_details.tracker_issue:
            return self.conf_details.tracker_issue
        return

    @property
    def main_tracker_issue(self):
        """
        Если у человека есть оба тикета TRAVEL и INTERCONF, то основным считаем TRAVEL
        """
        return self.travel_tracker_issue or self.conf_tracker_issue

    @property
    def alive_services(self):
        if not self.services:
            return []
        return [
            s
            for s in self.services
            if (
                s.status not in (ServiceStatus.deleted, ServiceStatus.cancelled)
                and not s.in_process_of_cancelling
            )
        ]

    @property
    def chat_url(self) -> str:
        if self.chat_id is None:
            return None
        chat_id = urllib.parse.quote_plus(self.chat_id)
        return f'https://{settings.MESSENGER_UI_HOST}/#/chats/{chat_id}'

    @property
    def manager_login(self) -> str:
        if self.manager is None:
            return None
        return self.manager.login

    @property
    def url(self) -> str:
        return settings.person_trip_url(
            trip_id=self.trip_id,
            person_id=self.person_id,
        )

    @validator('route', pre=True)
    def build_person_trip_complex_route(cls, v):
        return build_complex_route(v)

    @validator('route', always=True)
    def collect_route_if_empty(cls, v, values):
        if v is not None:
            return v
        return cls.get_city_list(values=values, date_prefix='gap_date')

    @root_validator(pre=True)
    def set_provider_cities(cls, values):
        values = unify_values(values, ['provider_city_from_id', 'aeroclub_city_from_id'])
        values = unify_values(values, ['provider_city_to_id', 'aeroclub_city_to_id'])
        return values


Service.update_forward_refs(PersonTrip=PersonTrip)
