#!/usr/bin/env python3
"""
Demo Database Seeder for Wizamart Platform

Creates DEMO/TEST data for development and testing:
- Demo vendors with realistic data
- Test customers and addresses
- Sample products
- Demo orders
- Vendor themes and custom domains
- Test import jobs

⚠️  WARNING: This script creates FAKE DATA for development only!
⚠️  NEVER run this in production!

Prerequisites:
    - Database migrations must be applied (make migrate-up)
    - Production initialization must be run (make init-prod)

Usage:
    make seed-demo          # Normal demo seeding
    make seed-demo-minimal  # Minimal seeding (1 vendor only)
    make seed-demo-reset    # Delete all data and reseed (DANGEROUS!)

This script is idempotent when run normally.
"""

import sys
from datetime import UTC, datetime
from decimal import Decimal
from pathlib import Path

# Add project root to path
project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))

# =============================================================================
# MODE DETECTION (from environment variable set by Makefile)
# =============================================================================
import os

from sqlalchemy import delete, select
from sqlalchemy.orm import Session

from app.core.config import settings
from app.core.database import SessionLocal
from app.core.environment import get_environment, is_production
from middleware.auth import AuthManager
from models.database.admin import PlatformAlert
from models.database.company import Company
from models.database.customer import Customer, CustomerAddress
from models.database.marketplace_import_job import MarketplaceImportJob
from models.database.marketplace_product import MarketplaceProduct
from models.database.order import Order, OrderItem
from models.database.product import Product
from models.database.user import User
from models.database.vendor import Role, Vendor, VendorUser
from models.database.vendor_domain import VendorDomain
from models.database.vendor_theme import VendorTheme

SEED_MODE = os.getenv("SEED_MODE", "normal")  # normal, minimal, reset

# =============================================================================
# DEMO DATA CONFIGURATION
# =============================================================================

# Demo company configurations (NEW: Company-based architecture)
DEMO_COMPANIES = [
    {
        "name": "WizaCorp Ltd.",
        "description": "Leading technology and electronics distributor",
        "owner_email": "john.owner@wizacorp.com",
        "owner_password": "password123",
        "owner_first_name": "John",
        "owner_last_name": "Smith",
        "contact_email": "info@wizacorp.com",
        "contact_phone": "+352 123 456 789",
        "website": "https://www.wizacorp.com",
        "business_address": "123 Tech Street, Luxembourg City, L-1234, Luxembourg",
        "tax_number": "LU12345678",
    },
    {
        "name": "Fashion Group S.A.",
        "description": "International fashion and lifestyle retailer",
        "owner_email": "jane.owner@fashiongroup.com",
        "owner_password": "password123",
        "owner_first_name": "Jane",
        "owner_last_name": "Merchant",
        "contact_email": "contact@fashiongroup.com",
        "contact_phone": "+352 234 567 890",
        "website": "https://www.fashiongroup.com",
        "business_address": "456 Fashion Avenue, Luxembourg, L-5678, Luxembourg",
        "tax_number": "LU23456789",
    },
    {
        "name": "BookWorld Publishing",
        "description": "Books, education, and media content provider",
        "owner_email": "bob.owner@bookworld.com",
        "owner_password": "password123",
        "owner_first_name": "Bob",
        "owner_last_name": "Seller",
        "contact_email": "support@bookworld.com",
        "contact_phone": "+352 345 678 901",
        "website": "https://www.bookworld.com",
        "business_address": "789 Library Lane, Esch-sur-Alzette, L-9012, Luxembourg",
        "tax_number": "LU34567890",
    },
]

