#!/usr/bin/env python3
"""
Populate Part Categories and Groups

This script populates the SQLite database with initial part categories
and groups following the RockAuto style organization.

The script is idempotent - it can be run multiple times safely.
"""

import sqlite3
import os
import re
from pathlib import Path


def create_slug(name: str) -> str:
    """
    Generate a URL-friendly slug from a name.

    Args:
        name: The name to convert to a slug

    Returns:
        Lowercase string with spaces replaced by hyphens
    """
    # Convert to lowercase
    slug = name.lower()
    # Remove special characters except spaces and hyphens
    slug = re.sub(r'[^a-z0-9\s-]', '', slug)
    # Replace spaces with hyphens
    slug = re.sub(r'\s+', '-', slug)
    # Remove multiple consecutive hyphens
    slug = re.sub(r'-+', '-', slug)
    # Strip leading/trailing hyphens
    slug = slug.strip('-')
    return slug


def get_database_path() -> str:
    """Get the path to the SQLite database."""
    return "/home/Autopartes/vehicle_database/vehicle_database.db"


def get_schema_path() -> str:
    """Get the path to the schema SQL file."""
    return "/home/Autopartes/vehicle_database/sql/schema.sql"


def create_tables_if_not_exist(conn: sqlite3.Connection) -> None:
    """
    Create the necessary tables if they don't exist.
    Reads and executes relevant CREATE TABLE statements from schema.sql.

    Args:
        conn: SQLite database connection
    """
    schema_path = get_schema_path()

    if not os.path.exists(schema_path):
        print(f"Warning: Schema file not found at {schema_path}")
        print("Creating tables with embedded schema...")

        # Fallback embedded schema for the parts catalog tables
        embedded_schema = """
        CREATE TABLE IF NOT EXISTS part_categories (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            name TEXT NOT NULL,
            name_es TEXT,
            parent_id INTEGER,
            slug TEXT UNIQUE,
            icon_name TEXT,
            display_order INTEGER DEFAULT 0,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            FOREIGN KEY (parent_id) REFERENCES part_categories(id)
        );

        CREATE TABLE IF NOT EXISTS part_groups (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            category_id INTEGER NOT NULL,
            name TEXT NOT NULL,
            name_es TEXT,
            slug TEXT,
            display_order INTEGER DEFAULT 0,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            FOREIGN KEY (category_id) REFERENCES part_categories(id)
        );

        CREATE TABLE IF NOT EXISTS parts (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            oem_part_number TEXT NOT NULL,
            name TEXT NOT NULL,
            name_es TEXT,
            group_id INTEGER,
            description TEXT,
            description_es TEXT,
            weight_kg REAL,
            material TEXT,
            is_discontinued BOOLEAN DEFAULT 0,
            superseded_by_id INTEGER,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            FOREIGN KEY (group_id) REFERENCES part_groups(id),
            FOREIGN KEY (superseded_by_id) REFERENCES parts(id)
        );

        CREATE TABLE IF NOT EXISTS vehicle_parts (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            model_year_engine_id INTEGER NOT NULL,
            part_id INTEGER NOT NULL,
            quantity_required INTEGER DEFAULT 1,
            position TEXT,
            fitment_notes TEXT,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            FOREIGN KEY (model_year_engine_id) REFERENCES model_year_engine(id),
            FOREIGN KEY (part_id) REFERENCES parts(id),
            UNIQUE(model_year_engine_id, part_id, position)
        );

        CREATE INDEX IF NOT EXISTS idx_part_categories_parent ON part_categories(parent_id);
        CREATE INDEX IF NOT EXISTS idx_part_categories_slug ON part_categories(slug);
        CREATE INDEX IF NOT EXISTS idx_part_groups_category ON part_groups(category_id);
        CREATE INDEX IF NOT EXISTS idx_parts_oem ON parts(oem_part_number);
        CREATE INDEX IF NOT EXISTS idx_parts_group ON parts(group_id);
        CREATE INDEX IF NOT EXISTS idx_vehicle_parts_mye ON vehicle_parts(model_year_engine_id);
        CREATE INDEX IF NOT EXISTS idx_vehicle_parts_part ON vehicle_parts(part_id);
        """
        conn.executescript(embedded_schema)
    else:
        # Read the schema file
        with open(schema_path, 'r') as f:
            schema_sql = f.read()

        # Execute the entire schema (CREATE TABLE IF NOT EXISTS is safe to re-run)
        conn.executescript(schema_sql)

    conn.commit()
    print("Tables created/verified successfully.")


