from datetime import timedelta
from urllib.parse import parse_qs
from django.utils import timezone
from django.db.models import Q
from hotels.models import Reservation, Hotel
from .models import UserActivityLog, ViolationLog
from touchh.utils.log import CustomLogger
# Настройка логирования
logger = CustomLogger(__name__).get_logger()


class ReservationChecker:
    """
    Класс для проверки несоответствий между бронированиями и логами заселения.
    """

    def __init__(self):
        """
        Инициализация времени проверки и списка нарушений.
        """
        self.start_time = timezone.now() - timedelta(days=30)
        self.end_time = timezone.now()
        self.violations = []

    def log_info(self, message):
        logger.info(message)

    def log_warning(self, message):
        logger.warning(message)

    def log_error(self, message):
        logger.error(message)

    def fetch_user_logs(self):
        try:
            self.log_info("Начинается извлечение логов активности пользователей.")
            user_logs = UserActivityLog.objects.filter(created__range=(self.start_time, self.end_time))
            self.log_info(f"Найдено {user_logs.count()} логов активности для анализа.")
            return user_logs
        except Exception as e:
            self.log_error(f"Ошибка при извлечении логов активности: {e}")
            return UserActivityLog.objects.none()

    def fetch_reservations(self):
        try:
            self.log_info("Начинается извлечение бронирований.")
            reservations = Reservation.objects.filter(
                Q(check_in__lte=self.end_time) & Q(check_out__gte=self.start_time)
            )
            self.log_info(f"Найдено {reservations.count()} бронирований для анализа.")
            return reservations
        except Exception as e:
            self.log_error(f"Ошибка при извлечении бронирований: {e}")
            return Reservation.objects.none()

    def find_violations(self):
        self.log_info("Начинается анализ несоответствий.")
        user_logs = self.fetch_user_logs()
        reservations = self.fetch_reservations()

        log_lookup = {}
        for log in user_logs:
            params = parse_qs(log.url_parameters or "")
            hotel_id = params.get("utm_content", [None])[0]
            room_number = params.get("utm_term", [None])[0]
            if hotel_id and room_number:
                key = (hotel_id, room_number)
                log_lookup.setdefault(key, []).append(log)

        for reservation in reservations:
            key = (reservation.hotel.hotel_id, reservation.room_number)
            logs = log_lookup.get(key, [])

            if reservation.status == "заселен" and not logs:
                self.record_violation(
                    hotel=reservation.hotel,
                    room_number=reservation.room_number,
                    violation_type="no_qr_scan",
                    details=f"Бронирование для номера {reservation.room_number} в отеле '{reservation.hotel.name}' "
                            f"не имеет записи сканирования QR."
                )

            for log in logs:
                if log.created < reservation.check_in:
                    self.record_violation(
                        hotel=reservation.hotel,
                        room_number=reservation.room_number,
                        violation_type="early_check_in",
                        details=f"Раннее заселение: сканирование QR {log.created} раньше времени заезда "
                                f"{reservation.check_in} для номера {reservation.room_number}."
                    )

        for (hotel_id, room_number), logs in log_lookup.items():
            matching_reservations = reservations.filter(
                hotel__hotel_id=hotel_id,
                room_number=room_number
            )
            if not matching_reservations.exists():
                for log in logs:
                    self.record_violation(
                        hotel=Hotel.objects.filter(hotel_id=hotel_id).first(),
                        room_number=room_number,
                        violation_type="no_reservation",
                        details=f"Сканирование QR {log.created} для номера {room_number} в отеле с ID '{hotel_id}' "
                                f"не соответствует ни одному бронированию."
                    )

    def record_violation(self, hotel, room_number, violation_type, details):
        if hotel:
            self.violations.append(ViolationLog(
                hotel=hotel,
                room_number=room_number,
                violation_type=violation_type,
                violation_details=details
            ))
            self.log_warning(f"Зафиксировано нарушение: {details}")

    def save_violations(self):
        if self.violations:
            ViolationLog.objects.bulk_create(self.violations)
            self.log_info(f"Создано {len(self.violations)} записей в ViolationLog.")
        else:
            self.log_info("Нарушений не обнаружено.")

    def run_check(self):
        self.log_info(f"Запуск проверки с {self.start_time} по {self.end_time}.")
        try:
            self.find_violations()
            self.save_violations()
        except Exception as e:
            self.log_error(f"Ошибка при выполнении проверки: {e}")
        self.log_info("Проверка завершена.")

# Функция для запуска из планировщика
def run_reservation_check():
    logger.info("Планировщик вызывает run_reservation_check.")
    try:
        checker = ReservationChecker()
        checker.run_check()
    except Exception as e:
        logger.error(f"Ошибка при запуске проверки: {e}")
    logger.info("run_reservation_check завершена.")