from fastapi import FastAPI from dotenv import load_dotenv from starlette.middleware.cors import CORSMiddleware from motor.motor_asyncio import AsyncIOMotorClient import os import logging from pathlib import Path from auth import hash_password from datetime import datetime # Import route modules from routes import auth_routes, destination_routes, special_routes, other_routes ROOT_DIR = Path(__file__).parent load_dotenv(ROOT_DIR / '.env') # MongoDB connection mongo_url = os.environ['MONGO_URL'] client = AsyncIOMotorClient(mongo_url) db = client[os.environ['DB_NAME']] # Inject database into route modules auth_routes.set_db(db) destination_routes.set_db(db) special_routes.set_db(db) other_routes.set_db(db) # Create the main app app = FastAPI(title="Epic Travel & Destinations API") # Include routers app.include_router(auth_routes.router) app.include_router(destination_routes.router) app.include_router(special_routes.router) app.include_router(other_routes.router) # Health check endpoint @app.get("/api") async def root(): return {"message": "Epic Travel API is running", "status": "healthy"} app.add_middleware( CORSMiddleware, allow_credentials=True, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"], ) # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) @app.on_event("startup") async def startup_db_client(): """Initialize database with seed data if empty""" try: # Check if admin user exists, if not create one admin_exists = await db.admin_users.find_one({"email": "admin@epictravel.com"}) if not admin_exists: admin_data = { "id": "admin-1", "email": "admin@epictravel.com", "password_hash": hash_password(os.environ['ADMIN_DEFAULT_PASSWORD']), "created_at": datetime.utcnow() } await db.admin_users.insert_one(admin_data) logger.info("Default admin user created") # Check if destinations exist, if not seed initial data dest_count = await db.destinations.count_documents({}) if dest_count == 0: # Seed initial destinations initial_destinations = [ { "id": "1", "name": "Paris", "location": "France", "description": "Experience the romance and elegance of the City of Light. Visit iconic landmarks like the Eiffel Tower, Louvre Museum, and stroll along the Champs-Élysées.", "image": "https://images.unsplash.com/photo-1502602898657-3e91760cbb34?w=800&q=80", "category": "City", "rating": 4.9, "price": 1299, "currency": "USD", "created_at": datetime.utcnow() }, { "id": "2", "name": "Bali", "location": "Indonesia", "description": "Discover tropical paradise with stunning beaches, ancient temples, lush rice terraces, and vibrant culture in this Indonesian gem.", "image": "https://images.unsplash.com/photo-1537996194471-e657df975ab4?w=800&q=80", "category": "Beach", "rating": 4.8, "price": 899, "currency": "USD", "created_at": datetime.utcnow() }, { "id": "3", "name": "Tokyo", "location": "Japan", "description": "Immerse yourself in the perfect blend of ancient tradition and cutting-edge technology in Japan's bustling capital city.", "image": "https://images.unsplash.com/photo-1540959733332-eab4deabeeaf?w=800&q=80", "category": "City", "rating": 4.9, "price": 1499, "currency": "USD", "created_at": datetime.utcnow() }, { "id": "4", "name": "Santorini", "location": "Greece", "description": "Marvel at breathtaking sunsets, whitewashed buildings, and crystal-clear waters in this stunning Greek island paradise.", "image": "https://images.unsplash.com/photo-1613395877344-13d4a8e0d49e?w=800&q=80", "category": "Beach", "rating": 4.9, "price": 1199, "currency": "USD", "created_at": datetime.utcnow() }, { "id": "5", "name": "Iceland", "location": "Iceland", "description": "Witness the Northern Lights, explore glaciers, geysers, and volcanic landscapes in this land of fire and ice.", "image": "https://images.unsplash.com/photo-1504829857797-ddff29c27927?w=800&q=80", "category": "Adventure", "rating": 4.8, "price": 1699, "currency": "USD", "created_at": datetime.utcnow() }, { "id": "6", "name": "Dubai", "location": "UAE", "description": "Experience luxury and innovation in the desert with world-class shopping, stunning architecture, and endless entertainment.", "image": "https://images.unsplash.com/photo-1512453979798-5ea266f8880c?w=800&q=80", "category": "City", "rating": 4.7, "price": 1399, "currency": "USD", "created_at": datetime.utcnow() }, { "id": "7", "name": "Maldives", "location": "Maldives", "description": "Relax in overwater bungalows, dive in pristine coral reefs, and enjoy the ultimate tropical island getaway.", "image": "https://images.unsplash.com/photo-1514282401047-d79a71a590e8?w=800&q=80", "category": "Beach", "rating": 5.0, "price": 2199, "currency": "USD", "created_at": datetime.utcnow() }, { "id": "8", "name": "New York", "location": "USA", "description": "Explore the city that never sleeps with iconic landmarks, world-class museums, Broadway shows, and diverse neighborhoods.", "image": "https://images.unsplash.com/photo-1496442226666-8d4d0e62e6e9?w=800&q=80", "category": "City", "rating": 4.8, "price": 1099, "currency": "USD", "created_at": datetime.utcnow() }, { "id": "9", "name": "Machu Picchu", "location": "Peru", "description": "Trek to the ancient Incan citadel nestled high in the Andes Mountains, one of the New Seven Wonders of the World.", "image": "https://images.unsplash.com/photo-1587595431973-160d0d94add1?w=800&q=80", "category": "Adventure", "rating": 4.9, "price": 1299, "currency": "USD", "created_at": datetime.utcnow() }, { "id": "10", "name": "Swiss Alps", "location": "Switzerland", "description": "Ski pristine slopes, hike mountain trails, and enjoy charming alpine villages with breathtaking mountain vistas.", "image": "https://images.unsplash.com/photo-1531366936337-7c912a4589a7?w=800&q=80", "category": "Adventure", "rating": 4.9, "price": 1799, "currency": "USD", "created_at": datetime.utcnow() }, { "id": "11", "name": "Venice", "location": "Italy", "description": "Glide through romantic canals, admire Renaissance architecture, and savor authentic Italian cuisine in this unique floating city.", "image": "https://images.unsplash.com/photo-1523906834658-6e24ef2386f9?w=800&q=80", "category": "City", "rating": 4.8, "price": 1149, "currency": "USD", "created_at": datetime.utcnow() }, { "id": "12", "name": "Safari Kenya", "location": "Kenya", "description": "Witness the Great Migration, spot the Big Five, and experience the raw beauty of African wilderness.", "image": "https://images.unsplash.com/photo-1516426122078-c23e76319801?w=800&q=80", "category": "Adventure", "rating": 4.9, "price": 2499, "currency": "USD", "created_at": datetime.utcnow() } ] await db.destinations.insert_many(initial_destinations) logger.info(f"Seeded {len(initial_destinations)} initial destinations") # Seed initial specials initial_specials = [ { "id": "special-1", "destination_id": "2", "discount": 25, "end_date": "2025-02-28", "highlights": ["Free spa treatment", "Complimentary airport transfer", "Sunset dinner cruise"], "created_at": datetime.utcnow() }, { "id": "special-2", "destination_id": "4", "discount": 30, "end_date": "2025-03-15", "highlights": ["Wine tasting tour", "Private yacht excursion", "Luxury accommodation upgrade"], "created_at": datetime.utcnow() }, { "id": "special-3", "destination_id": "7", "discount": 20, "end_date": "2025-02-20", "highlights": ["Snorkeling adventure", "Couples massage", "Romantic beach dinner"], "created_at": datetime.utcnow() } ] await db.specials.insert_many(initial_specials) logger.info(f"Seeded {len(initial_specials)} initial specials") except Exception as e: logger.error(f"Error during startup: {str(e)}") @app.on_event("shutdown") async def shutdown_db_client(): client.close()