#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Demo Suppliers Seeding Script for Suppliers Service
Creates realistic Spanish suppliers for demo template tenants using pre-defined UUIDs

This script runs as a Kubernetes init job inside the suppliers-service container.
It populates the template tenants with a comprehensive catalog of suppliers.

Usage:
    python /app/scripts/demo/seed_demo_suppliers.py

Environment Variables Required:
    SUPPLIERS_DATABASE_URL - PostgreSQL connection string for suppliers database
    DEMO_MODE - Set to 'production' for production seeding
    LOG_LEVEL - Logging level (default: INFO)

Note: No database lookups needed - all IDs are pre-defined in the JSON file
"""

import asyncio
import uuid
import sys
import os
import json
from datetime import datetime, timezone, timedelta
from pathlib import Path
import random
from decimal import Decimal

# Add app to path
sys.path.insert(0, str(Path(__file__).parent.parent.parent))

from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy import select, text
import structlog

from app.models.suppliers import (
    Supplier, SupplierPriceList,
    SupplierType, SupplierStatus, PaymentTerms
)

# Configure logging
structlog.configure(
    processors=[
        structlog.stdlib.add_log_level,
        structlog.processors.TimeStamper(fmt="iso"),
        structlog.dev.ConsoleRenderer()
    ]
)

logger = structlog.get_logger()

# Fixed Demo Tenant IDs (must match tenant service)
DEMO_TENANT_SAN_PABLO = uuid.UUID("a1b2c3d4-e5f6-47a8-b9c0-d1e2f3a4b5c6")
DEMO_TENANT_LA_ESPIGA = uuid.UUID("b2c3d4e5-f6a7-48b9-c0d1-e2f3a4b5c6d7")

# Hardcoded SKU to Ingredient ID mapping (no database lookups needed!)
INGREDIENT_ID_MAP = {
    "HAR-T55-001": "10000000-0000-0000-0000-000000000001",
    "HAR-T65-002": "10000000-0000-0000-0000-000000000002",
    "HAR-FUE-003": "10000000-0000-0000-0000-000000000003",
    "HAR-INT-004": "10000000-0000-0000-0000-000000000004",
    "HAR-CEN-005": "10000000-0000-0000-0000-000000000005",
    "HAR-ESP-006": "10000000-0000-0000-0000-000000000006",
    "LAC-MAN-001": "10000000-0000-0000-0000-000000000011",
    "LAC-LEC-002": "10000000-0000-0000-0000-000000000012",
    "LAC-NAT-003": "10000000-0000-0000-0000-000000000013",
    "LAC-HUE-004": "10000000-0000-0000-0000-000000000014",
    "LEV-FRE-001": "10000000-0000-0000-0000-000000000021",
    "LEV-SEC-002": "10000000-0000-0000-0000-000000000022",
    "BAS-SAL-001": "10000000-0000-0000-0000-000000000031",
    "BAS-AZU-002": "10000000-0000-0000-0000-000000000032",
    "ESP-CHO-001": "10000000-0000-0000-0000-000000000041",
    "ESP-ALM-002": "10000000-0000-0000-0000-000000000042",
    "ESP-VAI-004": "10000000-0000-0000-0000-000000000044",
    "ESP-CRE-005": "10000000-0000-0000-0000-000000000045",
}

# Ingredient costs (for price list generation)
INGREDIENT_COSTS = {
    "HAR-T55-001": 0.85,
    "HAR-T65-002": 0.95,
    "HAR-FUE-003": 1.15,
    "HAR-INT-004": 1.20,
    "HAR-CEN-005": 1.30,
    "HAR-ESP-006": 2.45,
    "LAC-MAN-001": 6.50,
    "LAC-LEC-002": 0.95,
    "LAC-NAT-003": 3.20,
    "LAC-HUE-004": 0.25,
    "LEV-FRE-001": 4.80,
    "LEV-SEC-002": 12.50,
    "BAS-SAL-001": 0.60,
    "BAS-AZU-002": 0.90,
    "ESP-CHO-001": 15.50,
    "ESP-ALM-002": 8.90,
    "ESP-VAI-004": 3.50,
    "ESP-CRE-005": 7.20,
}


def load_suppliers_data():
    """Load suppliers data from JSON file"""
    # Look for data file in the same directory as this script
    data_file = Path(__file__).parent / "proveedores_es.json"

    if not data_file.exists():
        raise FileNotFoundError(
            f"Suppliers data file not found: {data_file}. "
            "Make sure proveedores_es.json is in the same directory as this script."
        )

    logger.info("Loading suppliers data", file=str(data_file))

    with open(data_file, 'r', encoding='utf-8') as f:
        data = json.load(f)

    suppliers = data.get("proveedores", [])
    logger.info(f"Loaded {len(suppliers)} suppliers from JSON")
    return suppliers


async def seed_suppliers_for_tenant(
    db: AsyncSession,
    tenant_id: uuid.UUID,
    tenant_name: str,
    suppliers_data: list
) -> dict:
    """
    Seed suppliers for a specific tenant using pre-defined UUIDs

    Args:
        db: Database session
        tenant_id: UUID of the tenant
        tenant_name: Name of the tenant (for logging)
        suppliers_data: List of supplier dictionaries with pre-defined IDs

    Returns:
        Dict with seeding statistics
    """
    logger.info("─" * 80)
    logger.info(f"Seeding suppliers for: {tenant_name}")
    logger.info(f"Tenant ID: {tenant_id}")
    logger.info("─" * 80)

    created_suppliers = 0
    skipped_suppliers = 0
    created_price_lists = 0

    for supplier_data in suppliers_data:
        supplier_name = supplier_data["name"]

        # Generate tenant-specific UUID by combining base UUID with tenant ID
        base_supplier_id = uuid.UUID(supplier_data["id"])
        tenant_int = int(tenant_id.hex, 16)
        supplier_id = uuid.UUID(int=tenant_int ^ int(base_supplier_id.hex, 16))

        # Check if supplier already exists (using tenant-specific ID)
        result = await db.execute(
            select(Supplier).where(
                Supplier.tenant_id == tenant_id,
                Supplier.id == supplier_id
            )
        )
        existing_supplier = result.scalars().first()

        if existing_supplier:
            logger.debug(f"   ⏭️  Supplier exists, ensuring price lists: {supplier_name}")
            skipped_suppliers += 1
            # Don't skip - continue to create/update price lists below
        else:
            # Parse enums
            try:
                supplier_type = SupplierType(supplier_data.get("supplier_type", "ingredients"))
            except ValueError:
                supplier_type = SupplierType.INGREDIENTS

            try:
                status = SupplierStatus(supplier_data.get("status", "active"))
            except ValueError:
                status = SupplierStatus.ACTIVE

            try:
                payment_terms = PaymentTerms(supplier_data.get("payment_terms", "net_30"))
            except ValueError:
                payment_terms = PaymentTerms.NET_30

            # Create supplier with pre-defined ID
            supplier = Supplier(
                id=supplier_id,
                tenant_id=tenant_id,
                name=supplier_name,
                supplier_code=f"SUP-{created_suppliers + 1:03d}",
                supplier_type=supplier_type,
                status=status,
                tax_id=supplier_data.get("tax_id"),
                contact_person=supplier_data.get("contact_person"),
                email=supplier_data.get("email"),
                phone=supplier_data.get("phone"),
                mobile=supplier_data.get("mobile"),
                website=supplier_data.get("website"),
                address_line1=supplier_data.get("address_line1"),
                address_line2=supplier_data.get("address_line2"),
                city=supplier_data.get("city"),
                state_province=supplier_data.get("state_province"),
                postal_code=supplier_data.get("postal_code"),
                country=supplier_data.get("country", "España"),
                payment_terms=payment_terms,
                credit_limit=Decimal(str(supplier_data.get("credit_limit", 0.0))),
                standard_lead_time=supplier_data.get("standard_lead_time", 3),
                quality_rating=supplier_data.get("quality_rating", 4.5),
                delivery_rating=supplier_data.get("delivery_rating", 4.5),
                notes=supplier_data.get("notes"),
                certifications=supplier_data.get("certifications", []),
                created_at=datetime.now(timezone.utc),
                updated_at=datetime.now(timezone.utc),
                created_by=uuid.UUID("00000000-0000-0000-0000-000000000000"),  # System user
                updated_by=uuid.UUID("00000000-0000-0000-0000-000000000000")   # System user
            )

            db.add(supplier)
            created_suppliers += 1
            logger.debug(f"   ✅ Created supplier: {supplier_name}")

        # Create price lists for products using pre-defined ingredient IDs
        products = supplier_data.get("products", [])
        for product_sku in products:
            # Get ingredient ID from hardcoded mapping (no DB lookup!)
            ingredient_id_str = INGREDIENT_ID_MAP.get(product_sku)
            if not ingredient_id_str:
                logger.warning(f"      ⚠️  Product SKU not in mapping: {product_sku}")
                continue

            # Generate tenant-specific ingredient ID (same as inventory seed)
            base_ingredient_id = uuid.UUID(ingredient_id_str)
            tenant_int = int(tenant_id.hex, 16)
            ingredient_id = uuid.UUID(int=tenant_int ^ int(base_ingredient_id.hex, 16))

            # Check if price list already exists
            existing_price_list_result = await db.execute(
                select(SupplierPriceList).where(
                    SupplierPriceList.tenant_id == tenant_id,
                    SupplierPriceList.supplier_id == supplier_id,
                    SupplierPriceList.inventory_product_id == ingredient_id
                )
            )
            existing_price_list = existing_price_list_result.scalars().first()

            if existing_price_list:
                # Price list already exists, skip
                continue

            # Get base cost from hardcoded costs
            base_cost = INGREDIENT_COSTS.get(product_sku, 1.0)

            # Calculate supplier price (slightly vary from base cost)
            price_variation = random.uniform(0.90, 1.10)
            unit_price = Decimal(str(base_cost * price_variation))

            # price_per_unit is same as unit_price for base quantity
            price_per_unit = unit_price

            price_list = SupplierPriceList(
                id=uuid.uuid4(),
                tenant_id=tenant_id,
                supplier_id=supplier_id,
                inventory_product_id=ingredient_id,
                product_code=product_sku,
                unit_price=unit_price,
                price_per_unit=price_per_unit,
                minimum_order_quantity=random.choice([1, 5, 10]),
                unit_of_measure="kg",
                effective_date=datetime.now(timezone.utc) - timedelta(days=90),
                is_active=True,
                created_at=datetime.now(timezone.utc),
                updated_at=datetime.now(timezone.utc),
                created_by=uuid.UUID("00000000-0000-0000-0000-000000000000"),  # System user
                updated_by=uuid.UUID("00000000-0000-0000-0000-000000000000")   # System user
            )

            db.add(price_list)
            created_price_lists += 1

    # Commit all changes for this tenant
    await db.commit()

    logger.info(f"   📊 Suppliers: {created_suppliers}, Price Lists: {created_price_lists}")
    logger.info("")

    return {
        "tenant_id": str(tenant_id),
        "tenant_name": tenant_name,
        "suppliers_created": created_suppliers,
        "suppliers_skipped": skipped_suppliers,
        "price_lists_created": created_price_lists,
        "total_suppliers": len(suppliers_data)
    }


async def seed_suppliers(db: AsyncSession):
    """
    Seed suppliers for all demo template tenants using pre-defined IDs

    Args:
        db: Database session

    Returns:
        Dict with overall seeding statistics
    """
    logger.info("=" * 80)
    logger.info("🚚 Starting Demo Suppliers Seeding")
    logger.info("=" * 80)

    # Load suppliers data once
    try:
        suppliers_data = load_suppliers_data()
    except FileNotFoundError as e:
        logger.error(str(e))
        raise

    results = []

    # Seed for San Pablo (Traditional Bakery)
    logger.info("")
    result_san_pablo = await seed_suppliers_for_tenant(
        db,
        DEMO_TENANT_SAN_PABLO,
        "Panadería San Pablo (Traditional)",
        suppliers_data
    )
    results.append(result_san_pablo)

    # Seed for La Espiga (Central Workshop)
    result_la_espiga = await seed_suppliers_for_tenant(
        db,
        DEMO_TENANT_LA_ESPIGA,
        "Panadería La Espiga (Central Workshop)",
        suppliers_data
    )
    results.append(result_la_espiga)

    # Calculate totals
    total_suppliers = sum(r["suppliers_created"] for r in results)
    total_price_lists = sum(r["price_lists_created"] for r in results)
    total_skipped = sum(r["suppliers_skipped"] for r in results)

    logger.info("=" * 80)
    logger.info("✅ Demo Suppliers Seeding Completed")
    logger.info("=" * 80)

    return {
        "service": "suppliers",
        "tenants_seeded": len(results),
        "total_suppliers_created": total_suppliers,
        "total_price_lists_created": total_price_lists,
        "total_skipped": total_skipped,
        "results": results
    }


async def main():
    """Main execution function"""

    logger.info("Demo Suppliers Seeding Script Starting")
    logger.info("Mode: %s", os.getenv("DEMO_MODE", "development"))
    logger.info("Log Level: %s", os.getenv("LOG_LEVEL", "INFO"))

    # Get database URL from environment
    database_url = os.getenv("SUPPLIERS_DATABASE_URL") or os.getenv("DATABASE_URL")
    if not database_url:
        logger.error("❌ SUPPLIERS_DATABASE_URL or DATABASE_URL environment variable must be set")
        return 1

    # Convert to async URL if needed
    if database_url.startswith("postgresql://"):
        database_url = database_url.replace("postgresql://", "postgresql+asyncpg://", 1)

    logger.info("Connecting to suppliers database")

    # Create engine and session
    engine = create_async_engine(
        database_url,
        echo=False,
        pool_pre_ping=True,
        pool_size=5,
        max_overflow=10
    )

    session_maker = sessionmaker(
        engine,
        class_=AsyncSession,
        expire_on_commit=False
    )

    try:
        async with session_maker() as session:
            result = await seed_suppliers(session)

            logger.info("")
            logger.info("📊 Seeding Summary:")
            logger.info(f"   ✅ Tenants seeded: {result['tenants_seeded']}")
            logger.info(f"   ✅ Suppliers created: {result['total_suppliers_created']}")
            logger.info(f"   ✅ Price lists created: {result['total_price_lists_created']}")
            logger.info(f"   ⏭️  Skipped: {result['total_skipped']}")
            logger.info("")

            # Print per-tenant details
            for tenant_result in result['results']:
                logger.info(
                    f"   {tenant_result['tenant_name']}: "
                    f"{tenant_result['suppliers_created']} suppliers, "
                    f"{tenant_result['price_lists_created']} price lists"
                )

            logger.info("")
            logger.info("🎉 Success! Supplier catalog is ready for cloning.")
            logger.info("")
            logger.info("Suppliers created:")
            logger.info("  • Molinos San José S.L. (harinas)")
            logger.info("  • Lácteos del Valle S.A. (lácteos)")
            logger.info("  • Lesaffre Ibérica (levaduras)")
            logger.info("  • And 9 more suppliers...")
            logger.info("")
            logger.info("Note: All IDs are pre-defined and hardcoded for cross-service consistency")
            logger.info("")

            return 0

    except Exception as e:
        logger.error("=" * 80)
        logger.error("❌ Demo Suppliers Seeding Failed")
        logger.error("=" * 80)
        logger.error("Error: %s", str(e))
        logger.error("", exc_info=True)
        return 1

    finally:
        await engine.dispose()


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