def get_categories_data() -> list:
    """
    Return the list of categories to insert.

    Returns:
        List of tuples: (name, name_es, icon_name, display_order)
    """
    return [
        ("Body & Lamp Assembly", "Carroceria y Lamparas", "fa-car-side", 1),
        ("Brake & Wheel Hub", "Frenos y Mazas", "fa-compact-disc", 2),
        ("Cooling System", "Sistema de Enfriamiento", "fa-temperature-low", 3),
        ("Drivetrain", "Tren Motriz", "fa-cogs", 4),
        ("Electrical & Lighting", "Electrico e Iluminacion", "fa-bolt", 5),
        ("Engine", "Motor", "fa-cog", 6),
        ("Exhaust", "Escape", "fa-wind", 7),
        ("Fuel & Air", "Combustible y Aire", "fa-gas-pump", 8),
        ("Heat & Air Conditioning", "Calefaccion y AC", "fa-snowflake", 9),
        ("Steering", "Direccion", "fa-dharmachakra", 10),
        ("Suspension", "Suspension", "fa-truck-monster", 11),
        ("Transmission", "Transmision", "fa-gears", 12),
    ]


def get_groups_data() -> dict:
    """
    Return the groups for each category.

    Returns:
        Dictionary mapping category name to list of groups.
        Each group is a tuple: (name, name_es, display_order)
    """
    return {
        "Body & Lamp Assembly": [
            ("Body Panels", "Paneles de Carroceria", 1),
            ("Bumpers", "Defensas", 2),
            ("Doors", "Puertas", 3),
            ("Fenders", "Salpicaderas", 4),
            ("Hoods", "Cofres", 5),
            ("Trunk Lids", "Tapas de Cajuela", 6),
            ("Grilles", "Parrillas", 7),
            ("Mirrors", "Espejos", 8),
            ("Headlights", "Faros Delanteros", 9),
            ("Taillights", "Calaveras", 10),
            ("Fog Lights", "Faros de Niebla", 11),
            ("Turn Signal Lights", "Luces Direccionales", 12),
            ("Windshield", "Parabrisas", 13),
            ("Window Glass", "Cristales de Ventana", 14),
            ("Moldings & Trim", "Molduras y Acabados", 15),
        ],
        "Brake & Wheel Hub": [
            ("Brake Pads", "Balatas", 1),
            ("Brake Rotors", "Discos de Freno", 2),
            ("Brake Drums", "Tambores de Freno", 3),
            ("Brake Shoes", "Zapatas de Freno", 4),
            ("Brake Calipers", "Calibradores de Freno", 5),
            ("Brake Lines", "Lineas de Freno", 6),
            ("Brake Hoses", "Mangueras de Freno", 7),
            ("Master Cylinder", "Cilindro Maestro", 8),
            ("Wheel Cylinders", "Cilindros de Rueda", 9),
            ("Brake Boosters", "Boosters de Freno", 10),
            ("ABS Components", "Componentes ABS", 11),
            ("Wheel Bearings", "Baleros de Rueda", 12),
            ("Wheel Hubs", "Mazas de Rueda", 13),
            ("Wheel Studs", "Birlos", 14),
            ("Parking Brake", "Freno de Mano", 15),
        ],
        "Cooling System": [
            ("Radiators", "Radiadores", 1),
            ("Radiator Hoses", "Mangueras de Radiador", 2),
            ("Water Pumps", "Bombas de Agua", 3),
            ("Thermostats", "Termostatos", 4),
            ("Cooling Fans", "Ventiladores", 5),
            ("Fan Clutches", "Clutch de Ventilador", 6),
            ("Coolant Reservoirs", "Depositos de Anticongelante", 7),
            ("Radiator Caps", "Tapones de Radiador", 8),
            ("Heater Cores", "Nucleos de Calefaccion", 9),
            ("Heater Hoses", "Mangueras de Calefaccion", 10),
            ("Coolant Sensors", "Sensores de Temperatura", 11),
            ("Oil Coolers", "Enfriadores de Aceite", 12),
            ("Intercoolers", "Intercoolers", 13),
        ],
        "Drivetrain": [
            ("CV Axles", "Flechas CV", 1),
            ("CV Joints", "Juntas CV", 2),
            ("CV Boots", "Guardapolvos CV", 3),
            ("U-Joints", "Crucetas", 4),
            ("Drive Shafts", "Flechas Cardanes", 5),
            ("Differentials", "Diferenciales", 6),
            ("Axle Shafts", "Ejes", 7),
            ("Transfer Cases", "Cajas de Transferencia", 8),
            ("Wheel Bearings", "Baleros de Rueda", 9),
            ("Hub Assemblies", "Ensambles de Maza", 10),
        ],
        "Electrical & Lighting": [
            ("Batteries", "Baterias", 1),
            ("Alternators", "Alternadores", 2),
            ("Starters", "Marchas", 3),
            ("Ignition Coils", "Bobinas de Ignicion", 4),
            ("Spark Plug Wires", "Cables de Bujia", 5),
            ("Distributors", "Distribuidores", 6),
            ("Ignition Switches", "Switches de Encendido", 7),
            ("Relays", "Relevadores", 8),
            ("Fuses", "Fusibles", 9),
            ("Switches", "Interruptores", 10),
            ("Wiring Harnesses", "Arneses Electricos", 11),
            ("Sensors", "Sensores", 12),
            ("Headlight Bulbs", "Focos de Faros", 13),
            ("Taillight Bulbs", "Focos de Calaveras", 14),
            ("Interior Lights", "Luces Interiores", 15),
            ("Horn", "Claxon", 16),
        ],
        "Engine": [
            ("Oil Filters", "Filtros de Aceite", 1),
            ("Air Filters", "Filtros de Aire", 2),
            ("Spark Plugs", "Bujias", 3),
            ("Belts", "Bandas", 4),
            ("Timing Belts", "Bandas de Tiempo", 5),
            ("Timing Chains", "Cadenas de Tiempo", 6),
            ("Timing Components", "Componentes de Tiempo", 7),
            ("Gaskets", "Juntas", 8),
            ("Head Gaskets", "Juntas de Cabeza", 9),
            ("Valve Cover Gaskets", "Juntas de Tapa de Punterias", 10),
            ("Oil Pan Gaskets", "Juntas de Carter", 11),
            ("Pistons", "Pistones", 12),
            ("Piston Rings", "Anillos de Piston", 13),
            ("Connecting Rods", "Bielas", 14),
            ("Crankshafts", "Cigueñales", 15),
            ("Camshafts", "Arboles de Levas", 16),
            ("Valves", "Valvulas", 17),
            ("Valve Springs", "Resortes de Valvula", 18),
            ("Rocker Arms", "Balancines", 19),
            ("Lifters", "Buzos", 20),
            ("Oil Pumps", "Bombas de Aceite", 21),
            ("Engine Mounts", "Soportes de Motor", 22),
            ("Cylinder Heads", "Cabezas de Motor", 23),
            ("Engine Blocks", "Bloques de Motor", 24),
            ("Harmonic Balancers", "Dampers", 25),
            ("Pulleys", "Poleas", 26),
            ("Tensioners", "Tensores", 27),
            ("Idler Pulleys", "Poleas Locas", 28),
        ],
        "Exhaust": [
            ("Exhaust Manifolds", "Multiples de Escape", 1),
            ("Catalytic Converters", "Convertidores Cataliticos", 2),
            ("Mufflers", "Mofles", 3),
            ("Resonators", "Resonadores", 4),
            ("Exhaust Pipes", "Tubos de Escape", 5),
            ("Exhaust Tips", "Terminales de Escape", 6),
            ("Exhaust Gaskets", "Juntas de Escape", 7),
            ("Exhaust Hangers", "Soportes de Escape", 8),
            ("O2 Sensors", "Sensores de Oxigeno", 9),
            ("EGR Valves", "Valvulas EGR", 10),
            ("Headers", "Headers", 11),
            ("Flex Pipes", "Flexibles", 12),
        ],
        "Fuel & Air": [
            ("Fuel Pumps", "Bombas de Gasolina", 1),
            ("Fuel Filters", "Filtros de Gasolina", 2),
            ("Fuel Injectors", "Inyectores", 3),
            ("Fuel Lines", "Lineas de Combustible", 4),
            ("Fuel Tanks", "Tanques de Gasolina", 5),
            ("Fuel Caps", "Tapones de Gasolina", 6),
            ("Carburetors", "Carburadores", 7),
            ("Throttle Bodies", "Cuerpos de Aceleracion", 8),
            ("Intake Manifolds", "Multiples de Admision", 9),
            ("Air Intake Hoses", "Mangueras de Admision", 10),
            ("Mass Air Flow Sensors", "Sensores MAF", 11),
            ("Throttle Position Sensors", "Sensores TPS", 12),
            ("Fuel Pressure Regulators", "Reguladores de Presion", 13),
            ("PCV Valves", "Valvulas PCV", 14),
            ("Air Intake Systems", "Sistemas de Admision", 15),
            ("Turbochargers", "Turbocargadores", 16),
            ("Superchargers", "Supercargadores", 17),
        ],
        "Heat & Air Conditioning": [
            ("AC Compressors", "Compresores de AC", 1),
            ("AC Condensers", "Condensadores de AC", 2),
            ("AC Evaporators", "Evaporadores de AC", 3),
            ("AC Hoses", "Mangueras de AC", 4),
            ("AC Accumulators", "Acumuladores de AC", 5),
            ("AC Receiver Driers", "Filtros Deshidratadores", 6),
            ("AC Expansion Valves", "Valvulas de Expansion", 7),
            ("AC Clutches", "Clutch de AC", 8),
            ("Blower Motors", "Motores de Ventilador", 9),
            ("Blower Resistors", "Resistencias de Ventilador", 10),
            ("Heater Control Valves", "Valvulas de Calefaccion", 11),
            ("Cabin Air Filters", "Filtros de Cabina", 12),
            ("AC Pressure Switches", "Switches de Presion AC", 13),
            ("Climate Control Units", "Unidades de Control Climatico", 14),
        ],
        "Steering": [
            ("Power Steering Pumps", "Bombas de Direccion Hidraulica", 1),
            ("Power Steering Hoses", "Mangueras de Direccion", 2),
            ("Power Steering Fluid Reservoirs", "Depositos de Direccion", 3),
            ("Steering Racks", "Cremalleras de Direccion", 4),
            ("Steering Gearboxes", "Cajas de Direccion", 5),
            ("Tie Rods", "Terminales de Direccion", 6),
            ("Tie Rod Ends", "Rotulas de Direccion", 7),
            ("Inner Tie Rods", "Terminales Interiores", 8),
            ("Steering Columns", "Columnas de Direccion", 9),
            ("Steering Wheels", "Volantes", 10),
            ("Pitman Arms", "Brazos Pitman", 11),
            ("Idler Arms", "Brazos Locos", 12),
            ("Center Links", "Barras Centrales", 13),
            ("Drag Links", "Barras de Arrastre", 14),
            ("Steering Knuckles", "Muñones", 15),
        ],
        "Suspension": [
            ("Shocks", "Amortiguadores", 1),
            ("Struts", "Struts", 2),
            ("Strut Mounts", "Bases de Strut", 3),
            ("Coil Springs", "Resortes", 4),
            ("Leaf Springs", "Muelles", 5),
            ("Control Arms", "Brazos de Control", 6),
            ("Upper Control Arms", "Brazos Superiores", 7),
            ("Lower Control Arms", "Brazos Inferiores", 8),
            ("Ball Joints", "Rotulas", 9),
            ("Bushings", "Bujes", 10),
            ("Sway Bars", "Barras Estabilizadoras", 11),
            ("Sway Bar Links", "Links de Barra Estabilizadora", 12),
            ("Sway Bar Bushings", "Bujes de Barra Estabilizadora", 13),
            ("Torsion Bars", "Barras de Torsion", 14),
            ("Trailing Arms", "Brazos Traseros", 15),
            ("Track Bars", "Barras Track", 16),
            ("Radius Arms", "Brazos de Radio", 17),
            ("Air Suspension", "Suspension Neumatica", 18),
            ("Bump Stops", "Topes", 19),
        ],
        "Transmission": [
            ("Transmission Filters", "Filtros de Transmision", 1),
            ("Clutch Kits", "Kits de Clutch", 2),
            ("Clutch Discs", "Discos de Clutch", 3),
            ("Pressure Plates", "Platos de Presion", 4),
            ("Throw-out Bearings", "Collares de Clutch", 5),
            ("Clutch Masters", "Cilindros Maestros de Clutch", 6),
            ("Clutch Slaves", "Cilindros Esclavos de Clutch", 7),
            ("Flywheels", "Volantes de Motor", 8),
            ("Flexplates", "Flexplates", 9),
            ("Torque Converters", "Convertidores de Torque", 10),
            ("Transmission Mounts", "Soportes de Transmision", 11),
            ("Shift Cables", "Cables de Cambios", 12),
            ("Shift Linkages", "Varillajes de Cambios", 13),
            ("Speedometer Gears", "Engranes de Velocimetro", 14),
            ("Transmission Gaskets", "Juntas de Transmision", 15),
            ("Transmission Seals", "Sellos de Transmision", 16),
        ],
    }


