#!/usr/bin/env python3
"""
IMPORTADOR DEL CATÁLOGO CARTEK - FILTROS DE ACEITE
Formato: Brand → Model | YearFrom | YearTo | CTK#### | Observations
Solo aceite. PDF: /tmp/catalogs/cartek_aceite.pdf
"""

import sqlite3
import re
import pypdf
from pathlib import Path

DB_PATH = Path(__file__).parent.parent / 'vehicle_database.db'
PDF_PATH = '/tmp/catalogs/cartek_aceite.pdf'

# Known brand headers in the Cartek catalog
BRAND_HEADERS = {
    'ACURA', 'ALFA ROMEO', 'AM GENERAL', 'AMERICAN MOTORS', 'ASTON MARTIN',
    'ASUNA', 'AUDI', 'AUSTIN', 'AUSTIN HEALEY', 'AVANTI', 'BAIC', 'BENTLEY',
    'BERTONE', 'BMW', 'BRICKLIN', 'BUICK', 'CADILLAC', 'CHECKER', 'CHEVROLET',
    'CHRYSLER', 'DAEWOO', 'DAIHATSU', 'DATSUN', 'DELOREAN', 'DESOTO',
    'DETOMASO', 'DODGE', 'EAGLE', 'EDSEL', 'EXCALIBUR', 'FAW', 'FIAT', 'FORD',
    'FREIGHTLINER', 'GEO', 'GMC', 'HILLMAN', 'HONDA', 'HUMMER', 'HYUNDAI',
    'IC CORPORATION', 'INFINITI', 'INTERNATIONAL', 'ISUZU', 'JAC', 'JAGUAR',
    'JEEP', 'JENSEN', 'KARMA', 'KIA', 'KUBOTA', 'LAFORZA', 'LAND ROVER',
    'LEXUS', 'LINCOLN', 'LOTUS', 'MACK', 'MAZDA', 'MERCEDES-BENZ', 'MERCURY',
    'MERKUR', 'MINI', 'MITSUBISHI', 'MORGAN', 'NISSAN', 'NSU', 'OLDSMOBILE',
    'OPEL', 'OSHKOSH MOTOR TRUCK CO.', 'PETERBILT', 'PEUGEOT', 'PLYMOUTH',
    'POLARIS', 'PONTIAC', 'PORSCHE', 'QVALE', 'RAM', 'RENAULT', 'ROLLS ROYCE',
    'SAAB', 'SATURN', 'SCION', 'SEAT', 'SHELBY', 'SMART', 'SRT',
    'STERLING TRUCK', 'STUDEBAKER', 'SUBARU', 'SUNBEAM', 'SUZUKI', 'TOYOTA',
    'TRIUMPH', 'VAM', 'VOLKSWAGEN', 'VOLVO', 'VPG', 'WORKHORSE',
    'WORKHORSE CUSTOM CHASSIS', 'YAMAHA', 'YUGO',
}


def get_db():
    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row
    return conn


def ensure_manufacturer(cursor, name, type_='aftermarket', quality='standard', country=None):
    cursor.execute("SELECT id FROM manufacturers WHERE UPPER(name) = UPPER(?)", (name,))
    row = cursor.fetchone()
    if row:
        return row['id']
    cursor.execute(
        "INSERT INTO manufacturers (name, type, quality_tier, country) VALUES (?, ?, ?, ?)",
        (name, type_, quality, country))
    return cursor.lastrowid


def ensure_brand(cursor, name):
    cursor.execute("SELECT id FROM brands WHERE UPPER(name) = UPPER(?)", (name,))
    row = cursor.fetchone()
    if row:
        return row['id']
    cursor.execute("INSERT INTO brands (name) VALUES (?)", (name,))
    return cursor.lastrowid


def ensure_model(cursor, brand_id, name):
    cursor.execute(
        "SELECT id FROM models WHERE brand_id = ? AND UPPER(name) = UPPER(?)",
        (brand_id, name))
    row = cursor.fetchone()
    if row:
        return row['id']
    cursor.execute("INSERT INTO models (brand_id, name) VALUES (?, ?)", (brand_id, name))
    return cursor.lastrowid


def ensure_year(cursor, year):
    cursor.execute("SELECT id FROM years WHERE year = ?", (year,))
    row = cursor.fetchone()
    if row:
        return row['id']
    cursor.execute("INSERT INTO years (year) VALUES (?)", (year,))
    return cursor.lastrowid


def get_generic_engine(cursor):
    """Get or create a generic engine for catalogs without engine data."""
    cursor.execute("SELECT id FROM engines WHERE name = 'Generic'")
    row = cursor.fetchone()
    if row:
        return row['id']
    cursor.execute("INSERT INTO engines (name, fuel_type) VALUES ('Generic', 'gasoline')")
    return cursor.lastrowid


