"""
Production-Grade ORM Optimization Validation

This script validates:
1. Dashboard querysets use correct ORM optimization
2. ADR calculations use base_price (not total_price)
3. Active stay logic excludes checkout day
4. Occupancy percentages are mathematically correct
5. Zero-division protection works
6. Helper methods are unit-testable
"""

import os
import sys
import django
from datetime import date, timedelta
from decimal import Decimal

# Setup Django
sys.path.insert(0, '/var/www/html/aimantis/backend')
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')
django.setup()

from bookings.models import Booking
from dashboard.services.dashboard_metrics_service import (
    is_active_stay_on_date,
    calculate_occupancy_percentage,
    calculate_adr_from_bookings,
    calculate_per_night_revenue,
    expand_booking_to_revenue_nights,
    get_bookings_for_window,
    calculate_adr_for_window,
)
from dashboard.services.utils import get_today


def test_active_stay_logic():
    """Test active stay logic with checkout day exclusion."""
    print("\n" + "="*80)
    print("TEST 1: Active Stay Logic (checkout day exclusion)")
    print("="*80)
    
    # Booking: May 14-19 (5 nights)
    check_in = date(2026, 5, 14)
    check_out = date(2026, 5, 19)
    
    test_cases = [
        (date(2026, 5, 13), False, "Before check-in"),
        (date(2026, 5, 14), True, "Check-in day (inclusive)"),
        (date(2026, 5, 15), True, "During stay"),
        (date(2026, 5, 16), True, "During stay"),
        (date(2026, 5, 17), True, "During stay"),
        (date(2026, 5, 18), True, "Day before checkout"),
        (date(2026, 5, 19), False, "Checkout day (EXCLUSIVE)"),
        (date(2026, 5, 20), False, "After checkout"),
    ]
    
    all_passed = True
    for test_date, expected, description in test_cases:
        result = is_active_stay_on_date(check_in, check_out, test_date)
        status = "✓" if result == expected else "✗"
        if result != expected:
            all_passed = False
        print(f"{status} {test_date.isoformat()}: {description} -> {result} (expected {expected})")
    
    if all_passed:
        print("\n✓ All active stay logic tests passed!")
    else:
        print("\n✗ Some active stay logic tests failed!")
    
    return all_passed


def test_occupancy_calculation():
    """Test occupancy percentage calculation with zero-division protection."""
    print("\n" + "="*80)
    print("TEST 2: Occupancy Calculation (zero-division protection)")
    print("="*80)
    
    test_cases = [
        (20, 100, 20.0, "Normal case: 20/100"),
        (0, 100, 0.0, "Zero occupied"),
        (50, 0, 0.0, "Zero total (defensive)"),
        (100, 100, 100.0, "Full occupancy"),
        (33, 100, 33.0, "Partial occupancy"),
        (1, 3, 33.33, "Rounding test"),
    ]
    
    all_passed = True
    for occupied, total, expected, description in test_cases:
        result = calculate_occupancy_percentage(occupied, total)
        status = "✓" if result == expected else "✗"
        if result != expected:
            all_passed = False
        print(f"{status} {description}: {result}% (expected {expected}%)")
    
    if all_passed:
        print("\n✓ All occupancy calculation tests passed!")
    else:
        print("\n✗ Some occupancy calculation tests failed!")
    
    return all_passed


def test_per_night_revenue():
    """Test per-night revenue calculation using base_price."""
    print("\n" + "="*80)
    print("TEST 3: Per-Night Revenue (base_price, NOT total_price)")
    print("="*80)
    
    # Create mock booking object
    class MockBooking:
        def __init__(self, base_price, length_of_stay):
            self.base_price = base_price
            self.length_of_stay = length_of_stay
    
    test_cases = [
        (Decimal('270'), 5, Decimal('54'), "270 / 5 = 54"),
        (Decimal('500'), 10, Decimal('50'), "500 / 10 = 50"),
        (Decimal('0'), 5, Decimal('0'), "Zero base price"),
        (None, 5, Decimal('0'), "None base price"),
        (Decimal('100'), 0, Decimal('0'), "Zero length of stay"),
    ]
    
    all_passed = True
    for base_price, nights, expected, description in test_cases:
        booking = MockBooking(base_price, nights)
        result = calculate_per_night_revenue(booking)
        status = "✓" if result == expected else "✗"
        if result != expected:
            all_passed = False
        print(f"{status} {description}: {result} (expected {expected})")
    
    if all_passed:
        print("\n✓ All per-night revenue tests passed!")
    else:
        print("\n✗ Some per-night revenue tests failed!")
    
    return all_passed


