import logging
from datetime import datetime, timedelta
import requests
from asgiref.sync import sync_to_async
from hotels.models import Hotel, Reservation
from .base_plugin import BasePMSPlugin

class EcviPMSPlugin(BasePMSPlugin):
    """
    Плагин для интеграции с PMS Ecvi.
    """

    def __init__(self, hotel):
        super().__init__(hotel.pms)  # Передаем PMS-конфигурацию в базовый класс
        self.hotel = hotel  # Сохраняем объект отеля

        # Проверка PMS-конфигурации
        if not self.hotel.pms:
            raise ValueError(f"Отель {self.hotel.name} не имеет связанной PMS конфигурации.")

        # Инициализация параметров API
        self.api_url = self.hotel.pms.url
        self.token = self.hotel.pms.token
        self.username = self.hotel.pms.username
        self.password = self.hotel.pms.password

        # Настройка логгера
        self.logger = logging.getLogger(self.__class__.__name__)
        handler_console = logging.StreamHandler()
        handler_file = logging.FileHandler('ecvi_pms_plugin.log')
        formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
        handler_console.setFormatter(formatter)
        handler_file.setFormatter(formatter)
        self.logger.addHandler(handler_console)
        self.logger.addHandler(handler_file)
        self.logger.setLevel(logging.DEBUG)

    def get_default_parser_settings(self):
        """
        Возвращает настройки парсера по умолчанию.
        """
        return {
            "field_mapping": {
                "check_in": "checkin",
                "check_out": "checkout",
                "room_number": "room_name",
                "room_type_name": "room_type",
                "status": "occupancy",
            },
            "date_format": "%Y-%m-%d %H:%M:%S"  # Формат изменен на соответствующий данным
        }

    async def _fetch_data(self):
        """
        Получает данные из PMS API и сохраняет их в базу.
        """
        headers = {"Content-Type": "application/json"}
        data = {"token": self.token}

        try:
            # Запрос данных из PMS API
            response = await sync_to_async(requests.post)(
                self.api_url, headers=headers, json=data, auth=(self.username, self.password)
            )
            response.raise_for_status()
            response_data = response.json()
            self.logger.debug(f"Полученные данные с API: {response_data}")
            return await self._process_data(response_data)
        except requests.exceptions.RequestException as e:
            self.logger.error(f"Ошибка API: {e}")
            return {
                "processed_intervals": 0,
                "processed_items": 0,
                "errors": [str(e)]
            }

    async def _process_data(self, data):
        """
        Обрабатывает данные и сохраняет их в базу.
        """
        processed_items = 0
        errors = []

        date_formats = ["%Y-%m-%d %H:%M:%S", "%Y-%m-%dT%H:%M:%S"]  # Поддержка нескольких форматов даты

        for item in data:
            try:
                # Парсинг даты с поддержкой нескольких форматов
                checkin = self._parse_date(item['checkin'], date_formats)
                checkout = self._parse_date(item['checkout'], date_formats)

                reservation, created = await sync_to_async(Reservation.objects.update_or_create)(
                    reservation_id=item['task_id'],
                    defaults={
                        'room_number': item['room_name'],
                        'room_type': item['room_type'],
                        'check_in': checkin,
                        'check_out': checkout,
                        'status': item['occupancy'],
                        'hotel': self.hotel,
                    }
                )

                if created:
                    self.logger.debug(f"Создана новая резервация: {reservation.reservation_id}")
                else:
                    self.logger.debug(f"Обновлена существующая резервация: {reservation.reservation_id}")

                processed_items += 1

            except Exception as e:
                self.logger.error(f"Ошибка обработки записи: {e}")
                errors.append(str(e))

        return {
            "processed_intervals": 1,
            "processed_items": processed_items,
            "errors": errors
        }

    @staticmethod
    def _parse_date(date_str, formats):
        """
        Парсит дату, пытаясь использовать несколько форматов.
        """
        for fmt in formats:
            try:
                return datetime.strptime(date_str, fmt)
            except ValueError:
                continue
        raise ValueError(f"Дата '{date_str}' не соответствует ожидаемым форматам: {formats}")

    def validate_plugin(self):
        """
        Проверка корректности реализации плагина.
        """
        required_methods = ["fetch_data", "get_default_parser_settings", "_fetch_data"]
        for method in required_methods:
            if not hasattr(self, method):
                raise ValueError(f"Плагин {type(self).__name__} не реализует метод {method}.")
        self.logger.debug(f"Плагин {self.__class__.__name__} прошел валидацию.")
        return True
