from __future__ import annotations

from datetime import date
from typing import Iterable, Protocol

from .date_range import DateRange
from .exceptions import RoomNotAvailableError


class BookingLike(Protocol):
    check_in: date
    check_out: date


class AvailabilityChecker:
    """Check if a room is available for a requested date range."""

    def is_available(self, requested: DateRange, existing_bookings: Iterable[BookingLike]) -> bool:
        for booking in existing_bookings:
            if self._overlaps(requested, booking):
                return False
        return True

    def ensure_available(self, requested: DateRange, existing_bookings: Iterable[BookingLike]) -> None:
        if not self.is_available(requested, existing_bookings):
            raise RoomNotAvailableError("Room is not available for the requested dates.")

    @staticmethod
    def _overlaps(requested: DateRange, booking: BookingLike) -> bool:
        return not (requested.check_out <= booking.check_in or requested.check_in >= booking.check_out)
