from django.db import models
from hotels.models import Hotel, Reservation


class UserActivityLog(models.Model):
    id = models.BigIntegerField(primary_key=True)
    user_id = models.BigIntegerField(verbose_name="ID пользователя")
    ip = models.GenericIPAddressField(verbose_name="IP-адрес")
    created = models.DateTimeField(verbose_name="Дата создания")
    timestamp = models.BigIntegerField(verbose_name="Метка времени")
    date_time = models.DateTimeField(verbose_name="Дата и время")
    referred = models.TextField(blank=True, null=True, verbose_name="Реферальная ссылка")
    agent = models.TextField(verbose_name="Агент пользователя")
    platform = models.CharField(max_length=255, blank=True, null=True, verbose_name="Платформа")
    version = models.CharField(max_length=255, blank=True, null=True, verbose_name="Версия")
    model = models.CharField(max_length=255, blank=True, null=True, verbose_name="Модель устройства")
    device = models.CharField(max_length=255, blank=True, null=True, verbose_name="Тип устройства")
    UAString = models.TextField(verbose_name="User-Agent строка")
    location = models.CharField(max_length=255, blank=True, null=True, verbose_name="Местоположение")
    page_id = models.BigIntegerField(blank=True, null=True, verbose_name="ID страницы")
    url_parameters = models.TextField(blank=True, null=True, verbose_name="Параметры URL")
    page_title = models.TextField(blank=True, null=True, verbose_name="Заголовок страницы")
    type = models.CharField(max_length=50, verbose_name="Тип")
    last_counter = models.IntegerField(verbose_name="Последний счетчик")
    hits = models.IntegerField(verbose_name="Количество обращений")
    honeypot = models.BooleanField(verbose_name="Метка honeypot")
    reply = models.BooleanField(verbose_name="Ответ пользователя")
    page_url = models.URLField(blank=True, null=True, verbose_name="URL страницы")

    def __str__(self):
        return f"UserActivityLog {self.id}: {self.page_title}"

    class Meta:
        verbose_name = "Регистрация посетителей"
        verbose_name_plural = "Регистрации посетителей"


class ExternalDBSettings(models.Model):
    name = models.CharField(max_length=255, unique=True, help_text="Имя подключения для идентификации.")
    host = models.CharField(max_length=255, help_text="Адрес сервера базы данных.")
    port = models.PositiveIntegerField(default=3306, help_text="Порт сервера базы данных.")
    user = models.CharField(max_length=255, help_text="Имя пользователя базы данных.")
    password = models.CharField(max_length=255, help_text="Пароль для подключения.")
    database = models.CharField(max_length=255, default="", help_text="Имя базы данных.")
    table_name = models.CharField(max_length=255, blank=True, null=True, help_text="Имя таблицы для загрузки данных.")
    selected_fields = models.TextField(blank=True, null=True, help_text="Список полей для загрузки (через запятую).")
    is_active = models.BooleanField(default=True, help_text="Флаг активности подключения.")
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return f"{self.name} ({self.host}:{self.port})"

    class Meta:
        verbose_name = "Настройки подключения к БД"
        verbose_name_plural = "Настройки подключений к БД"


class RoomDiscrepancy(models.Model):
    hotel = models.ForeignKey(Hotel, on_delete=models.CASCADE, verbose_name="Отель")
    room_number = models.CharField(max_length=50, verbose_name="Номер комнаты")
    booking_id = models.CharField(max_length=255, verbose_name="ID бронирования")
    check_in_date_expected = models.DateField(verbose_name="Ожидаемая дата заселения")
    check_in_date_actual = models.DateField(verbose_name="Фактическая дата заселения")
    discrepancy_type = models.CharField(
        max_length=50,
        choices=[("early", "Раннее заселение"), ("late", "Позднее заселение"), ("missed", "Неявка")],
        verbose_name="Тип несоответствия"
    )
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата создания")

    def __str__(self):
        return f"{self.hotel.name} - Room {self.room_number}: {self.discrepancy_type}"

    class Meta:
        verbose_name = "Несовпадение в заселении"
        verbose_name_plural = "Несовпадения в заселении"

    @staticmethod
    def detect_discrepancies(expected_bookings, actual_check_ins):
        """
        Сравнение ожидаемых и фактических данных о заселении.
        """
        discrepancies = []

        # Преобразуем фактические заселения в словарь для быстрого доступа
        actual_dict = {
            (entry.hotel_id, entry.room_number): entry.check_in_date
            for entry in actual_check_ins
        }

        for booking in expected_bookings:
            key = (booking.hotel_id, booking.room_number)
            actual_date = actual_dict.get(key)

            if actual_date is None:
                discrepancies.append(RoomDiscrepancy(
                    hotel=booking.hotel,
                    room_number=booking.room_number,
                    booking_id=booking.booking_id,
                    check_in_date_expected=booking.check_in_date,
                    discrepancy_type="missed"
                ))
            elif actual_date < booking.check_in_date:
                discrepancies.append(RoomDiscrepancy(
                    hotel=booking.hotel,
                    room_number=booking.room_number,
                    booking_id=booking.booking_id,
                    check_in_date_expected=booking.check_in_date,
                    check_in_date_actual=actual_date,
                    discrepancy_type="early"
                ))
            elif actual_date > booking.check_in_date:
                discrepancies.append(RoomDiscrepancy(
                    hotel=booking.hotel,
                    room_number=booking.room_number,
                    booking_id=booking.booking_id,
                    check_in_date_expected=booking.check_in_date,
                    check_in_date_actual=actual_date,
                    discrepancy_type="late"
                ))

        RoomDiscrepancy.objects.bulk_create(discrepancies)
