#!/usr/bin/env python3
"""
Script to seed sample bookings for testing check-in/check-out and housekeeping notifications.
"""

import sys
import os
from pathlib import Path
# Add both the seeds_data directory and the Backend directory to the path
sys.path.insert(0, str(Path(__file__).parent))
sys.path.insert(0, str(Path(__file__).parent.parent))
from sqlalchemy.orm import Session
from sqlalchemy import and_
from src.shared.config.database import SessionLocal
# Import all models needed for SQLAlchemy relationship setup
# Import base models first
from src.auth.models.role import Role
from src.auth.models.user import User
from src.rooms.models.room import Room, RoomStatus
from src.rooms.models.room_type import RoomType  # For Room relationship
from src.rooms.models.rate_plan import RatePlan  # For RoomType relationship
from src.rooms.models.room_maintenance import RoomMaintenance  # For Room relationship
from src.rooms.models.room_inspection import RoomInspection  # For Room relationship
from src.rooms.models.room_attribute import RoomAttribute  # For Room relationship
from src.hotel_services.models.housekeeping_task import HousekeepingTask  # For Room relationship
from src.bookings.models.booking import Booking, BookingStatus
from src.bookings.models.group_booking import GroupBooking  # For Booking relationship

# Import all related models to satisfy SQLAlchemy relationships
# This is necessary because SQLAlchemy needs all related models loaded
try:
    from src.auth.models.refresh_token import RefreshToken
    from src.reviews.models.review import Review
    from src.reviews.models.favorite import Favorite
    from src.hotel_services.models.service import Service  # For ServiceBooking relationship
    from src.hotel_services.models.service_booking import ServiceBooking
    from src.hotel_services.models.service_usage import ServiceUsage  # For Booking relationship
    from src.bookings.models.checkin_checkout import CheckInCheckOut
    from src.payments.models.payment import Payment
    from src.payments.models.invoice import Invoice
    from src.ai.models.chat import Chat
    from src.loyalty.models.user_loyalty import UserLoyalty
    from src.loyalty.models.loyalty_tier import LoyaltyTier  # For UserLoyalty relationship
    from src.loyalty.models.loyalty_point_transaction import LoyaltyPointTransaction  # For UserLoyalty relationship
    from src.loyalty.models.referral import Referral
    from src.loyalty.models.package import Package  # For RoomType relationship
    from src.guest_management.models.guest_preference import GuestPreference
    from src.guest_management.models.guest_note import GuestNote
    from src.guest_management.models.guest_communication import GuestCommunication
    from src.guest_management.models.guest_tag import GuestTag, guest_tag_association
    from src.guest_management.models.guest_segment import GuestSegment, guest_segment_association
    # Import any other models that might be related
except ImportError:
    pass  # Some models might not exist, that's okay
from datetime import datetime, timedelta
import random
import secrets

def get_db():
    db = SessionLocal()
    try:
        return db
    finally:
        pass

def generate_booking_number() -> str:
    """Generate a unique booking number"""
    prefix = 'BK'
    ts = int(datetime.utcnow().timestamp() * 1000)
    rand = secrets.randbelow(9000) + 1000
    return f'{prefix}-{ts}-{rand}'

