#!/usr/bin/env python3
"""
Service Finder v2.0 Seed Script (Gamification 2.0 + Mock Service Profiles)
Modern, asynchronous SQLAlchemy 2.0 seed script for development and testing.
Includes: Superadmin user, Gamification levels (-3 to +10), 15 mock service profiles.
"""

import asyncio
import sys
from datetime import datetime
from typing import List, Tuple

from sqlalchemy import select, delete, text
from sqlalchemy.dialects.postgresql import insert
from geoalchemy2 import WKTElement

from app.db.session import SessionLocal
from app.models.identity.identity import User
from app.models.gamification.gamification import LevelConfig
from app.models.marketplace.service import ServiceProfile, ServiceStatus
from app.core.security import get_password_hash

# Environment safety check
ENVIRONMENT = "development"  # Change to 'production' in production deployments


async def cleanup_existing_seeds(db):
    """Clean up previously seeded data (only in non-production environments)."""
    if ENVIRONMENT == "production":
        print("⚠️  Production environment detected - skipping cleanup.")
        return
    
    print("🧹 Cleaning up previously seeded data...")
    
    # Delete mock service profiles (fingerprint starts with 'MOCK-')
    result = await db.execute(
        delete(ServiceProfile).where(ServiceProfile.fingerprint.like("MOCK-%"))
    )
    print(f"   Deleted {result.rowcount} mock service profiles")
    
    # Delete gamification levels we're about to insert (levels -3 to +10)
    result = await db.execute(
        delete(LevelConfig).where(LevelConfig.level_number.between(-3, 10))
    )
    print(f"   Deleted {result.rowcount} gamification level configs")
    
    # Delete superadmin user if exists (by email)
    result = await db.execute(
        delete(User).where(User.email == "admin@servicefinder.hu")
    )
    print(f"   Deleted {result.rowcount} superadmin users")
    
    await db.commit()


async def create_superadmin(db):
    """Create superadmin user with admin@servicefinder.hu / admin123 credentials."""
    stmt = select(User).where(User.email == "admin@servicefinder.hu")
    existing = (await db.execute(stmt)).scalar_one_or_none()
    
    if existing:
        print("✅ Superadmin user already exists")
        return existing
    
    hashed_password = get_password_hash("admin123")
    admin = User(
        email="admin@servicefinder.hu",
        hashed_password=hashed_password,
        full_name="System Administrator",
        is_active=True,
        is_superuser=True,
        is_verified=True,
        email_verified_at=datetime.utcnow(),
    )
    db.add(admin)
    await db.commit()
    await db.refresh(admin)
    print("✅ Superadmin user created: admin@servicefinder.hu / admin123")
    return admin


async def seed_gamification_levels(db):
    """Create Gamification 2.0 levels from -3 (penalty) to +10 (prestige)."""
    levels = [
        # Penalty levels (is_penalty = True)
        (-3, 0, "Börtönviselt", True),
        (-2, 10, "Büntetőszint 2", True),
        (-1, 25, "Büntetőszint 1", True),
        
        # Regular levels (is_penalty = False)
        (0, 0, "Újonc", False),
        (1, 50, "Felfedező", False),
        (2, 150, "Gyakornok", False),
        (3, 300, "Szakképzett", False),
        (4, 500, "Szakértő", False),
        (5, 750, "Mester", False),
        (6, 1050, "Legenda", False),
        (7, 1400, "Hős", False),
        (8, 1800, "Elit", False),
        (9, 2250, "Zsoldos", False),
        (10, 2750, "Kalandor", False),
    ]
    
    inserted = 0
    for level_num, min_points, rank_name, is_penalty in levels:
        # Use PostgreSQL upsert to avoid duplicates
        insert_stmt = insert(LevelConfig).values(
            level_number=level_num,
            min_points=min_points,
            rank_name=rank_name,
            is_penalty=is_penalty
        )
        upsert_stmt = insert_stmt.on_conflict_do_update(
            index_elements=['level_number'],
            set_=dict(
                min_points=min_points,
                rank_name=rank_name,
                is_penalty=is_penalty
            )
        )
        await db.execute(upsert_stmt)
        inserted += 1
    
    await db.commit()
    print(f"✅ {inserted} gamification levels seeded (-3 to +10)")
    return inserted