# Demo vendor configurations (linked to companies by index)
DEMO_VENDORS = [
    {
        "company_index": 0,  # WizaCorp
        "vendor_code": "WIZAMART",
        "name": "WizaMart",
        "subdomain": "wizamart",
        "description": "Premium electronics and gadgets marketplace",
        "theme_preset": "modern",
        "custom_domain": "wizamart.shop",
    },
    {
        "company_index": 1,  # Fashion Group
        "vendor_code": "FASHIONHUB",
        "name": "Fashion Hub",
        "subdomain": "fashionhub",
        "description": "Trendy clothing and accessories",
        "theme_preset": "vibrant",
        "custom_domain": "fashionhub.store",
    },
    {
        "company_index": 2,  # BookWorld
        "vendor_code": "BOOKSTORE",
        "name": "The Book Store",
        "subdomain": "bookstore",
        "description": "Books, magazines, and educational materials",
        "theme_preset": "classic",
        "custom_domain": None,
    },
]

# Theme presets
THEME_PRESETS = {
    "modern": {
        "primary": "#3b82f6",
        "secondary": "#06b6d4",
        "accent": "#f59e0b",
        "background": "#f9fafb",
        "text": "#111827",
    },
    "classic": {
        "primary": "#1e40af",
        "secondary": "#7c3aed",
        "accent": "#dc2626",
        "background": "#ffffff",
        "text": "#374151",
    },
    "vibrant": {
        "primary": "#ec4899",
        "secondary": "#f59e0b",
        "accent": "#8b5cf6",
        "background": "#fef3c7",
        "text": "#78350f",
    },
}


# =============================================================================
# HELPER FUNCTIONS
# =============================================================================


def print_header(text: str):
    """Print formatted header."""
    print("\n" + "=" * 70)
    print(f"  {text}")
    print("=" * 70)


def print_step(step: int, text: str):
    """Print step indicator."""
    print(f"\n[{step}] {text}")


def print_success(text: str):
    """Print success message."""
    print(f"  ✓ {text}")


def print_warning(text: str):
    """Print warning message."""
    print(f"  ⚠ {text}")


def print_error(text: str):
    """Print error message."""
    print(f"  ✗ {text}")


# =============================================================================
# SAFETY CHECKS
# =============================================================================


def check_environment():
    """Prevent running demo seed in production."""

    if is_production():
        print_error("Cannot run demo seeding in production!")
        print("  This script creates FAKE DATA for development only.")
        print(f"  Current environment: {get_environment()}")
        print("\n  To seed in production:")
        print("  1. Set ENVIRONMENT=development in .env (or ENV=development)")
        print("  2. Run: make seed-demo")
        sys.exit(1)

    print_success(f"Environment check passed: {get_environment()}")


def check_admin_exists(db: Session) -> bool:
    """Check if admin user exists."""

    admin = db.execute(select(User).where(User.role == "admin")).scalar_one_or_none()

    if not admin:
        print_error("No admin user found!")
        print("  Run production initialization first:")
        print("  make init-prod")
        return False

    print_success(f"Admin user exists: {admin.email}")
    return True


# =============================================================================
# DATA DELETION (for reset mode)
# =============================================================================


def reset_all_data(db: Session):
    """Delete ALL data from database (except admin user)."""

    print_warning("RESETTING ALL DATA...")
    print("  This will delete all vendors, customers, orders, etc.")
    print("  Admin user will be preserved.")

    # Get confirmation
    response = input("\n  Type 'DELETE ALL DATA' to confirm: ")
    if response != "DELETE ALL DATA":
        print("  Reset cancelled.")
        sys.exit(0)

    # Delete in correct order (respecting foreign keys)
    tables_to_clear = [
        OrderItem,
        Order,
        CustomerAddress,
        Customer,
        MarketplaceImportJob,
        MarketplaceProduct,
        Product,
        VendorDomain,
        VendorTheme,
        Role,
        VendorUser,
        Vendor,
        Company,  # Delete companies (cascades to vendors)
        PlatformAlert,
    ]

    for table in tables_to_clear:
        db.execute(delete(table))

    # Delete non-admin users
    db.execute(delete(User).where(User.role != "admin"))

    db.commit()
    print_success("All data deleted (admin preserved)")