def test_revenue_night_expansion():
    """Test booking expansion to individual revenue nights."""
    print("\n" + "="*80)
    print("TEST 4: Revenue Night Expansion (stay-night logic)")
    print("="*80)
    
    class MockBooking:
        def __init__(self, booking_id, property_id, check_in, check_out, base_price, length_of_stay):
            self.id = booking_id
            self.property_id = property_id
            self.check_in_date = check_in
            self.check_out_date = check_out
            self.base_price = base_price
            self.length_of_stay = length_of_stay
    
    # Booking: May 14-19, base_price=270, 5 nights -> 54/night
    booking = MockBooking(
        booking_id=1,
        property_id=21,
        check_in=date(2026, 5, 14),
        check_out=date(2026, 5, 19),
        base_price=Decimal('270'),
        length_of_stay=5,
    )
    
    # Expand for single day (today only)
    window_start = date(2026, 5, 14)
    window_end = date(2026, 5, 15)
    
    revenue_nights = expand_booking_to_revenue_nights(booking, window_start, window_end)
    
    all_passed = True
    
    # Test 1: Single day expansion
    if len(revenue_nights) == 1:
        print(f"✓ Single day expansion: 1 revenue night")
    else:
        print(f"✗ Single day expansion: {len(revenue_nights)} nights (expected 1)")
        all_passed = False
    
    if revenue_nights[0].revenue == Decimal('54'):
        print(f"✓ Per-night revenue: {revenue_nights[0].revenue} (expected 54)")
    else:
        print(f"✗ Per-night revenue: {revenue_nights[0].revenue} (expected 54)")
        all_passed = False
    
    # Test 2: Multi-day expansion
    window_start = date(2026, 5, 14)
    window_end = date(2026, 5, 19)
    
    revenue_nights = expand_booking_to_revenue_nights(booking, window_start, window_end)
    
    if len(revenue_nights) == 5:
        print(f"✓ Multi-day expansion: 5 revenue nights")
    else:
        print(f"✗ Multi-day expansion: {len(revenue_nights)} nights (expected 5)")
        all_passed = False
    
    total_revenue = sum(night.revenue for night in revenue_nights)
    if total_revenue == Decimal('270'):
        print(f"✓ Total revenue: {total_revenue} (expected 270)")
    else:
        print(f"✗ Total revenue: {total_revenue} (expected 270)")
        all_passed = False
    
    if all_passed:
        print("\n✓ All revenue night expansion tests passed!")
    else:
        print("\n✗ Some revenue night expansion tests failed!")
    
    return all_passed


def test_queryset_optimization():
    """Test that querysets don't use unnecessary select_related."""
    print("\n" + "="*80)
    print("TEST 5: Queryset ORM Optimization")
    print("="*80)
    
    # Read dashboard_metrics_service.py to verify no select_related
    with open('/var/www/html/aimantis/backend/dashboard/services/dashboard_metrics_service.py', 'r') as f:
        content = f.read()
    
    all_passed = True
    
    # Check that select_related is NOT used in dashboard_metrics_service
    if '.select_related(' in content:
        print("✗ dashboard_metrics_service.py still uses select_related (should be removed)")
        all_passed = False
    else:
        print("✓ dashboard_metrics_service.py does NOT use select_related (correct)")
    
    # Check that base_price is used instead of total_price
    if "'base_price'" in content or '"base_price"' in content:
        print("✓ dashboard_metrics_service.py uses base_price for ADR (correct)")
    else:
        print("✗ dashboard_metrics_service.py does not use base_price")
        all_passed = False
    
    # Check upcoming_events_service.py
    with open('/var/www/html/aimantis/backend/dashboard/services/upcoming_events_service.py', 'r') as f:
        events_content = f.read()
    
    if '.select_related("property", "property_type")' in events_content:
        print("✗ upcoming_events_service.py still uses select_related for property/property_type")
        all_passed = False
    else:
        print("✓ upcoming_events_service.py does NOT use unnecessary select_related (correct)")
    
    if all_passed:
        print("\n✓ All queryset optimization tests passed!")
    else:
        print("\n✗ Some queryset optimization tests failed!")
    
    return all_passed


def test_real_database_data():
    """Test with real database data if available."""
    print("\n" + "="*80)
    print("TEST 6: Real Database Data Validation")
    print("="*80)
    
    today = get_today()
    
    # Check if there are any bookings in the database
    total_bookings = Booking.objects.count()
    print(f"Total bookings in database: {total_bookings}")
    
    if total_bookings == 0:
        print("⚠ No bookings in database, skipping real data tests")
        return True
    
    # Test ADR calculation
    try:
        adr_today = calculate_adr_for_window(
            structure_id=None,
            window_start=today,
            window_end=today + timedelta(days=1),
            only_checked_in=True,
        )
        print(f"✓ ADR today calculation successful: {adr_today}")
        
        adr_7_days = calculate_adr_for_window(
            structure_id=None,
            window_start=today,
            window_end=today + timedelta(days=7),
            only_checked_in=False,
        )
        print(f"✓ ADR 7 days calculation successful: {adr_7_days}")
        
        return True
    except Exception as e:
        print(f"✗ ADR calculation failed with error: {e}")
        import traceback
        traceback.print_exc()
        return False


def main():
    """Run all validation tests."""
    print("\n" + "="*80)
    print("PRODUCTION-GRADE ORM OPTIMIZATION VALIDATION")
    print("="*80)
    
    results = {
        "Active Stay Logic": test_active_stay_logic(),
        "Occupancy Calculation": test_occupancy_calculation(),
        "Per-Night Revenue": test_per_night_revenue(),
        "Revenue Night Expansion": test_revenue_night_expansion(),
        "Queryset Optimization": test_queryset_optimization(),
        "Real Database Data": test_real_database_data(),
    }
    
    print("\n" + "="*80)
    print("VALIDATION SUMMARY")
    print("="*80)
    
    for test_name, passed in results.items():
        status = "✓ PASSED" if passed else "✗ FAILED"
        print(f"{status}: {test_name}")
    
    all_passed = all(results.values())
    
    print("\n" + "="*80)
    if all_passed:
        print("✓ ALL TESTS PASSED - Production-ready!")
    else:
        print("✗ SOME TESTS FAILED - Requires attention")
    print("="*80 + "\n")
    
    return 0 if all_passed else 1


if __name__ == "__main__":
    sys.exit(main())