def ensure_mye(cursor, model_id, year_id, engine_id=None):
    if engine_id:
        cursor.execute(
            "SELECT id FROM model_year_engine WHERE model_id = ? AND year_id = ? AND engine_id = ?",
            (model_id, year_id, engine_id))
    else:
        cursor.execute(
            "SELECT id FROM model_year_engine WHERE model_id = ? AND year_id = ?",
            (model_id, year_id))
    row = cursor.fetchone()
    if row:
        return row['id']
    if not engine_id:
        engine_id = get_generic_engine(cursor)
    cursor.execute(
        "INSERT INTO model_year_engine (model_id, year_id, engine_id) VALUES (?, ?, ?)",
        (model_id, year_id, engine_id))
    return cursor.lastrowid


def get_or_create_part(cursor, part_number, group_id, name, name_es, description):
    cursor.execute("SELECT id FROM parts WHERE oem_part_number = ?", (part_number,))
    row = cursor.fetchone()
    if row:
        return row['id'], False
    cursor.execute(
        "INSERT INTO parts (oem_part_number, name, name_es, group_id, description) VALUES (?, ?, ?, ?, ?)",
        (part_number, name, name_es, group_id, description))
    return cursor.lastrowid, True


def get_oil_filter_group(cursor):
    cursor.execute(
        "SELECT id FROM part_groups WHERE name = 'Oil Filters' LIMIT 1")
    row = cursor.fetchone()
    if row:
        return row['id']
    cursor.execute("SELECT id FROM part_categories WHERE name = 'Engine' LIMIT 1")
    cat = cursor.fetchone()
    if not cat:
        return None
    cursor.execute(
        "INSERT INTO part_groups (category_id, name, name_es) VALUES (?, 'Oil Filters', 'Filtros de Aceite')",
        (cat['id'],))
    return cursor.lastrowid


def parse_cartek_pdf(pdf_path):
    """Parse the Cartek oil filter catalog PDF."""
    pdf = pypdf.PdfReader(pdf_path)
    entries = []
    current_brand = None

    for page_num in range(4, len(pdf.pages)):  # Skip cover/index pages
        text = pdf.pages[page_num].extract_text()
        if not text:
            continue

        lines = text.split('\n')
        pending_model = None

        for line in lines:
            line = line.strip()
            if not line:
                continue

            # Skip header/footer lines
            if 'Marca/Modelo' in line or 'Observaciones' in line:
                continue
            # Skip page numbers
            if re.match(r'^\d{1,3}$', line):
                continue

            # Check for brand header
            if line in BRAND_HEADERS:
                current_brand = line
                pending_model = None
                continue

            if not current_brand:
                continue

            # Try to parse data line: Model YearFrom YearTo CTK#### Observations
            match = re.match(
                r'^(.+?)\s+(\d{4})\s+(\d{4})\s+(CTK\w+)\s+(.*)$', line)
            if match:
                model = match.group(1).strip()
                if pending_model:
                    model = f"{pending_model} {model}"
                    pending_model = None

                year_from = int(match.group(2))
                year_to = int(match.group(3))
                part_number = match.group(4).strip()
                observations = match.group(5).strip()

                for year in range(year_from, year_to + 1):
                    entries.append({
                        'brand': current_brand,
                        'model': model,
                        'year': year,
                        'part_number': part_number,
                        'observations': observations,
                    })
            else:
                # Check if this is a continuation model name (e.g., "Avalanche")
                # followed by a sub-model on the next line
                if not re.match(r'^\d', line) and not line.startswith('CTK'):
                    # Could be a model name prefix (like "Avalanche" before "1500")
                    # or a sub-brand header we don't recognize
                    pending_model = line
                else:
                    pending_model = None

    return entries