# =============================================================================
# SEEDING FUNCTIONS
# =============================================================================


def create_demo_companies(db: Session, auth_manager: AuthManager) -> list[Company]:
    """Create demo companies with owner accounts."""

    companies = []

    # Determine how many companies to create based on mode
    company_count = 1 if SEED_MODE == "minimal" else len(DEMO_COMPANIES)
    companies_to_create = DEMO_COMPANIES[:company_count]

    for company_data in companies_to_create:
        # Check if company already exists
        existing = db.execute(
            select(Company).where(Company.name == company_data["name"])
        ).scalar_one_or_none()

        if existing:
            print_warning(f"Company already exists: {company_data['name']}")
            companies.append(existing)
            continue

        # Check if owner user already exists
        owner_user = db.execute(
            select(User).where(User.email == company_data["owner_email"])
        ).scalar_one_or_none()

        if not owner_user:
            # Create owner user
            owner_user = User(
                username=company_data["owner_email"].split("@")[0],
                email=company_data["owner_email"],
                hashed_password=auth_manager.hash_password(
                    company_data["owner_password"]
                ),
                role="vendor",
                first_name=company_data["owner_first_name"],
                last_name=company_data["owner_last_name"],
                is_active=True,
                is_email_verified=True,
                created_at=datetime.now(UTC),
                updated_at=datetime.now(UTC),
            )
            db.add(owner_user)
            db.flush()
            print_success(
                f"Created owner user: {owner_user.email} (password: {company_data['owner_password']})"
            )
        else:
            print_warning(f"Using existing user as owner: {owner_user.email}")

        # Create company
        company = Company(
            name=company_data["name"],
            description=company_data["description"],
            owner_user_id=owner_user.id,
            contact_email=company_data["contact_email"],
            contact_phone=company_data.get("contact_phone"),
            website=company_data.get("website"),
            business_address=company_data.get("business_address"),
            tax_number=company_data.get("tax_number"),
            is_active=True,
            is_verified=True,  # Auto-verified for demo
            created_at=datetime.now(UTC),
            updated_at=datetime.now(UTC),
        )
        db.add(company)
        db.flush()

        companies.append(company)
        print_success(
            f"Created company: {company.name} (Owner: {owner_user.email})"
        )

    db.flush()
    return companies


def create_demo_vendors(
    db: Session, companies: list[Company], auth_manager: AuthManager
) -> list[Vendor]:
    """Create demo vendors linked to companies."""

    vendors = []

    # Determine how many vendors to create based on mode
    vendor_count = 1 if SEED_MODE == "minimal" else len(DEMO_VENDORS)
    vendors_to_create = DEMO_VENDORS[:vendor_count]

    for vendor_data in vendors_to_create:
        # Check if vendor already exists
        existing = db.execute(
            select(Vendor).where(Vendor.vendor_code == vendor_data["vendor_code"])
        ).scalar_one_or_none()

        if existing:
            print_warning(f"Vendor already exists: {vendor_data['name']}")
            vendors.append(existing)
            continue

        # Get company by index
        company_index = vendor_data["company_index"]
        if company_index >= len(companies):
            print_error(
                f"Invalid company_index {company_index} for vendor {vendor_data['name']}"
            )
            continue

        company = companies[company_index]

        # Create vendor linked to company (owner is inherited from company)
        vendor = Vendor(
            company_id=company.id,  # Link to company
            vendor_code=vendor_data["vendor_code"],
            name=vendor_data["name"],
            subdomain=vendor_data["subdomain"],
            description=vendor_data["description"],
            is_active=True,
            is_verified=True,
            created_at=datetime.now(UTC),
            updated_at=datetime.now(UTC),
        )
        db.add(vendor)
        db.flush()

        # Link company owner to vendor as owner
        vendor_user_link = VendorUser(
            vendor_id=vendor.id,
            user_id=company.owner_user_id,
            user_type="owner",
            is_active=True,
            created_at=datetime.now(UTC),
        )
        db.add(vendor_user_link)

        # Create vendor theme
        theme_colors = THEME_PRESETS.get(
            vendor_data["theme_preset"], THEME_PRESETS["modern"]
        )
        theme = VendorTheme(
            vendor_id=vendor.id,
            theme_name=vendor_data["theme_preset"],
            colors={  # ✅ Use JSON format
                "primary": theme_colors["primary"],
                "secondary": theme_colors["secondary"],
                "accent": theme_colors["accent"],
                "background": theme_colors["background"],
                "text": theme_colors["text"],
            },
            is_active=True,
            created_at=datetime.now(UTC),
            updated_at=datetime.now(UTC),
        )
        db.add(theme)

        # Create custom domain if specified
        if vendor_data.get("custom_domain"):
            domain = VendorDomain(
                vendor_id=vendor.id,
                domain=vendor_data["custom_domain"],  # ✅ Field is 'domain', not 'domain_name'
                is_verified=True,  # Auto-verified for demo
                is_primary=True,
                verification_token=None,
                created_at=datetime.now(UTC),
                updated_at=datetime.now(UTC),
            )
            db.add(domain)

        vendors.append(vendor)
        print_success(f"Created vendor: {vendor.name} ({vendor.vendor_code})")

    db.flush()
    return vendors


