"""
Сервис для работы с адресами и получателями заказов.
Содержит логику создания, обновления и управления адресами доставки и получателями.
"""
from ..models import Order, Address, Recipient


class AddressService:
    """Сервис для управления адресами доставки и получателями в заказах"""

    @staticmethod
    def create_address_from_form_data(form_data):
        """
        Создает объект Address из данных формы.

        Args:
            form_data (dict): Словарь с данными из формы
                - address_street
                - address_building_number
                - address_apartment_number (опционально)
                - address_entrance (опционально)
                - address_floor (опционально)
                - address_intercom_code (опционально)
                - address_delivery_instructions (опционально)

        Returns:
            Address: Новый объект адреса (не сохраненный в БД)
        """
        address = Address(
            street=form_data.get('address_street', ''),
            building_number=form_data.get('address_building_number', ''),
            apartment_number=form_data.get('address_apartment_number', ''),
            entrance=form_data.get('address_entrance', ''),
            floor=form_data.get('address_floor', ''),
            intercom_code=form_data.get('address_intercom_code', ''),
            delivery_instructions=form_data.get('address_delivery_instructions', ''),
            confirm_address_with_recipient=form_data.get('address_confirm_with_recipient', False),
        )
        return address

    @staticmethod
    def create_recipient_from_form_data(form_data):
        """
        Создает объект Recipient из данных формы.

        Args:
            form_data (dict): Словарь с данными из формы
                - recipient_name
                - recipient_phone
                - recipient_notes (опционально)

        Returns:
            Recipient: Новый объект получателя (не сохраненный в БД)
        """
        recipient = Recipient(
            name=form_data.get('recipient_name', ''),
            phone=form_data.get('recipient_phone', ''),
            notes=form_data.get('recipient_notes', '') or None,
        )
        return recipient

    @staticmethod
    def process_recipient_from_form(order, form_data):
        """
        Обрабатывает получателя из данных формы заказа.
        Создает нового Recipient или использует существующего в зависимости от режима.

        Args:
            order (Order): Объект заказа
            form_data (dict): Все данные из формы

        Returns:
            Recipient or None: Получатель для привязки к заказу или None
        """
        # Если чекбокс "Другой получатель" не включен - возвращаем None (получатель = покупатель)
        other_recipient = form_data.get('other_recipient', False)
        if not other_recipient:
            return None

        # Определяем источник получателя
        recipient_source = form_data.get('recipient_source', 'new')

        # Если режим "выбрать из истории" - возвращаем выбранного получателя
        if recipient_source == 'history':
            recipient_id = form_data.get('recipient_from_history')
            if recipient_id:
                try:
                    return Recipient.objects.get(pk=recipient_id)
                except Recipient.DoesNotExist:
                    return None

        # Если режим "новый получатель"
        if recipient_source == 'new':
            name = form_data.get('recipient_name', '').strip()
            phone = form_data.get('recipient_phone', '')
            notes = form_data.get('recipient_notes', '').strip() or None

            if not name or not phone:
                return None

            # Если у заказа уже есть получатель - обновляем его вместо создания нового
            # Загружаем заказ из БД, чтобы получить актуального получателя
            if order.pk:
                try:
                    # Order уже импортирован в начале файла
                    db_order = Order.objects.select_related('recipient').get(pk=order.pk)
                    if db_order.recipient:
                        # Обновляем существующего получателя
                        db_order.recipient.name = name
                        db_order.recipient.phone = phone
                        db_order.recipient.notes = notes
                        # Сохранять будем в views.py, здесь просто возвращаем объект
                        return db_order.recipient
                except Order.DoesNotExist:
                    pass

            # Проверяем, есть ли уже такой получатель в БД (по имени и нормализованному телефону)
            # PhoneNumberField автоматически нормализует телефон, поэтому можно искать напрямую
            existing_recipient = Recipient.objects.filter(
                name__iexact=name.strip(),
                phone=phone
            ).first()

            if existing_recipient:
                # Обновляем заметки, если они изменились
                if existing_recipient.notes != notes:
                    existing_recipient.notes = notes
                return existing_recipient

            # Создаем нового получателя
            recipient = AddressService.create_recipient_from_form_data(form_data)
            return recipient

        return None

    @staticmethod
    def process_address_from_form(order, form_data):
        """
        Обрабатывает адрес из данных формы заказа.
        Создает новый Address или использует существующий в зависимости от режима.

        Args:
            order (Order): Объект заказа
            form_data (dict): Все данные из формы

        Returns:
            Address or None: Адрес для привязки к заказу или None
        """
        address_mode = form_data.get('address_mode')

        # Если режим "без адреса" - возвращаем None
        if address_mode == 'empty':
            return None

        # Если режим "выбрать из истории" - возвращаем выбранный адрес
        if address_mode == 'history':
            address_id = form_data.get('address_from_history')
            if address_id:
                try:
                    return Address.objects.get(pk=address_id)
                except Address.DoesNotExist:
                    return None

        # Если режим "ввести новый адрес"
        if address_mode == 'new':
            # Проверяем обязательные поля
            street = form_data.get('address_street', '').strip()
            building_number = form_data.get('address_building_number', '').strip()

            # Для автосохранения разрешаем сохранять адрес даже если не все поля заполнены
            # Проверяем только что хотя бы одно поле адреса заполнено
            has_any_address_data = any([
                street,
                building_number,
                form_data.get('address_apartment_number', '').strip(),
                form_data.get('address_entrance', '').strip(),
                form_data.get('address_floor', '').strip(),
                form_data.get('address_intercom_code', '').strip(),
                form_data.get('address_delivery_instructions', '').strip(),
            ])

            if not has_any_address_data:
                # Если все поля адреса пустые, возвращаем None
                return None

            # Проверяем, есть ли уже такой адрес в БД (по основным полям)
            existing_address = Address.objects.filter(
                street=street,
                building_number=building_number,
                apartment_number=form_data.get('address_apartment_number', '').strip()
            ).first()

            if existing_address:
                return existing_address

            # Создаем новый адрес
            address = AddressService.create_address_from_form_data(form_data)
            return address

        return None

    @staticmethod
    def get_customer_address_history(customer):
        """
        Получает список адресов из истории заказов клиента.

        Args:
            customer (Customer): Клиент

        Returns:
            QuerySet: Адреса, отсортированные по дате создания (новые первыми)
        """
        customer_orders = Order.objects.filter(
            customer=customer,
            delivery_address__isnull=False
        ).order_by('-created_at')

        addresses = Address.objects.filter(
            orders__in=customer_orders
        ).distinct().order_by('-created_at')

        return addresses

    @staticmethod
    def format_address_for_display(address):
        """
        Форматирует адрес для отображения в списке.

        Args:
            address (Address): Объект адреса

        Returns:
            str: Форматированная строка адреса
        """
        address_line = f"{address.street}, {address.building_number}"

        if address.apartment_number:
            address_line += f", кв. {address.apartment_number}"

        details = []
        if address.entrance:
            details.append(f"подъезд {address.entrance}")
        if address.floor:
            details.append(f"этаж {address.floor}")

        if details:
            address_line += f" ({', '.join(details)})"

        return address_line
