from dataclasses import replace
from datetime import date, timedelta

import pytest

from adventurestay_utils import (
    AdventureBooking,
    AdventurePackage,
    PackageAvailabilityChecker,
    PackageBookingValidator,
    PackageNotAvailableError,
)


def sample_package(**overrides):
    base = AdventurePackage(
        package_id="PKG1",
        category="LODGING",
        name="Jungle Lodge",
        location="Kanha",
        base_price_per_night=150.0,
        max_guests=6,
        min_nights=1,
        max_nights=7,
        includes_meals=True,
        includes_guide=True,
    )
    return replace(base, **overrides)


def make_booking(package, start_date, end_date, guests):
    nights = PackageBookingValidator.validate_dates(start_date, end_date, package)
    return AdventureBooking(
        package=package,
        start_date=start_date,
        end_date=end_date,
        num_guests=guests,
        nights=nights,
        total_price=0.0,
    )


def test_non_overlapping_bookings_allowed():
    package = sample_package()
    existing = [
        make_booking(package, date(2025, 1, 1), date(2025, 1, 3), 3),
    ]
    request = PackageBookingValidator.create_booking_request(
        package, date(2025, 1, 5), date(2025, 1, 7), 2
    )
    checker = PackageAvailabilityChecker()
    checker.check_availability(request, package, existing)


def test_overlapping_bookings_raise_error():
    package = sample_package()
    existing = [
        make_booking(package, date(2025, 1, 1), date(2025, 1, 3), 5),
    ]
    request = PackageBookingValidator.create_booking_request(
        package, date(2025, 1, 2), date(2025, 1, 4), 2
    )
    checker = PackageAvailabilityChecker()
    with pytest.raises(PackageNotAvailableError):
        checker.check_availability(request, package, existing)


def test_different_packages_can_coexist():
    package = sample_package()
    other_package = sample_package(package_id="PKG2")
    existing = [
        make_booking(other_package, date(2025, 1, 1), date(2025, 1, 4), 5),
    ]
    request = PackageBookingValidator.create_booking_request(
        package, date(2025, 1, 2), date(2025, 1, 5), 3
    )
    checker = PackageAvailabilityChecker()
    checker.check_availability(request, package, existing)


def test_capacity_exceeded_with_overlap():
    package = sample_package(max_guests=6)
    existing = [
        make_booking(package, date(2025, 3, 1), date(2025, 3, 4), 4),
    ]
    request = PackageBookingValidator.create_booking_request(
        package, date(2025, 3, 2), date(2025, 3, 5), 3
    )
    checker = PackageAvailabilityChecker()
    with pytest.raises(PackageNotAvailableError):
        checker.check_availability(request, package, existing)