def create_demo_customers(
    db: Session, vendor: Vendor, auth_manager: AuthManager, count: int
) -> list[Customer]:
    """Create demo customers for a vendor."""

    customers = []
    # Use a simple demo password for all customers
    demo_password = "customer123"

    for i in range(1, count + 1):
        email = f"customer{i}@{vendor.subdomain}.example.com"
        customer_number = f"CUST-{vendor.vendor_code}-{i:04d}"

        # Check if customer already exists
        existing_customer = (
            db.query(Customer)
            .filter(Customer.vendor_id == vendor.id, Customer.email == email)
            .first()
        )

        if existing_customer:
            customers.append(existing_customer)
            continue  # Skip creation, customer already exists

        customer = Customer(
            vendor_id=vendor.id,
            email=email,
            hashed_password=auth_manager.hash_password(demo_password),
            first_name=f"Customer{i}",
            last_name="Test",
            phone=f"+352123456{i:03d}",
            customer_number=customer_number,
            is_active=True,
            created_at=datetime.now(UTC),
            updated_at=datetime.now(UTC),
        )
        db.add(customer)
        customers.append(customer)

    db.flush()

    new_count = len([c for c in customers if c.id is None or db.is_modified(c)])
    if new_count > 0:
        print_success(f"Created {new_count} customers for {vendor.name}")
    else:
        print_warning(f"Customers already exist for {vendor.name}")

    return customers