def main():
    print("=" * 70)
    print("IMPORTADOR - CATÁLOGO CARTEK FILTROS DE ACEITE")
    print("=" * 70)

    print(f"\n[1/5] Leyendo PDF: {PDF_PATH}")
    entries = parse_cartek_pdf(PDF_PATH)
    print(f"      Entradas parseadas: {len(entries)}")

    # Get unique parts and brands
    unique_parts = set(e['part_number'] for e in entries)
    unique_brands = set(e['brand'] for e in entries)
    print(f"      Partes únicas: {len(unique_parts)}")
    print(f"      Marcas de vehículos: {len(unique_brands)}")

    conn = get_db()
    cursor = conn.cursor()

    # Create Cartek manufacturer
    print("\n[2/5] Creando fabricante Cartek...")
    cartek_mfr_id = ensure_manufacturer(cursor, 'Cartek', 'aftermarket', 'standard', 'Mexico')
    print(f"      Cartek manufacturer_id: {cartek_mfr_id}")

    # Get oil filter group
    oil_group_id = get_oil_filter_group(cursor)
    print(f"      Oil Filters group_id: {oil_group_id}")

    # Create parts
    print("\n[3/5] Creando partes de filtros...")
    part_ids = {}
    parts_created = 0
    for pn in sorted(unique_parts):
        name = f"Oil Filter {pn}"
        name_es = f"Filtro de Aceite {pn}"
        part_id, created = get_or_create_part(
            cursor, pn, oil_group_id, name, name_es, "Cartek Oil Filter")
        part_ids[pn] = part_id
        if created:
            parts_created += 1
    print(f"      Partes creadas: {parts_created}")
    print(f"      Partes existentes: {len(unique_parts) - parts_created}")

    # Create vehicles and fitments
    print("\n[4/5] Creando vehículos y fitments...")
    vehicles_created = 0
    fitments_created = 0
    mye_cache = {}

    for entry in entries:
        cache_key = (entry['brand'], entry['model'], entry['year'])
        if cache_key not in mye_cache:
            brand_id = ensure_brand(cursor, entry['brand'])
            model_id = ensure_model(cursor, brand_id, entry['model'])
            year_id = ensure_year(cursor, entry['year'])

            # Try to find existing MYE (any engine)
            cursor.execute(
                """SELECT mye.id FROM model_year_engine mye
                   JOIN models m ON mye.model_id = m.id
                   JOIN brands b ON m.brand_id = b.id
                   JOIN years y ON mye.year_id = y.id
                   WHERE UPPER(b.name) = UPPER(?) AND UPPER(m.name) = UPPER(?) AND y.year = ?
                   LIMIT 1""",
                (entry['brand'], entry['model'], entry['year']))
            existing = cursor.fetchone()

            if existing:
                mye_cache[cache_key] = existing['id']
            else:
                mye_id = ensure_mye(cursor, model_id, year_id)
                mye_cache[cache_key] = mye_id
                vehicles_created += 1

        mye_id = mye_cache[cache_key]
        part_id = part_ids.get(entry['part_number'])
        if not part_id:
            continue

        # Check if fitment exists
        cursor.execute(
            "SELECT id FROM vehicle_parts WHERE model_year_engine_id = ? AND part_id = ?",
            (mye_id, part_id))
        if not cursor.fetchone():
            notes = f"Catálogo Cartek - ACEITE"
            if entry['observations'] and entry['observations'] != '-':
                notes += f" ({entry['observations']})"
            cursor.execute(
                "INSERT INTO vehicle_parts (model_year_engine_id, part_id, quantity_required, fitment_notes) VALUES (?, ?, 1, ?)",
                (mye_id, part_id, notes))
            fitments_created += 1

    print(f"      Vehículos creados: {vehicles_created}")
    print(f"      Fitments creados: {fitments_created}")

    # Create cross-references by matching Cartek parts to existing parts (Gonher, etc.)
    # that fit the same vehicle
    print("\n[5/5] Creando referencias cruzadas...")
    xrefs_created = 0

    for pn, part_id in part_ids.items():
        # Find other parts in the same group that fit the same vehicles
        cursor.execute("""
            SELECT DISTINCT p2.id, p2.oem_part_number
            FROM vehicle_parts vp1
            JOIN vehicle_parts vp2 ON vp1.model_year_engine_id = vp2.model_year_engine_id
            JOIN parts p2 ON vp2.part_id = p2.id
            WHERE vp1.part_id = ?
              AND p2.id != ?
              AND p2.group_id = (SELECT group_id FROM parts WHERE id = ?)
              AND p2.oem_part_number NOT LIKE 'CTK%'
            LIMIT 20
        """, (part_id, part_id, part_id))

        for row in cursor.fetchall():
            # Add cross-ref from Cartek to other brand
            cursor.execute(
                "SELECT id FROM part_cross_references WHERE part_id = ? AND cross_reference_number = ?",
                (part_id, row['oem_part_number']))
            if not cursor.fetchone():
                cursor.execute(
                    "INSERT INTO part_cross_references (part_id, cross_reference_number, reference_type, source) VALUES (?, ?, 'interchange', 'Cartek Catalog')",
                    (part_id, row['oem_part_number']))
                xrefs_created += 1

            # Add reverse cross-ref
            cursor.execute(
                "SELECT id FROM part_cross_references WHERE part_id = ? AND cross_reference_number = ?",
                (row['id'], pn))
            if not cursor.fetchone():
                cursor.execute(
                    "INSERT INTO part_cross_references (part_id, cross_reference_number, reference_type, source) VALUES (?, ?, 'interchange', 'Cartek Catalog')",
                    (row['id'], pn))
                xrefs_created += 1

    print(f"      Cross-refs creadas: {xrefs_created}")

    conn.commit()
    conn.close()

    print("\n" + "=" * 70)
    print("IMPORTACIÓN CARTEK COMPLETADA")
    print("=" * 70)
    print(f"""
RESUMEN:
  - Partes creadas:        {parts_created:,}
  - Vehículos creados:     {vehicles_created:,}
  - Fitments creados:      {fitments_created:,}
  - Cross-refs creadas:    {xrefs_created:,}
""")


if __name__ == '__main__':
    main()
