#!/usr/bin/env python3
"""
Athens Restaurant Data Generator
Since TripAdvisor blocks scraping, we'll generate realistic restaurant data
based on actual Athens restaurant types and Greek cuisine
"""

import json
import os
import uuid
import random
import time
from datetime import datetime, time as dt_time
from urllib.parse import quote_plus
from sqlalchemy import create_engine, text
from typing import List, Dict
import urllib.request

class AthensRestaurantGenerator:
    """Generate realistic Athens restaurant data"""
    
    def __init__(self):
        # Database connection
        self.DATABASE_URL = f"postgresql://postgres:{quote_plus('F@f@k0s!!')}@localhost:5432/bookbeach"
        self.engine = create_engine(self.DATABASE_URL)
        
        # Photo directory
        self.photo_dir = "restaurant_photos"
        os.makedirs(self.photo_dir, exist_ok=True)
        
        # Athens restaurant data
        self.restaurant_names = [
            "Thanasis", "Dionysos", "Funky Gourmet", "Spondi", "CTC", "Hytra", "Tudor Hall",
            "Varoulko Seaside", "Aleria", "Boschetto", "Kuzina", "Electra Roof Garden",
            "GB Roof Garden", "Point a Bar", "Strofi", "Psyrri Taverna", "Plaka Garden",
            "Philos Athens", "Atomium", "Lefteris o Politikos", "Thanasis Kebab",
            "Ta Karamanlidika tou Fani", "Liondi Traditional Greek", "Nolan",
            "Piato", "Cookoovaya", "Mironi", "Daphne's", "Psaras Taverna",
            "Maiandros", "Scholarhio", "Keelings", "Athenaeum InterContinental",
            "Matsuhisa Athens", "Balthazar", "Orizontes", "Akrotiri Lounge",
            "Life Gallery Athens", "Penthouse", "Dinner in the Sky", "Blue Pine",
            "Premiere", "Yafka", "Kanella", "Estiatorio Milos", "Seychelles",
            "Jimmy & the Fish", "Island Club Restaurant", "Macelleria",
            "Al Convento", "L'Abreuvoir", "La Scala", "Baba au Rum", "Monsieur Paul",
            "Pil Poul", "Telaro", "Nobu Athens", "Catch Bar Restaurant", "Artisanal",
            "Cellier Le Bistrot", "Clemente VIII", "Mamacas", "Roka", "Black Duck",
            "Alatsi", "Bread & Roses", "Fabrica de Vino", "Manouka", "Byzantino",
            "Andreas Restaurant", "Ergon House Athens", "Vezene", "Kastelorizo",
            "Salero", "Athiri Santorini", "Klimataria", "Ammos Estiatorio",
            "Moorings", "Selene", "Papadakis Restaurant", "Asterias Taverna",
            "Archeon Gefsis", "Kollias Restaurant", "Oikeio", "Ama Laxei Sto Melathron",
            "Fish Point", "Seven Jokers", "The Gatsby Athens", "Vintage Wine bar & Bistro",
            "Kiku", "Ostria", "Sardelles", "Noel", "By the Glass", "Gazi College",
            "Papaioannou", "Prosopa", "Barakos Estiatorio", "Psomi & Alati",
            "Gold Restaurant", "Paschalis", "Kapnikarea", "Athensreproducti", "Lukumades",
            "Cinco Jotas", "Tivoli", "Cookoovaya Mykonos", "Black Duck Garden",
            "Spilia", "Epsilon Restaurant", "Soil", "Alati", "Kremmydi",
            "Diverdi", "Cinque Wine & Deli Bar", "Seaven Art-i-Show", "BeeRaki",
            "Central Park", "Lotus Lounge", "Nolan Restaurant", "Okio",
            "Blue Lagoon Restaurant", "Fish Tavern Kavos", "Vosporos Fish Restaurant"
        ]
        
        self.cuisine_types = [
            "Greek", "Mediterranean", "Seafood", "Traditional Greek", "Modern Greek",
            "Italian", "International", "European", "Contemporary", "Fine Dining",
            "Taverna", "Mezze", "Souvlaki", "Grill", "Pizza", "Fusion"
        ]
        
        self.neighborhoods = [
            "Plaka", "Monastiraki", "Psyrri", "Kolonaki", "Exarchia", "Thiseio",
            "Koukaki", "Pangrati", "Glyfada", "Vouliagmeni", "Kifisia", "Marousi",
            "Piraeus", "Nea Smyrni", "Palaio Faliro", "Chalandri", "Agia Paraskevi",
            "Holargos", "Amarousi", "Vrilissia"
        ]
        
        self.greek_dishes = [
            {"name": "Moussaka", "price": 12.50, "category": "Main Course"},
            {"name": "Souvlaki", "price": 8.00, "category": "Grills"},
            {"name": "Greek Salad", "price": 7.50, "category": "Salads"},
            {"name": "Tzatziki", "price": 4.50, "category": "Appetizers"},
            {"name": "Dolmades", "price": 6.00, "category": "Appetizers"},
            {"name": "Spanakopita", "price": 5.50, "category": "Appetizers"},
            {"name": "Pastitsio", "price": 11.00, "category": "Main Course"},
            {"name": "Grilled Octopus", "price": 15.00, "category": "Seafood"},
            {"name": "Lamb Kleftiko", "price": 18.00, "category": "Main Course"},
            {"name": "Fried Calamari", "price": 12.00, "category": "Seafood"},
            {"name": "Feta Saganaki", "price": 6.50, "category": "Appetizers"},
            {"name": "Avgolemono Soup", "price": 5.00, "category": "Soups"},
            {"name": "Grilled Sea Bass", "price": 22.00, "category": "Seafood"},
            {"name": "Gemista", "price": 9.50, "category": "Main Course"},
            {"name": "Keftedes", "price": 7.00, "category": "Appetizers"},
            {"name": "Baklava", "price": 4.00, "category": "Desserts"},
            {"name": "Galaktoboureko", "price": 4.50, "category": "Desserts"},
            {"name": "Greek Coffee", "price": 2.50, "category": "Beverages"},
            {"name": "Ouzo", "price": 3.50, "category": "Beverages"},
            {"name": "Retsina Wine", "price": 4.00, "category": "Beverages"},
            {"name": "Grilled Lamb Chops", "price": 20.00, "category": "Main Course"},
            {"name": "Fassolada", "price": 6.50, "category": "Soups"},
            {"name": "Horiatiki Salad", "price": 8.00, "category": "Salads"},
            {"name": "Grilled Sardines", "price": 10.00, "category": "Seafood"},
            {"name": "Yemista Peppers", "price": 8.50, "category": "Main Course"}
        ]
        
        self.descriptions = [
            "Traditional Greek taverna serving authentic dishes in a cozy atmosphere",
            "Modern Greek cuisine with a contemporary twist on classic recipes",
            "Family-owned restaurant offering the best of Mediterranean flavors",
            "Elegant dining experience with panoramic views of the Acropolis",
            "Casual dining spot popular with locals for fresh seafood",
            "Historic taverna in the heart of Plaka serving traditional Greek food",
            "Upscale restaurant featuring innovative Greek cuisine",
            "Waterfront dining with spectacular sunset views",
            "Authentic Greek mezze and grilled specialties",
            "Fine dining establishment with award-winning cuisine",
            "Rustic taverna with live Greek music and dancing",
            "Modern bistro combining Greek and international flavors",
            "Rooftop restaurant with stunning city views",
            "Traditional psistaria specializing in grilled meats",
            "Cozy neighborhood restaurant with homestyle cooking"
        ]
    
    def generate_restaurant_data(self, count: int = 500) -> List[Dict]:
        """Generate realistic restaurant data"""
        restaurants = []
        used_names = set()
        
        for i in range(count):
            # Generate unique name
            base_name = random.choice(self.restaurant_names)
            if base_name in used_names:
                name = f"{base_name} {random.choice(self.neighborhoods)}"
            else:
                name = base_name
            used_names.add(name)
            
            # Generate restaurant details
            cuisine = random.choice(self.cuisine_types)
            neighborhood = random.choice(self.neighborhoods)
            
            # Some restaurants close at midnight
            if random.random() < 0.1:  # 10% chance
                closing_hour = 0  # Midnight
            else:
                closing_hour = random.randint(22, 23)
            
            restaurant = {
                'name': name,
                'description': random.choice(self.descriptions),
                'cuisine_type': cuisine,
                'address': f"{random.randint(1, 200)} {random.choice(['Adrianou', 'Ermou', 'Mitropoleos', 'Pandrossou', 'Kidathineon'])} St, {neighborhood}, Athens, Greece",
                'phone': f"+30 21 {random.randint(1000, 9999)} {random.randint(1000, 9999)}",
                'rating': round(random.uniform(3.5, 4.8), 1),
                'review_count': random.randint(50, 1500),
                'opening_time': dt_time(random.randint(11, 13), random.choice([0, 30])),
                'closing_time': dt_time(closing_hour, random.choice([0, 30])),
                'price_range': random.choice(['€', '€€', '€€€']),
                'photos': self.generate_photo_urls(name, random.randint(3, 8)),
                'menu_items': self.generate_menu_items(cuisine, random.randint(8, 25))
            }
            
            restaurants.append(restaurant)
            
            if (i + 1) % 50 == 0:
                print(f"📊 Generated {i + 1}/{count} restaurants")
        
        return restaurants
    
    def generate_photo_urls(self, restaurant_name: str, count: int) -> List[str]:
        """Generate placeholder photo URLs"""
        photos = []
        base_urls = [
            "https://picsum.photos/800/600",
            "https://source.unsplash.com/800x600/?restaurant,food,greek",
            "https://source.unsplash.com/800x600/?athens,taverna",
            "https://source.unsplash.com/800x600/?mediterranean,cuisine"
        ]
        
        for i in range(count):
            photos.append(f"{random.choice(base_urls)}&sig={random.randint(1, 1000)}")
        
        return photos
    
    def generate_menu_items(self, cuisine_type: str, count: int) -> List[Dict]:
        """Generate menu items based on cuisine type"""
        menu_items = []
        available_dishes = self.greek_dishes.copy()
        
        # Add some cuisine-specific variations
        if 'seafood' in cuisine_type.lower():
            seafood_multiplier = 2
            available_dishes = [dish for dish in available_dishes if 'seafood' in dish['category'].lower()] * seafood_multiplier + available_dishes
        
        selected_dishes = random.sample(available_dishes, min(count, len(available_dishes)))
        
        for dish in selected_dishes:
            # Add some price variation
            base_price = dish['price']
            price_variation = random.uniform(0.8, 1.3)
            final_price = round(base_price * price_variation, 2)
            
            menu_items.append({
                'name': dish['name'],
                'price': final_price,
                'category': dish['category'],
                'description': f"Traditional {dish['name'].lower()} prepared with fresh ingredients"
            })
        
        return menu_items
    
    def download_sample_photos(self, restaurants: List[Dict]):
        """Download sample photos for restaurants"""
        print("📷 Downloading sample photos...")
        
        for i, restaurant in enumerate(restaurants[:20]):  # Download for first 20 restaurants
            try:
                safe_name = restaurant['name'].replace(' ', '_').replace('/', '_')[:30]
                
                for j, photo_url in enumerate(restaurant['photos'][:3]):  # Max 3 photos per restaurant
                    try:
                        filename = f"{safe_name}_{j+1}.jpg"
                        filepath = os.path.join(self.photo_dir, filename)
                        
                        if not os.path.exists(filepath):
                            # Use a simple food photo URL
                            sample_url = f"https://picsum.photos/800/600?random={random.randint(1, 1000)}"
                            urllib.request.urlretrieve(sample_url, filepath)
                            print(f"   Downloaded: {filename}")
                        
                    except Exception as e:
                        print(f"   ⚠️ Photo download failed: {e}")
                        
            except Exception as e:
                print(f"   ❌ Error with restaurant {restaurant['name']}: {e}")
            
            time.sleep(0.5)  # Be polite to image services
    
    def save_to_database(self, restaurants: List[Dict]):
        """Save restaurants to database"""
        print("💾 Saving restaurants to database...")
        
        with self.engine.connect() as db:
            # Get company and currency info
            company_id = "c35388d2-0028-4002-bcc4-db4d7ed2042e"
            
            # Try to get Athens beach place
            beach_result = db.execute(text("SELECT beach_place_id FROM beach_places WHERE city ILIKE '%athens%' LIMIT 1")).fetchone()
            beach_place_id = beach_result[0] if beach_result else None
            
            currency_id = 1  # EUR
            
            successful_saves = 0
            
            for restaurant in restaurants:
                try:
                    # Check if already exists
                    existing = db.execute(text("SELECT 1 FROM restaurants WHERE restaurant_name = :name"), 
                                        {'name': restaurant['name']}).fetchone()
                    if existing:
                        print(f"⏭️ Skipped (exists): {restaurant['name']}")
                        continue
                    
                    restaurant_id = str(uuid.uuid4())
                    
                    # Insert restaurant
                    db.execute(text("""
                        INSERT INTO restaurants (
                            restaurant_id, restaurant_name, company_id, beach_place_id,
                            description, cuisine_type, opening_time, closing_time, is_active, created_at
                        ) VALUES (
                            :restaurant_id, :restaurant_name, :company_id, :beach_place_id,
                            :description, :cuisine_type, :opening_time, :closing_time, :is_active, NOW()
                        )
                    """), {
                        'restaurant_id': restaurant_id,
                        'restaurant_name': restaurant['name'],
                        'company_id': company_id,
                        'beach_place_id': beach_place_id,
                        'description': restaurant['description'],
                        'cuisine_type': restaurant['cuisine_type'],
                        'opening_time': restaurant['opening_time'],
                        'closing_time': restaurant['closing_time'],
                        'is_active': True
                    })
                    
                    # Create category
                    category_id = int(time.time() * 1000000) % 2000000000  # Unique ID
                    try:
                        db.execute(text("""
                            INSERT INTO restaurant_categories (
                                category_id, restaurant_id, category_name, description
                            ) VALUES (
                                :category_id, :restaurant_id, :category_name, :description
                            )
                        """), {
                            'category_id': category_id,
                            'restaurant_id': restaurant_id,
                            'category_name': restaurant['cuisine_type'],
                            'description': f"{restaurant['cuisine_type']} cuisine and specialties"
                        })
                    except:
                        category_id = 1  # Fallback
                    
                    # Insert menu items
                    for item in restaurant['menu_items']:
                        try:
                            item_id = str(uuid.uuid4())
                            db.execute(text("""
                                INSERT INTO restaurant_items (
                                    item_id, restaurant_id, category_id, item_name,
                                    description, price, currency_id, is_available, created_at
                                ) VALUES (
                                    :item_id, :restaurant_id, :category_id, :item_name,
                                    :description, :price, :currency_id, :is_available, NOW()
                                )
                            """), {
                                'item_id': item_id,
                                'restaurant_id': restaurant_id,
                                'category_id': category_id,
                                'item_name': item['name'],
                                'description': item.get('description', ''),
                                'price': item['price'],
                                'currency_id': currency_id,
                                'is_available': True
                            })
                        except Exception as e:
                            print(f"   ⚠️ Menu item save failed: {e}")
                    
                    db.commit()
                    successful_saves += 1
                    
                    if successful_saves % 25 == 0:
                        print(f"   ✅ Saved {successful_saves} restaurants...")
                    
                except Exception as e:
                    db.rollback()
                    print(f"❌ Failed to save {restaurant['name']}: {e}")
            
            print(f"✅ Successfully saved {successful_saves}/{len(restaurants)} restaurants")
    
    def generate_athens_restaurants(self, count: int = 500):
        """Main generation method"""
        print(f"🚀 Generating {count} Athens restaurants...")
        
        # Generate data
        restaurants = self.generate_restaurant_data(count)
        
        # Download sample photos
        self.download_sample_photos(restaurants)
        
        # Save to database
        self.save_to_database(restaurants)
        
        # Save to JSON for backup
        with open('athens_restaurants.json', 'w', encoding='utf-8') as f:
            # Convert time objects to strings for JSON serialization
            json_restaurants = []
            for r in restaurants:
                json_r = r.copy()
                if 'opening_time' in json_r and json_r['opening_time']:
                    json_r['opening_time'] = json_r['opening_time'].strftime('%H:%M:%S')
                if 'closing_time' in json_r and json_r['closing_time']:
                    json_r['closing_time'] = json_r['closing_time'].strftime('%H:%M:%S')
                json_restaurants.append(json_r)
            
            json.dump(json_restaurants, f, indent=2, ensure_ascii=False)
        
        print(f"🎉 Generated {len(restaurants)} Athens restaurants!")
        print(f"📁 Photos saved to: {self.photo_dir}")
        print(f"📄 Data backup: athens_restaurants.json")
        
        return restaurants

def main():
    """Main function"""
    generator = AthensRestaurantGenerator()
    
    try:
        restaurants = generator.generate_athens_restaurants(count=500)
        
        print(f"\n✅ GENERATION COMPLETE!")
        print(f"   🏪 Total restaurants: {len(restaurants)}")
        print(f"   📷 Sample photos downloaded")
        print(f"   💾 Data saved to database")
        print(f"   📄 Backup saved to JSON")
        
        # Show some statistics
        cuisines = {}
        total_items = 0
        for r in restaurants:
            cuisine = r['cuisine_type']
            cuisines[cuisine] = cuisines.get(cuisine, 0) + 1
            total_items += len(r['menu_items'])
        
        print(f"\n📊 STATISTICS:")
        print(f"   🍽️ Total menu items: {total_items}")
        print(f"   🏷️ Cuisine types: {len(cuisines)}")
        for cuisine, count in sorted(cuisines.items(), key=lambda x: x[1], reverse=True)[:5]:
            print(f"      {cuisine}: {count} restaurants")
        
    except Exception as e:
        print(f"❌ Error: {e}")
        import traceback
        traceback.print_exc()

if __name__ == "__main__":
    main()