def create_demo_products(db: Session, vendor: Vendor, count: int) -> list[Product]:
    """Create demo products for a vendor."""

    products = []

    for i in range(1, count + 1):
        marketplace_product_id = f"{vendor.vendor_code}-MP-{i:04d}"
        product_id = f"{vendor.vendor_code}-PROD-{i:03d}"

        # Check if this product already exists
        existing_product = (
            db.query(Product)
            .filter(Product.vendor_id == vendor.id, Product.product_id == product_id)
            .first()
        )

        if existing_product:
            products.append(existing_product)
            continue  # Skip creation, product already exists

        # Check if marketplace product already exists
        existing_mp = (
            db.query(MarketplaceProduct)
            .filter(MarketplaceProduct.marketplace_product_id == marketplace_product_id)
            .first()
        )

        if existing_mp:
            marketplace_product = existing_mp
        else:
            # Create the MarketplaceProduct (base product data)
            marketplace_product = MarketplaceProduct(
                marketplace_product_id=marketplace_product_id,
                title=f"Sample Product {i} - {vendor.name}",
                description=f"This is a demo product for testing purposes in {vendor.name}. High quality and affordable.",
                link=f"https://{vendor.subdomain}.example.com/products/sample-{i}",
                image_link=f"https://{vendor.subdomain}.example.com/images/product-{i}.jpg",
                price=str(Decimal(f"{(i * 10) % 500 + 9.99}")),  # Store as string
                brand=vendor.name,
                gtin=f"TEST{vendor.id:02d}{i:010d}",
                availability="in stock",
                condition="new",
                google_product_category="Electronics > Computers > Laptops",
                marketplace="Wizamart",
                vendor_name=vendor.name,
                currency="EUR",
                created_at=datetime.now(UTC),
                updated_at=datetime.now(UTC),
            )
            db.add(marketplace_product)
            db.flush()  # Flush to get the marketplace_product.id

        # Create the Product (vendor-specific entry)
        product = Product(
            vendor_id=vendor.id,
            marketplace_product_id=marketplace_product.id,
            product_id=product_id,
            price=float(Decimal(f"{(i * 10) % 500 + 9.99}")),  # Store as float
            availability="in stock",
            condition="new",
            currency="EUR",
            is_active=True,
            is_featured=(i % 5 == 0),  # Every 5th product is featured
            display_order=i,
            min_quantity=1,
            created_at=datetime.now(UTC),
            updated_at=datetime.now(UTC),
        )
        db.add(product)
        products.append(product)

    db.flush()

    new_count = len([p for p in products if p.id is None or db.is_modified(p)])
    if new_count > 0:
        print_success(f"Created {new_count} products for {vendor.name}")
    else:
        print_warning(f"Products already exist for {vendor.name}")

    return products


# =============================================================================
# MAIN SEEDING
# =============================================================================


def seed_demo_data(db: Session, auth_manager: AuthManager):
    """Seed demo data for development."""

    print_header("DEMO DATA SEEDING")
    print(f"  Mode: {SEED_MODE.upper()}")

    # Step 1: Check environment
    print_step(1, "Checking environment...")
    check_environment()

    # Step 2: Check admin exists
    print_step(2, "Verifying admin user...")
    if not check_admin_exists(db):
        sys.exit(1)

    # Step 3: Reset data if in reset mode
    if SEED_MODE == "reset":
        print_step(3, "Resetting data...")
        reset_all_data(db)

    # Step 4: Create companies
    print_step(4, "Creating demo companies...")
    companies = create_demo_companies(db, auth_manager)

    # Step 5: Create vendors
    print_step(5, "Creating demo vendors...")
    vendors = create_demo_vendors(db, companies, auth_manager)

    # Step 6: Create customers
    print_step(6, "Creating demo customers...")
    for vendor in vendors:
        create_demo_customers(
            db, vendor, auth_manager, count=settings.seed_customers_per_vendor
        )

    # Step 7: Create products
    print_step(7, "Creating demo products...")
    for vendor in vendors:
        create_demo_products(db, vendor, count=settings.seed_products_per_vendor)

    # Commit all changes
    db.commit()
    print_success("All demo data committed")


