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, pms_config):
        super().__init__(pms_config)

        # Инициализация логгера
        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)  # Уровень логирования

        # Инициализация параметров API
        self.api_url = pms_config.url
        self.token = pms_config.token
        self.username = pms_config.username
        self.password = pms_config.password
        self.pagination_count = 50  # Максимальное количество записей на страницу (если используется пагинация)

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

    async def _fetch_data(self):
        """
        Получает данные из PMS API, фильтрует и сохраняет в базу данных.
        """
        now = datetime.now()
        current_date = now.strftime('%Y-%m-%d')
        yesterday_date = (now - timedelta(days=1)).strftime('%Y-%m-%d')

        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()  # Если ошибка, выбросит исключение
            data = response.json()  # Преобразуем ответ в JSON
            self.logger.debug(f"Получены данные с API: {data}")
        except requests.exceptions.RequestException as e:
            self.logger.error(f"Ошибка запроса: {e}")
            return []
        self.logger.debug(f"\n\n\n\n\ndata: {data}\n\n\n\n\n")
        # Фильтрация данных
        filtered_data = [
            {
                'reservation_id': item.get('task_id'),
                'room_number': item.get('room_name'),
                'room_type': item.get('room_type'),
                'checkin': datetime.strptime(item.get('checkin'), '%Y-%m-%d %H:%M:%S'),
                'checkout': datetime.strptime(item.get('checkout'), '%Y-%m-%d %H:%M:%S'),
                'status': item.get('occupancy')
            } for item in data if isinstance(item, dict) and item.get('occupancy') in ['проживание', 'под выезд', 'под заезд']
        ]
        
        
        self.logger.debug(f"filtered_data: {filtered_data}")
        
        # Сохранение данных в базу данных
        for item in filtered_data:
            await self._save_to_db(item)
        
        self.logger.debug(f"Данные успешно сохранены.")
        return filtered_data

    async def _save_to_db(self, item):
        """
        Сохраняет данные в БД (например, информацию о номере).
        """
        try:
            # Получаем отель по настройкам PMS
            hotel = await sync_to_async(Hotel.objects.get)(pms=self.pms_config)
            self.logger.debug(f"Отель найден: {hotel.name}")

            # Проверяем, существует ли уже резервация с таким внешним ID
            reservation_id = item.get('reservation_id')
            self.logger.debug(f"-----\n\n\nITEM : {item}\n\n\n---")
            if not reservation_id:
                self.logger.error("Ошибка: 'reservation_id' отсутствует в данных.")
                return
            
            existing_reservation = await sync_to_async(Reservation.objects.filter)(reservation_id=reservation_id)

            # Теперь вызываем .first() после асинхронного вызова
            existing_reservation = await sync_to_async(existing_reservation.first)()

            if existing_reservation:
                self.logger.debug(f"Резервация {reservation_id} уже существует. Обновляем...")
                await sync_to_async(Reservation.objects.update_or_create)(
                    reservation_id=reservation_id,
                    defaults={
                        'room_number': item.get('room_number'),
                        'room_type': item.get('room_type'),
                        'check_in': item.get('checkin'),
                        'check_out': item.get('checkout'),
                        'status': item.get('status'),
                        'hotel': hotel
                    }
                )
                self.logger.debug(f"Резервация обновлена.")
            else:
                self.logger.debug(f"Резервация не найдена, создаем новую...")
                reservation = await sync_to_async(Reservation.objects.create)(
                    reservation_id=reservation_id,
                    room_number=item.get('room_number'),
                    room_type=item.get('room_type'),
                    check_in=item.get('checkin'),
                    check_out=item.get('checkout'),
                    status=item.get('status'),
                    hotel=hotel
                )
                self.logger.debug(f"Новая резервация создана с ID: {reservation.reservation_id}")

        except Exception as e:
            self.logger.error(f"Ошибка сохранения данных: {e}")

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