#!/usr/bin/env python3
"""
FASE 4: Full-Text Search and VIN Decoder
This script creates FASE 4 tables (FTS5, triggers, vin_cache) and populates
the parts_fts table with existing parts data.
"""

import sqlite3
import os
import json
from typing import Optional
from datetime import datetime, timedelta

# Database path configuration
DB_PATH = os.path.join(os.path.dirname(__file__), '..', 'vehicle_database.db')
SCHEMA_PATH = os.path.join(os.path.dirname(__file__), '..', 'sql', 'schema.sql')


class Fase4Manager:
    """Manager for FASE 4 tables: parts_fts, vin_cache, and related triggers"""

    def __init__(self, db_path: str = DB_PATH):
        self.db_path = db_path
        self.connection = None

    def connect(self):
        """Connect to the SQLite database"""
        self.connection = sqlite3.connect(self.db_path)
        self.connection.row_factory = sqlite3.Row
        print(f"Connected to database: {self.db_path}")

    def disconnect(self):
        """Close the database connection"""
        if self.connection:
            self.connection.close()
            print("Disconnected from database")

    def create_fase4_tables(self):
        """Create FASE 4 tables from schema file"""
        if not os.path.exists(SCHEMA_PATH):
            raise FileNotFoundError(f"Schema file not found: {SCHEMA_PATH}")

        with open(SCHEMA_PATH, 'r') as f:
            schema = f.read()

        if self.connection:
            cursor = self.connection.cursor()
            cursor.executescript(schema)
            self.connection.commit()
            print("FASE 4 tables created successfully")

    def check_fts_table_exists(self) -> bool:
        """Check if the parts_fts FTS5 table exists"""
        cursor = self.connection.cursor()
        cursor.execute(
            "SELECT name FROM sqlite_master WHERE type='table' AND name='parts_fts'"
        )
        return cursor.fetchone() is not None

    def check_fts_populated(self) -> bool:
        """Check if the FTS table has any data"""
        cursor = self.connection.cursor()
        try:
            cursor.execute("SELECT COUNT(*) FROM parts_fts")
            count = cursor.fetchone()[0]
            return count > 0
        except sqlite3.OperationalError:
            return False

    def populate_fts_from_parts(self):
        """Populate the parts_fts table with existing parts data"""
        if not self.check_fts_table_exists():
            print("FTS table does not exist, creating tables first...")
            self.create_fase4_tables()

        # Check if already populated
        if self.check_fts_populated():
            print("parts_fts table already has data, skipping population")
            return

        cursor = self.connection.cursor()

        # Get count of parts
        cursor.execute("SELECT COUNT(*) FROM parts")
        parts_count = cursor.fetchone()[0]

        if parts_count == 0:
            print("No parts found in parts table, nothing to populate")
            return

        # Populate FTS table from parts
        cursor.execute("""
            INSERT INTO parts_fts(rowid, oem_part_number, name, name_es, description, description_es)
            SELECT id, oem_part_number, name, name_es, description, description_es FROM parts
        """)
        self.connection.commit()

        # Rebuild FTS index for proper search functionality
        cursor.execute("INSERT INTO parts_fts(parts_fts) VALUES('rebuild')")
        self.connection.commit()

        # Verify population
        cursor.execute("SELECT COUNT(*) FROM parts_fts")
        fts_count = cursor.fetchone()[0]
        print(f"Populated parts_fts with {fts_count} entries from {parts_count} parts")

    def get_vin_by_vin(self, vin: str) -> Optional[int]:
        """Get VIN cache entry ID by VIN, returns None if not found"""
        cursor = self.connection.cursor()
        cursor.execute("SELECT id FROM vin_cache WHERE vin = ?", (vin,))
        result = cursor.fetchone()
        return result[0] if result else None

    def insert_vin_cache(self, vin: str, decoded_data: dict, make: str, model: str,
                         year: int, engine_info: str = None, body_class: str = None,
                         drive_type: str = None, model_year_engine_id: int = None,
                         expires_days: int = 30) -> int:
        """Insert a VIN cache entry if it doesn't exist, return its ID"""
        existing_id = self.get_vin_by_vin(vin)
        if existing_id:
            print(f"  VIN '{vin}' already exists in cache (ID: {existing_id})")
            return existing_id

        cursor = self.connection.cursor()
        expires_at = datetime.now() + timedelta(days=expires_days)

        cursor.execute(
            """INSERT INTO vin_cache
               (vin, decoded_data, make, model, year, engine_info, body_class,
                drive_type, model_year_engine_id, expires_at)
               VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
            (vin, json.dumps(decoded_data), make, model, year, engine_info,
             body_class, drive_type, model_year_engine_id, expires_at.isoformat())
        )
        self.connection.commit()
        vin_id = cursor.lastrowid
        print(f"  Inserted VIN cache: {vin} -> {make} {model} {year} (ID: {vin_id})")
        return vin_id

    def populate_sample_vins(self):
        """Populate sample VIN cache entries for testing"""
        print("\nPopulating sample VIN cache entries...")

        sample_vins = [
            {
                'vin': '4T1BF1FK5CU123456',
                'decoded_data': {
                    'Make': 'TOYOTA',
                    'Model': 'Camry',
                    'ModelYear': '2023',
                    'EngineModel': '2.5L I4',
                    'BodyClass': 'Sedan/Saloon',
                    'DriveType': 'FWD',
                    'PlantCountry': 'UNITED STATES (USA)',
                    'VehicleType': 'PASSENGER CAR'
                },
                'make': 'Toyota',
                'model': 'Camry',
                'year': 2023,
                'engine_info': '2.5L I4 DOHC 16V',
                'body_class': 'Sedan',
                'drive_type': 'FWD'
            },
            {
                'vin': '1HGBH41JXMN109186',
                'decoded_data': {
                    'Make': 'HONDA',
                    'Model': 'Civic',
                    'ModelYear': '2023',
                    'EngineModel': '2.0L I4',
                    'BodyClass': 'Sedan/Saloon',
                    'DriveType': 'FWD',
                    'PlantCountry': 'UNITED STATES (USA)',
                    'VehicleType': 'PASSENGER CAR'
                },
                'make': 'Honda',
                'model': 'Civic',
                'year': 2023,
                'engine_info': '2.0L I4 DOHC 16V',
                'body_class': 'Sedan',
                'drive_type': 'FWD'
            },
            {
                'vin': '1FA6P8CF5L5123456',
                'decoded_data': {
                    'Make': 'FORD',
                    'Model': 'Mustang',
                    'ModelYear': '2020',
                    'EngineModel': '5.0L V8',
                    'BodyClass': 'Coupe',
                    'DriveType': 'RWD',
                    'PlantCountry': 'UNITED STATES (USA)',
                    'VehicleType': 'PASSENGER CAR'
                },
                'make': 'Ford',
                'model': 'Mustang',
                'year': 2020,
                'engine_info': '5.0L V8 Coyote',
                'body_class': 'Coupe',
                'drive_type': 'RWD'
            }
        ]

        for vin_data in sample_vins:
            self.insert_vin_cache(
                vin=vin_data['vin'],
                decoded_data=vin_data['decoded_data'],
                make=vin_data['make'],
                model=vin_data['model'],
                year=vin_data['year'],
                engine_info=vin_data['engine_info'],
                body_class=vin_data['body_class'],
                drive_type=vin_data['drive_type']
            )

    def verify_installation(self):
        """Verify FASE 4 installation"""
        cursor = self.connection.cursor()

        print("\n" + "=" * 50)
        print("FASE 4 Installation Verification")
        print("=" * 50)

        # Check FTS table
        cursor.execute(
            "SELECT name FROM sqlite_master WHERE type='table' AND name='parts_fts'"
        )
        fts_exists = cursor.fetchone() is not None
        print(f"parts_fts table: {'OK' if fts_exists else 'MISSING'}")

        if fts_exists:
            cursor.execute("SELECT COUNT(*) FROM parts_fts")
            fts_count = cursor.fetchone()[0]
            print(f"  - FTS entries: {fts_count}")

        # Check triggers
        triggers = ['parts_fts_insert', 'parts_fts_delete', 'parts_fts_update']
        for trigger_name in triggers:
            cursor.execute(
                "SELECT name FROM sqlite_master WHERE type='trigger' AND name=?",
                (trigger_name,)
            )
            trigger_exists = cursor.fetchone() is not None
            print(f"Trigger {trigger_name}: {'OK' if trigger_exists else 'MISSING'}")

        # Check vin_cache table
        cursor.execute(
            "SELECT name FROM sqlite_master WHERE type='table' AND name='vin_cache'"
        )
        vin_exists = cursor.fetchone() is not None
        print(f"vin_cache table: {'OK' if vin_exists else 'MISSING'}")

        if vin_exists:
            cursor.execute("SELECT COUNT(*) FROM vin_cache")
            vin_count = cursor.fetchone()[0]
            print(f"  - VIN cache entries: {vin_count}")

            cursor.execute("SELECT vin, make, model, year FROM vin_cache")
            for row in cursor.fetchall():
                print(f"    - {row['vin']}: {row['make']} {row['model']} {row['year']}")

        # Check indexes
        indexes = ['idx_vin_cache_vin', 'idx_vin_cache_make_model']
        for index_name in indexes:
            cursor.execute(
                "SELECT name FROM sqlite_master WHERE type='index' AND name=?",
                (index_name,)
            )
            index_exists = cursor.fetchone() is not None
            print(f"Index {index_name}: {'OK' if index_exists else 'MISSING'}")

        print("=" * 50)


def main():
    """Main function to populate FASE 4 tables"""
    print("=" * 60)
    print("FASE 4: Full-Text Search and VIN Decoder Population")
    print("=" * 60)

    manager = Fase4Manager()

    try:
        manager.connect()

        # Step 1: Create FASE 4 tables (FTS5, triggers, vin_cache)
        print("\n[1/4] Creating FASE 4 tables...")
        manager.create_fase4_tables()

        # Step 2: Populate FTS table with existing parts
        print("\n[2/4] Populating Full-Text Search index...")
        manager.populate_fts_from_parts()

        # Step 3: Add sample VIN cache entries
        print("\n[3/4] Adding sample VIN cache entries...")
        manager.populate_sample_vins()

        # Step 4: Verify installation
        print("\n[4/4] Verifying FASE 4 installation...")
        manager.verify_installation()

        print("\nFASE 4 population completed successfully!")

    except Exception as e:
        print(f"\nError during FASE 4 population: {e}")
        raise
    finally:
        manager.disconnect()


if __name__ == '__main__':
    main()
