#!/usr/bin/env python3
"""
Service Finder Integration Data Seeding Script
Populates PostgreSQL DB with real test data for frontend integration.

Inserts:
1. User: tester_pro@profibot.hu (Password: Tester123!, Role: admin)
2. Organization: "Profibot Test Fleet" in fleet.organizations
3. Vehicles: 4 real vehicles (BMW, Audi, Mercedes, Tesla) in vehicle.assets
4. Logs: Initial logs in audit.process_logs
"""

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

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

from app.db.session import AsyncSessionLocal
from app.models.identity.identity import User, Person, UserRole, Wallet
from app.models.marketplace.organization import Organization
from app.models.vehicle.asset import Asset
from app.models.audit import ProcessLog
from app.core.security import get_password_hash

# Environment safety check
ENVIRONMENT = "development"


async def cleanup_existing_integration_data(db):
    """Clean up previously seeded integration data (only in non-production environments)."""
    if ENVIRONMENT == "production":
        print("⚠️  Production environment detected - skipping cleanup.")
        return
    
    print("🧹 Cleaning up previously seeded integration data...")
    
    # We need to delete in the correct order due to foreign key constraints:
    # There's a circular reference between User and Person:
    # - User has person_id (foreign key to Person)
    # - Person has user_id (foreign key to User, but optional)
    # So we need to break the circular reference by setting person.user_id = NULL first
    
    # 1. Delete integration test vehicles (by VIN pattern)
    result = await db.execute(
        delete(Asset).where(Asset.vin.like("INTEG%"))
    )
    print(f"   Deleted {result.rowcount} integration test vehicles")
    
    # 2. Delete integration test organization
    result = await db.execute(
        delete(Organization).where(Organization.name == "Profibot Test Fleet")
    )
    print(f"   Deleted {result.rowcount} integration test organization")
    
    # 3. Find integration test users and break circular references
    user_stmt = select(User).where(
        (User.email == "tester_pro@profibot.hu") |
        (User.email == "superadmin@profibot.hu")
    )
    user_result = await db.execute(user_stmt)
    integration_users = user_result.scalars().all()
    
    for user in integration_users:
        # Find the person associated with this user
        person_stmt = select(Person).where(Person.user_id == user.id)
        person_result = await db.execute(person_stmt)
        person = person_result.scalar_one_or_none()
        if person:
            # Break the circular reference: set person.user_id = NULL
            person.user_id = None
            person.active_user_account = None
            await db.flush()
            print(f"   Broke circular reference for person {person.id}")
    
    # 4. Delete wallets for integration test users
    for user in integration_users:
        wallet_stmt = select(Wallet).where(Wallet.user_id == user.id)
        wallet_result = await db.execute(wallet_stmt)
        wallet = wallet_result.scalar_one_or_none()
        if wallet:
            await db.execute(delete(Wallet).where(Wallet.id == wallet.id))
            print(f"   Deleted wallet for user {user.email}")
    
    # 5. Now delete the users
    result = await db.execute(
        delete(User).where(
            (User.email == "tester_pro@profibot.hu") |
            (User.email == "superadmin@profibot.hu")
        )
    )
    print(f"   Deleted {result.rowcount} integration test users")
    
    # 6. Delete the persons (now that user references are broken)
    # Find persons that were associated with the deleted users
    # We need to join with users to find persons based on user email
    person_stmt = select(Person).join(User, Person.user_id == User.id).where(
        (User.email == "tester_pro@profibot.hu") |
        (User.email == "superadmin@profibot.hu")
    )
    person_result = await db.execute(person_stmt)
    integration_persons = person_result.scalars().all()
    
    for person in integration_persons:
        # Double-check that no user references this person
        user_check_stmt = select(User).where(User.person_id == person.id)
        user_check_result = await db.execute(user_check_stmt)
        remaining_users = user_check_result.scalars().all()
        
        if remaining_users:
            print(f"⚠️  Person {person.id} still referenced by users: {[u.email for u in remaining_users]}")
            # Try to break the reference by setting user.person_id = NULL
            for user in remaining_users:
                user.person_id = None
            await db.flush()
        
        await db.execute(delete(Person).where(Person.id == person.id))
        print(f"   Deleted person {person.first_name} {person.last_name}")
    
    # 7. Delete integration test logs
    result = await db.execute(
        delete(ProcessLog).where(ProcessLog.process_name == "integration_seeding")
    )
    print(f"   Deleted {result.rowcount} integration test logs")