def seed_bookings(db: Session):
    print('=' * 80)
    print('SEEDING SAMPLE BOOKINGS FOR TESTING')
    print('=' * 80)
    
    # Get roles
    customer_role = db.query(Role).filter(Role.name == 'customer').first()
    staff_role = db.query(Role).filter(Role.name == 'staff').first()
    admin_role = db.query(Role).filter(Role.name == 'admin').first()
    
    if not customer_role:
        print('  ❌ Customer role not found! Please seed roles first.')
        return
    
    # Get customers
    customers = db.query(User).filter(User.role_id == customer_role.id).all()
    if not customers:
        print('  ❌ No customer users found! Please seed users first.')
        return
    
    # Get available rooms
    rooms = db.query(Room).all()
    if not rooms:
        print('  ❌ No rooms found! Please seed rooms first.')
        return
    
    print(f'\n✓ Found {len(customers)} customer(s) and {len(rooms)} room(s)')
    
    # Delete existing bookings (optional - comment out if you want to keep existing bookings)
    existing_bookings = db.query(Booking).all()
    if existing_bookings:
        print(f'\n🗑️  Deleting {len(existing_bookings)} existing booking(s)...')
        booking_ids = [b.id for b in existing_bookings]
        
        # Delete related records first to avoid foreign key constraints
        try:
            from src.guest_management.models.guest_complaint import GuestComplaint, ComplaintUpdate
            complaints = db.query(GuestComplaint).filter(GuestComplaint.booking_id.in_(booking_ids)).all()
            if complaints:
                complaint_ids = [c.id for c in complaints]
                # Delete complaint updates first
                updates = db.query(ComplaintUpdate).filter(ComplaintUpdate.complaint_id.in_(complaint_ids)).all()
                if updates:
                    for update in updates:
                        db.delete(update)
                    print(f'  ✓ Deleted {len(updates)} complaint update(s)')
                # Then delete complaints
                for complaint in complaints:
                    db.delete(complaint)
                print(f'  ✓ Deleted {len(complaints)} guest complaint(s)')
        except ImportError:
            pass
        
        for booking in existing_bookings:
            db.delete(booking)
        db.commit()
        print(f'✓ Deleted {len(existing_bookings)} booking(s)')
    
    # Create sample bookings with different statuses
    now = datetime.utcnow()
    bookings_data = []
    
    # 1. Past bookings (checked out) - These should trigger cleaning notifications
    print('\n📅 Creating past bookings (checked out)...')
    for i in range(3):
        room = random.choice(rooms)
        customer = random.choice(customers)
        
        # Check-out was 1-3 days ago
        days_ago = random.randint(1, 3)
        check_out_date = now - timedelta(days=days_ago)
        check_in_date = check_out_date - timedelta(days=random.randint(1, 5))
        
        # Calculate price
        base_price = float(room.price) if room.price else 100.0
        num_nights = (check_out_date - check_in_date).days
        total_price = base_price * num_nights
        
        booking = Booking(
            booking_number=generate_booking_number(),
            user_id=customer.id,
            room_id=room.id,
            check_in_date=check_in_date,
            check_out_date=check_out_date,
            num_guests=random.randint(1, min(room.capacity, 4)),
            total_price=total_price,
            status=BookingStatus.checked_out,
            deposit_paid=True,
            requires_deposit=False,
            special_requests=f'Sample booking for testing - Checked out {days_ago} day(s) ago'
        )
        db.add(booking)
        db.flush()  # Flush to get booking ID
        
        # Set room status to cleaning for checked out bookings
        # Check if there's active maintenance first
        try:
            from src.rooms.models.room_maintenance import RoomMaintenance, MaintenanceStatus
            active_maintenance = db.query(RoomMaintenance).filter(
                and_(
                    RoomMaintenance.room_id == room.id,
                    RoomMaintenance.blocks_room == True,
                    RoomMaintenance.status.in_([MaintenanceStatus.scheduled, MaintenanceStatus.in_progress])
                )
            ).first()
            if not active_maintenance:
                room.status = RoomStatus.cleaning
                
                # Create housekeeping task for checkout cleaning
                try:
                    from src.hotel_services.models.housekeeping_task import HousekeepingTask, HousekeepingStatus, HousekeepingType
                    checkout_checklist = [
                        {'item': 'Bathroom cleaned', 'completed': False, 'notes': ''},
                        {'item': 'Beds made with fresh linens', 'completed': False, 'notes': ''},
                        {'item': 'Trash emptied', 'completed': False, 'notes': ''},
                        {'item': 'Towels replaced', 'completed': False, 'notes': ''},
                        {'item': 'Amenities restocked', 'completed': False, 'notes': ''},
                        {'item': 'Floor vacuumed and mopped', 'completed': False, 'notes': ''},
                        {'item': 'Surfaces dusted', 'completed': False, 'notes': ''},
                        {'item': 'Windows and mirrors cleaned', 'completed': False, 'notes': ''},
                    ]
                    
                    housekeeping_task = HousekeepingTask(
                        room_id=room.id,
                        booking_id=booking.id,
                        task_type=HousekeepingType.checkout,
                        status=HousekeepingStatus.pending,
                        scheduled_time=datetime.utcnow(),
                        created_by=admin_role.id if admin_role else (staff_role.id if staff_role else None),
                        checklist_items=checkout_checklist,
                        notes=f'Auto-created on checkout for booking {booking.booking_number}',
                        estimated_duration_minutes=45
                    )
                    db.add(housekeeping_task)
                except ImportError:
                    pass  # If housekeeping models not available, skip task creation
        except ImportError:
            # If maintenance model not available, just set to cleaning
            room.status = RoomStatus.cleaning
        bookings_data.append({
            'number': booking.booking_number,
            'room': room.room_number,
            'status': 'checked_out',
            'check_out': check_out_date.strftime('%Y-%m-%d')
        })
        print(f'  ✓ Created booking {booking.booking_number} - Room {room.room_number}, Checked out {days_ago} day(s) ago')
    
    # 2. Current bookings (checked in) - Guests currently staying
    print('\n📅 Creating current bookings (checked in)...')
    for i in range(2):
        room = random.choice(rooms)
        customer = random.choice(customers)
        
        # Checked in 1-3 days ago, checking out in 1-3 days
        days_ago = random.randint(1, 3)
        check_in_date = now - timedelta(days=days_ago)
        check_out_date = now + timedelta(days=random.randint(1, 3))
        
        base_price = float(room.price) if room.price else 100.0
        num_nights = (check_out_date - check_in_date).days
        total_price = base_price * num_nights
        
        booking = Booking(
            booking_number=generate_booking_number(),
            user_id=customer.id,
            room_id=room.id,
            check_in_date=check_in_date,
            check_out_date=check_out_date,
            num_guests=random.randint(1, min(room.capacity, 4)),
            total_price=total_price,
            status=BookingStatus.checked_in,
            deposit_paid=True,
            requires_deposit=False,
            special_requests=f'Sample booking for testing - Currently checked in'
        )
        db.add(booking)
        db.flush()  # Flush to get booking ID
        
        # Set room status to occupied for checked in bookings
        room.status = RoomStatus.occupied
        bookings_data.append({
            'number': booking.booking_number,
            'room': room.room_number,
            'status': 'checked_in',
            'check_out': check_out_date.strftime('%Y-%m-%d')
        })
        print(f'  ✓ Created booking {booking.booking_number} - Room {room.room_number}, Checked in {days_ago} day(s) ago')
    
    # 3. Future bookings (confirmed) - Upcoming reservations
    print('\n📅 Creating future bookings (confirmed)...')
    for i in range(3):
        room = random.choice(rooms)
        customer = random.choice(customers)
        
        # Check-in in 1-7 days, staying for 2-5 days
        days_ahead = random.randint(1, 7)
        check_in_date = now + timedelta(days=days_ahead)
        check_out_date = check_in_date + timedelta(days=random.randint(2, 5))
        
        base_price = float(room.price) if room.price else 100.0
        num_nights = (check_out_date - check_in_date).days
        total_price = base_price * num_nights
        
        booking = Booking(
            booking_number=generate_booking_number(),
            user_id=customer.id,
            room_id=room.id,
            check_in_date=check_in_date,
            check_out_date=check_out_date,
            num_guests=random.randint(1, min(room.capacity, 4)),
            total_price=total_price,
            status=BookingStatus.confirmed,
            deposit_paid=random.choice([True, False]),
            requires_deposit=random.choice([True, False]),
            special_requests=f'Sample booking for testing - Future reservation'
        )
        db.add(booking)
        bookings_data.append({
            'number': booking.booking_number,
            'room': room.room_number,
            'status': 'confirmed',
            'check_in': check_in_date.strftime('%Y-%m-%d')
        })
        print(f'  ✓ Created booking {booking.booking_number} - Room {room.room_number}, Check-in in {days_ahead} day(s)')
    
    db.commit()
    
    print(f'\n✅ Successfully created {len(bookings_data)} sample bookings!')
    print(f'\n📊 Summary:')
    checked_out = sum(1 for b in bookings_data if b['status'] == 'checked_out')
    checked_in = sum(1 for b in bookings_data if b['status'] == 'checked_in')
    confirmed = sum(1 for b in bookings_data if b['status'] == 'confirmed')
    print(f'  - Checked out: {checked_out} (rooms should be in cleaning status)')
    print(f'  - Checked in: {checked_in} (guests currently staying)')
    print(f'  - Confirmed: {confirmed} (upcoming reservations)')
    print('\n💡 To test notifications:')
    print('  1. Log in as staff user (staff@gnxsoft.com / staff123)')
    print('  2. Go to Bookings and mark a checked_in booking as checked_out')
    print('  3. Log in as housekeeping user (housekeeping@gnxsoft.com / P4eli240453.)')
    print('  4. You should receive a notification about the room needing cleaning')
    print('=' * 80)

def main():
    db = get_db()
    try:
        seed_bookings(db)
    except Exception as e:
        print(f'\n❌ Error: {e}')
        import traceback
        traceback.print_exc()
        db.rollback()
    finally:
        db.close()

if __name__ == '__main__':
    main()