def insert_categories(conn: sqlite3.Connection) -> dict:
    """
    Insert categories into the database.

    Args:
        conn: SQLite database connection

    Returns:
        Dictionary mapping category name to category id
    """
    cursor = conn.cursor()
    categories = get_categories_data()
    category_ids = {}

    for name, name_es, icon_name, display_order in categories:
        slug = create_slug(name)

        # Use INSERT OR IGNORE to make the script idempotent
        cursor.execute("""
            INSERT OR IGNORE INTO part_categories
            (name, name_es, slug, icon_name, display_order)
            VALUES (?, ?, ?, ?, ?)
        """, (name, name_es, slug, icon_name, display_order))

        # Get the id (whether it was just inserted or already existed)
        cursor.execute("SELECT id FROM part_categories WHERE slug = ?", (slug,))
        result = cursor.fetchone()
        if result:
            category_ids[name] = result[0]
            print(f"  Category: {name} (ID: {result[0]})")

    conn.commit()
    return category_ids


def insert_groups(conn: sqlite3.Connection, category_ids: dict) -> None:
    """
    Insert groups into the database.

    Args:
        conn: SQLite database connection
        category_ids: Dictionary mapping category name to category id
    """
    cursor = conn.cursor()
    groups_data = get_groups_data()

    for category_name, groups in groups_data.items():
        if category_name not in category_ids:
            print(f"  Warning: Category '{category_name}' not found, skipping groups")
            continue

        category_id = category_ids[category_name]

        for name, name_es, display_order in groups:
            slug = create_slug(name)

            # Check if group already exists for this category
            cursor.execute("""
                SELECT id FROM part_groups
                WHERE category_id = ? AND slug = ?
            """, (category_id, slug))

            if cursor.fetchone() is None:
                cursor.execute("""
                    INSERT INTO part_groups
                    (category_id, name, name_es, slug, display_order)
                    VALUES (?, ?, ?, ?, ?)
                """, (category_id, name, name_es, slug, display_order))
                print(f"    Group: {name}")

    conn.commit()