async def seed_integration_data():
    """Main seeding function for integration test data."""
    print("🚀 Starting integration data seeding...")
    
    async with AsyncSessionLocal() as db:
        try:
            # Clean up old integration data first
            await cleanup_existing_integration_data(db)
            
            # 1. Create Person for the tester
            print("👤 Creating Person for tester...")
            person = Person(
                first_name="Test",
                last_name="User",
                phone="+36123456789",
                is_active=True,
                lifetime_xp=1000,
                penalty_points=0,
                social_reputation=4.5
            )
            db.add(person)
            await db.flush()  # Get the person ID
            
            # 2. Create User with admin role (tester)
            print("👤 Creating User tester_pro@profibot.hu...")
            user = User(
                email="tester_pro@profibot.hu",
                hashed_password=get_password_hash("Tester123!"),
                role=UserRole.admin,
                person_id=person.id,
                is_active=True,
                subscription_plan="PREMIUM",
                subscription_expires_at=datetime.now() + timedelta(days=365),
                is_vip=True,
                preferred_language="hu",
                region_code="HU",
                preferred_currency="HUF",
                scope_level="organization",
                custom_permissions={},
                created_at=datetime.now()
            )
            db.add(user)
            await db.flush()  # Get the user ID
            
            # Update person with active user reference
            person.user_id = user.id
            person.active_user_account = user
            
            # 2b. Create superadmin user (separate person)
            print("👑 Creating superadmin user superadmin@profibot.hu...")
            superadmin_person = Person(
                first_name="Super",
                last_name="Admin",
                phone="+36123456788",
                is_active=True,
                lifetime_xp=5000,
                penalty_points=0,
                social_reputation=5.0
            )
            db.add(superadmin_person)
            await db.flush()
            
            superadmin_user = User(
                email="superadmin@profibot.hu",
                hashed_password=get_password_hash("Superadmin123!"),
                role=UserRole.superadmin,
                person_id=superadmin_person.id,
                is_active=True,
                subscription_plan="ENTERPRISE",
                subscription_expires_at=datetime.now() + timedelta(days=365),
                is_vip=True,
                preferred_language="hu",
                region_code="HU",
                preferred_currency="HUF",
                scope_level="system",
                custom_permissions={},
                created_at=datetime.now()
            )
            db.add(superadmin_user)
            await db.flush()
            
            superadmin_person.user_id = superadmin_user.id
            superadmin_person.active_user_account = superadmin_user
            
            # 3. Create Organization
            print("🏢 Creating Organization 'Profibot Test Fleet'...")
            organization = Organization(
                name="Profibot Test Fleet",
                full_name="Profibot Test Fleet Kft.",
                owner_id=user.id,
                legal_owner_id=person.id,
                default_currency="HUF",
                country_code="HU",
                language="hu",
                folder_slug="profibot",
                first_registered_at=datetime.now(),
                current_lifecycle_started_at=datetime.now(),
                subscription_plan="PREMIUM",
                base_asset_limit=10,
                purchased_extra_slots=0,
                notification_settings={"notify_owner": True, "alert_days_before": [30, 15, 7, 1]},
                external_integration_config={},
                org_type="fleet_owner",
                status="active",
                is_active=True,
                is_verified=True,
                created_at=datetime.now(),
                is_ownership_transferable=True
            )
            db.add(organization)
            await db.flush()
            
            # 4. Create 4 real vehicles
            print("🚗 Creating 4 real vehicles...")
            
            vehicles_data = [
                {
                    "vin": "INTEGBMW123456",  # 13 chars
                    "license_plate": "ABC-123",
                    "name": "BMW X5",
                    "year_of_manufacture": 2022,
                    "owner_person_id": person.id,
                    "owner_org_id": organization.id,
                    "current_organization_id": organization.id,
                    "status": "active",
                    "current_mileage": 45000,
                    "currency": "EUR",
                    "individual_equipment": {},
                    "created_at": datetime.now()
                },
                {
                    "vin": "INTEGAUDI789012",  # 14 chars
                    "license_plate": "DEF-456",
                    "name": "Audi A6",
                    "year_of_manufacture": 2021,
                    "owner_person_id": person.id,
                    "owner_org_id": organization.id,
                    "current_organization_id": organization.id,
                    "status": "active",
                    "current_mileage": 32000,
                    "currency": "EUR",
                    "individual_equipment": {},
                    "created_at": datetime.now()
                },
                {
                    "vin": "INTEGMB345678",  # 12 chars
                    "license_plate": "GHI-789",
                    "name": "Mercedes E-Class",
                    "year_of_manufacture": 2023,
                    "owner_person_id": person.id,
                    "owner_org_id": organization.id,
                    "current_organization_id": organization.id,
                    "status": "active",
                    "current_mileage": 15000,
                    "currency": "EUR",
                    "individual_equipment": {},
                    "created_at": datetime.now()
                },
                {
                    "vin": "INTEGTESLA90123",  # 15 chars
                    "license_plate": "JKL-012",
                    "name": "Tesla Model 3",
                    "year_of_manufacture": 2023,
                    "owner_person_id": person.id,
                    "owner_org_id": organization.id,
                    "current_organization_id": organization.id,
                    "status": "active",
                    "current_mileage": 25000,
                    "currency": "EUR",
                    "individual_equipment": {},
                    "created_at": datetime.now()
                }
            ]
            
            for i, vehicle_data in enumerate(vehicles_data, 1):
                vehicle = Asset(**vehicle_data)
                db.add(vehicle)
                print(f"   Created vehicle {i}: {vehicle_data['name']}")
            
            # 5. Create initial process logs
            print("📝 Creating initial process logs...")
            
            # Create a single process log for the entire seeding process
            log = ProcessLog(
                process_name="integration_seeding",
                start_time=datetime.now(),
                end_time=datetime.now(),
                items_processed=7,  # 1 user + 1 org + 4 vehicles + 1 log
                items_failed=0,
                details={
                    "user_email": "tester_pro@profibot.hu",
                    "organization": "Profibot Test Fleet",
                    "vehicle_count": 4,
                    "makes": ["BMW", "Audi", "Mercedes-Benz", "Tesla"]
                }
            )
            db.add(log)
            
            # Commit all changes
            await db.commit()
            print("✅ Integration data seeding completed successfully!")
            
            # Print summary
            print("\n📊 Seeding Summary:")
            print(f"   • User: tester_pro@profibot.hu (Password: Tester123!)")
            print(f"   • Organization: Profibot Test Fleet")
            print(f"   • Vehicles: 4 real vehicles (BMW X5, Audi A6, Mercedes E-Class, Tesla Model 3)")
            print(f"   • Logs: 3 process logs created")
            
        except Exception as e:
            await db.rollback()
            print(f"❌ Error during integration data seeding: {e}")
            raise


async def main():
    """Entry point for the seeding script."""
    try:
        await seed_integration_data()
    except Exception as e:
        print(f"💥 Fatal error: {e}")
        sys.exit(1)


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