import logging

from datetime import datetime
from typing import Optional
from phonenumbers import parse, format_number, PhoneNumberFormat

from intranet.trip.src.config import settings
from intranet.trip.src.lib.drive.gateway import DriveGateway
from intranet.trip.src.logic.triggers.base import BaseTrigger


logger = logging.getLogger(__name__)


class DriveTrigger(BaseTrigger):
    """
    Подключение/отключение кошелька драйва
    """

    async def activate(self):
        org_id = f'{settings.DRIVE_ORG_PREFIX}{self.person_trip.person.company_id}'
        phone_number = self._format_phone_number(self.person_trip.person.phone_number)
        drive_gateway = await DriveGateway.init()
        user_id = await drive_gateway.get_user(phone_number)
        tracker_issue = self.person_trip.travel_details.tracker_issue
        await drive_gateway.activate(org_id, user_id, tracker_issue)
        if await drive_gateway.is_activated(org_id, user_id):
            await self._update_travel_details(
                org_id=org_id,
                user_id=user_id,
                is_drive_activated=True,
            )
        else:
            logger.error('drive activation failed')

    async def deactivate(self):
        org_id = self.person_trip.travel_details.drive_org_id
        user_id = self.person_trip.travel_details.drive_user_id
        tracker_issue = self.person_trip.travel_details.tracker_issue
        drive_gateway = await DriveGateway.init()
        await drive_gateway.deactivate(org_id, user_id, tracker_issue)
        if not await drive_gateway.is_activated(org_id, user_id):
            await self._update_travel_details(
                org_id=None,
                user_id=None,
                is_drive_activated=False,
            )
        else:
            logger.error('drive deactivation failed')

    def is_active(self) -> bool:
        return self._has_travel_details() and self.person_trip.travel_details.is_drive_activated

    def should_be_active(self) -> bool:
        return (
            settings.IS_YA_TEAM  # Пока не включаем Драйв совсем в b2b-версии
            and self.person_trip.person.phone_number is not None
            and self._has_travel_details()
            and self._is_in_activation_date_range()
        )

    def _has_travel_details(self) -> bool:
        return self.person_trip.travel_details is not None

    def _is_in_activation_date_range(self) -> bool:
        now = datetime.now().date()
        start_time = self.person_trip.travel_details.taxi_date_from
        end_time = self.person_trip.travel_details.taxi_date_to
        return start_time <= now <= end_time

    @staticmethod
    def _format_phone_number(phone: str) -> str:
        """
        Преобразование номера телефона в ожидаемый в API драйва формат

        В базе номер хранится в формате: +7 900 123-45-67
        Драйв ожидает номер в формате: +79001234567
        """
        parsed_number = parse(phone)
        return format_number(parsed_number, PhoneNumberFormat.E164)

    async def _update_travel_details(
            self,
            org_id: Optional[str],
            user_id: Optional[str],
            is_drive_activated: bool,
    ):
        await self.uow.person_trips.update_travel_details(
            trip_id=self.person_trip.trip_id,
            person_id=self.person_trip.person_id,
            drive_org_id=org_id,
            drive_user_id=user_id,
            is_drive_activated=is_drive_activated,
            city_id=1,
            is_created_on_provider=self.person_trip.travel_details.is_created_on_provider,
        )