def print_summary(conn: sqlite3.Connection) -> None:
    """
    Print a summary of the data in the database.

    Args:
        conn: SQLite database connection
    """
    cursor = conn.cursor()

    # Count categories
    cursor.execute("SELECT COUNT(*) FROM part_categories")
    category_count = cursor.fetchone()[0]

    # Count groups
    cursor.execute("SELECT COUNT(*) FROM part_groups")
    group_count = cursor.fetchone()[0]

    print("\n" + "=" * 50)
    print("SUMMARY")
    print("=" * 50)
    print(f"Total Categories: {category_count}")
    print(f"Total Groups: {group_count}")
    print()

    # Show categories with group counts
    cursor.execute("""
        SELECT pc.name, pc.name_es, pc.icon_name, COUNT(pg.id) as group_count
        FROM part_categories pc
        LEFT JOIN part_groups pg ON pc.id = pg.category_id
        GROUP BY pc.id
        ORDER BY pc.display_order
    """)

    print("Categories and Group Counts:")
    print("-" * 50)
    for row in cursor.fetchall():
        name, name_es, icon, count = row
        print(f"  {icon:20} {name:30} ({count} groups)")


def main():
    """Main function to populate categories and groups."""
    db_path = get_database_path()

    print("=" * 50)
    print("POPULATE PART CATEGORIES AND GROUPS")
    print("=" * 50)
    print(f"Database: {db_path}")
    print()

    # Check if database exists
    if not os.path.exists(db_path):
        print(f"Warning: Database does not exist at {db_path}")
        print("Creating new database...")

    # Connect to database
    conn = sqlite3.connect(db_path)

    try:
        # Create tables if they don't exist
        print("Creating/verifying tables...")
        create_tables_if_not_exist(conn)
        print()

        # Insert categories
        print("Inserting categories...")
        category_ids = insert_categories(conn)
        print()

        # Insert groups
        print("Inserting groups...")
        insert_groups(conn, category_ids)

        # Print summary
        print_summary(conn)

        print("\nDone! Categories and groups populated successfully.")

    except sqlite3.Error as e:
        print(f"Database error: {e}")
        raise
    finally:
        conn.close()


if __name__ == "__main__":
    main()