def print_summary(db: Session):
    """Print seeding summary."""

    print_header("SEEDING SUMMARY")

    # Count records
    company_count = db.query(Company).count()
    vendor_count = db.query(Vendor).count()
    user_count = db.query(User).count()
    customer_count = db.query(Customer).count()
    product_count = db.query(Product).count()

    print("\n📊 Database Status:")
    print(f"  Companies:   {company_count}")
    print(f"  Vendors:     {vendor_count}")
    print(f"  Users:       {user_count}")
    print(f"  Customers:   {customer_count}")
    print(f"  Products:    {product_count}")

    # Show company details
    companies = db.query(Company).all()
    print("\n🏢 Demo Companies:")
    for company in companies:
        print(f"\n  {company.name}")
        print(f"    Owner:     {company.owner.email if company.owner else 'N/A'}")
        print(f"    Vendors:   {len(company.vendors) if company.vendors else 0}")
        print(f"    Status:    {'✓ Active' if company.is_active else '✗ Inactive'}")
        if company.is_verified:
            print(f"    Verified:  ✓")

    # Show vendor details
    vendors = db.query(Vendor).all()
    print("\n🏪 Demo Vendors:")
    for vendor in vendors:
        print(f"\n  {vendor.name} ({vendor.vendor_code})")
        print(f"    Subdomain: {vendor.subdomain}.{settings.platform_domain}")

        # Query custom domains separately
        custom_domain = (
            db.query(VendorDomain)
            .filter(VendorDomain.vendor_id == vendor.id, VendorDomain.is_active == True)
            .first()
        )

        if custom_domain:
            # Try different possible field names (model field might vary)
            domain_value = (
                getattr(custom_domain, "domain", None)
                or getattr(custom_domain, "domain_name", None)
                or getattr(custom_domain, "name", None)
            )
            if domain_value:
                print(f"    Custom:    {domain_value}")

        print(f"    Status:    {'✓ Active' if vendor.is_active else '✗ Inactive'}")

    print("\n🔐 Demo Company Owner Credentials:")
    print("─" * 70)
    for i, company_data in enumerate(DEMO_COMPANIES[:company_count], 1):
        company = companies[i - 1] if i <= len(companies) else None
        print(f"  Company {i}: {company_data['name']}")
        print(f"    Email:    {company_data['owner_email']}")
        print(f"    Password: {company_data['owner_password']}")
        if company and company.vendors:
            for vendor in company.vendors:
                print(
                    f"    Vendor:   http://localhost:8000/vendor/{vendor.vendor_code}/login"
                )
                print(
                    f"           or http://{vendor.subdomain}.localhost:8000/vendor/login"
                )
        print()

    print("\n🛒 Demo Customer Credentials:")
    print("─" * 70)
    print("  All customers:")
    print("    Email:    customer1@{subdomain}.example.com")
    print("    Password: customer123")
    print("  (Replace {subdomain} with vendor subdomain, e.g., wizamart)")
    print()

    print("\n🏪 Shop Access (Development):")
    print("─" * 70)
    for vendor in vendors:
        print(f"  {vendor.name}:")
        print(
            f"    Path-based:   http://localhost:8000/vendors/{vendor.vendor_code}/shop/"
        )
        print(f"    Subdomain:    http://{vendor.subdomain}.localhost:8000/")
    print()

    print("⚠️  ALL DEMO CREDENTIALS ARE INSECURE - For development only!")

    print("\n🚀 NEXT STEPS:")
    print("  1. Start development: make dev")
    print("  2. Login as vendor:")
    print("     • Path-based:  http://localhost:8000/vendor/WIZAMART/login")
    print("     • Subdomain:   http://wizamart.localhost:8000/vendor/login")
    print("  3. Visit vendor shop: http://localhost:8000/vendors/WIZAMART/shop/")
    print("  4. Admin panel: http://localhost:8000/admin/login")
    print(f"     Username: {settings.admin_username}")
    print(f"     Password: {settings.admin_password}")


# =============================================================================
# MAIN ENTRY POINT
# =============================================================================


def main():
    """Main entry point."""

    print("\n" + "╔" + "═" * 68 + "╗")
    print("║" + " " * 20 + "DEMO DATA SEEDING" + " " * 31 + "║")
    print("╚" + "═" * 68 + "╝")

    db = SessionLocal()
    auth_manager = AuthManager()

    try:
        seed_demo_data(db, auth_manager)
        print_summary(db)

        print_header("✅ DEMO SEEDING COMPLETED")

    except KeyboardInterrupt:
        db.rollback()
        print("\n\n⚠️  Seeding interrupted")
        sys.exit(1)

    except Exception as e:
        db.rollback()
        print_header("❌ SEEDING FAILED")
        print(f"\nError: {e}\n")
        import traceback

        traceback.print_exc()
        sys.exit(1)

    finally:
        db.close()


if __name__ == "__main__":
    main()