def generate_hungarian_coordinates(index: int) -> Tuple[float, float]:
    """Generate realistic Hungarian coordinates for mock service profiles."""
    # Major Hungarian cities with their coordinates
    cities = [
        (47.4979, 19.0402),   # Budapest
        (46.2530, 20.1482),   # Szeged
        (47.5316, 21.6273),   # Debrecen
        (46.0759, 18.2280),   # Pécs
        (47.2300, 16.6216),   # Szombathely
        (47.9025, 20.3772),   # Eger
        (47.1890, 18.4103),   # Székesfehérvár
        (46.8412, 16.8416),   # Zalaegerszeg
        (48.1033, 20.7786),   # Miskolc
        (46.3833, 18.1333),   # Kaposvár
        (47.4980, 19.0399),   # Budapest (different district)
        (47.5300, 21.6200),   # Debrecen (slightly offset)
        (46.2600, 20.1500),   # Szeged (slightly offset)
        (47.1900, 18.4200),   # Székesfehérvár (slightly offset)
        (46.8400, 16.8500),   # Zalaegerszeg (slightly offset)
    ]
    
    # Add small random offset to make each location unique
    import random
    base_lat, base_lon = cities[index % len(cities)]
    offset_lat = random.uniform(-0.01, 0.01)
    offset_lon = random.uniform(-0.01, 0.01)
    
    return (base_lat + offset_lat, base_lon + offset_lon)


async def seed_service_profiles(db, admin_user):
    """Create 15 mock service profiles with different statuses and Hungarian coordinates."""
    statuses = [ServiceStatus.ghost, ServiceStatus.active, ServiceStatus.flagged]
    status_distribution = [5, 7, 3]  # 5 ghost, 7 active, 3 flagged
    
    service_names = [
        "AutoCenter Budapest",
        "Speedy Garage Szeged",
        "MesterMűhely Debrecen",
        "First Class Autószerviz Pécs",
        "Profik Szerviz Szombathely",
        "TopGear Eger",
        "Gold Service Székesfehérvár",
        "Zala Autó Zalaegerszeg",
        "Borsodi Műhely Miskolc",
        "Kaposvári Autó Centrum",
        "Budapest East Garage",
        "Debrecen North Workshop",
        "Szeged South Auto",
        "Fehérvári Speedy",
        "Zala Pro Motors"
    ]
    
    inserted = 0
    status_idx = 0
    
    for i in range(15):
        # Determine status based on distribution
        if i < status_distribution[0]:
            status = ServiceStatus.ghost
        elif i < status_distribution[0] + status_distribution[1]:
            status = ServiceStatus.active
        else:
            status = ServiceStatus.flagged
        
        # Generate coordinates
        lat, lon = generate_hungarian_coordinates(i)
        
        # Create WKT element for PostGIS
        location = WKTElement(f'POINT({lon} {lat})', srid=4326)
        
        # Create service profile
        service = ServiceProfile(
            fingerprint=f"MOCK-{i:03d}-{datetime.utcnow().timestamp():.0f}",
            location=location,
            status=status,
            trust_score=30 if status == ServiceStatus.ghost else 75,
            is_verified=(status == ServiceStatus.active),
            contact_phone=f"+36 30 {1000 + i} {2000 + i}",
            contact_email=f"info@{service_names[i].replace(' ', '').lower()}.hu",
            website=f"https://{service_names[i].replace(' ', '').lower()}.hu",
            bio=f"{service_names[i]} - Profi autószerviz Magyarországon.",
            rating=4.0 + (i % 5) * 0.2,
            user_ratings_total=10 + i * 5,
            last_audit_at=datetime.utcnow()
        )
        
        db.add(service)
        inserted += 1
        
        # Commit in batches
        if inserted % 5 == 0:
            await db.commit()
    
    await db.commit()
    print(f"✅ {inserted} mock service profiles created (ghost:5, active:7, flagged:3)")
    return inserted


async def main():
    """Main seed function."""
    print("🚀 Service Finder v2.0 Seed Script")
    print("=" * 50)
    
    async with SessionLocal() as db:
        try:
            # 1. Cleanup (only in non-production)
            await cleanup_existing_seeds(db)
            
            # 2. Create superadmin user
            admin = await create_superadmin(db)
            
            # 3. Seed gamification levels
            await seed_gamification_levels(db)
            
            # 4. Seed service profiles
            await seed_service_profiles(db, admin)
            
            print("=" * 50)
            print("🎉 Seed completed successfully!")
            print("   - Superadmin: admin@servicefinder.hu / admin123")
            print("   - Gamification: Levels -3 to +10 configured")
            print("   - Service Profiles: 15 mock profiles with Hungarian coordinates")
            print("   - Status distribution: 5 ghost, 7 active, 3 flagged")
            
        except Exception as e:
            await db.rollback()
            print(f"❌ Seed failed: {e}")
            import traceback
            traceback.print_exc()
            sys.exit(1)


if __name__ == "__main__":
    asyncio.run(main())