import asyncio
import os
import sys
import importlib.util
from pathlib import Path
from sqlalchemy import inspect, text
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy.dialects.postgresql import JSONB, ENUM, NUMERIC

# Elérési utak beállítása
BASE_DIR = Path(__file__).resolve().parents[2]
sys.path.append(str(BASE_DIR))

try:
    from app.database import Base, engine
    from app.core.config import settings
except ImportError as e:
    print(f"❌ Hiba az alapvető importoknál: {e}")
    sys.exit(1)

def dynamic_import_models(models_dir: Path):
    """
    Automatikusan bejárja az app/models mappát és beimportál minden .py fájlt,
    hogy a Base.metadata.tables feltöltődjön.
    """
    print(f"🔍 Modellek dinamikus felderítése itt: {models_dir}...")
    count = 0
    for root, _, files in os.walk(models_dir):
        for file in files:
            if file.endswith(".py") and file != "__init__.py":
                full_path = Path(root) / file
                # Modul név képzése (pl. app.models.identity.user)
                rel_path = full_path.relative_to(BASE_DIR)
                module_name = str(rel_path).replace(os.sep, ".").replace(".py", "")
                
                try:
                    spec = importlib.util.spec_from_file_location(module_name, full_path)
                    module = importlib.util.module_from_spec(spec)
                    spec.loader.exec_module(module)
                    count += 1
                except Exception as e:
                    print(f"  ⚠️  Nem sikerült importálni: {module_name} -> {e}")
    print(f"✅ {count} modell fájl sikeresen betöltve a memóriába.\n")

async def run_unified_audit():
    # 1. Modellek betöltése
    models_path = BASE_DIR / "app" / "models"
    dynamic_import_models(models_path)

    print(f"🔗 Kapcsolódás az adatbázishoz: {settings.POSTGRES_DB}")
    
    async with engine.connect() as conn:
        inspector = await conn.run_sync(inspect)
        all_db_schemas = await conn.run_sync(lambda c: inspector.get_schema_names())
        
        # Kigyűjtjük a modellekben definiált sémákat
        expected_schemas = sorted({t.schema for t in Base.metadata.sorted_tables if t.schema})
        
        mismatches = 0
        suggestions = []

        for sc in expected_schemas:
            print(f"\n--- 🛰️ DOMAIN AUDIT: '{sc}' ---")
            if sc not in all_db_schemas:
                print(f"❌ KRITIKUS: A(z) '{sc}' séma hiányzik!")
                mismatches += 1
                continue

            db_tables = await conn.run_sync(lambda c: inspector.get_table_names(schema=sc))
            model_tables = [t for t in Base.metadata.sorted_tables if t.schema == sc]

            for table in model_tables:
                t_name = table.name
                if t_name not in db_tables:
                    print(f"❌ HIÁNYZÓ TÁBLA: {sc}.{t_name}")
                    mismatches += 1
                    suggestions.append(f"-- Hozd létre a táblát: {sc}.{t_name}")
                    continue

                # Oszlopok lekérése a DB-ből
                db_cols = {c['name']: c for c in await conn.run_sync(
                    lambda c: inspector.get_columns(t_name, schema=sc)
                )}
                
                # Oszlopok lekérése a Modellből
                for col in table.columns:
                    if col.name not in db_cols:
                        print(f"⚠️  HIÁNYZÓ OSZLOP: {sc}.{t_name}.{col.name}")
                        mismatches += 1
                        suggestions.append(f"ALTER TABLE {sc}.{t_name} ADD COLUMN {col.name} {col.type};")
                    else:
                        # MÉLY TÍPUS ELLENŐRZÉS
                        db_col = db_cols[col.name]
                        db_type_str = str(db_col['type']).upper()
                        
                        # 1. JSONB Ellenőrzés
                        if isinstance(col.type, JSONB) and "JSONB" not in db_type_str:
                            print(f"🔬 TÍPUS ELTÉRÉS [JSONB]: {sc}.{t_name}.{col.name} (DB: {db_type_str})")
                            mismatches += 1

                        # 2. NUMERIC Precizitás
                        elif isinstance(col.type, NUMERIC):
                            m_prec, m_scale = col.type.precision, col.type.scale
                            d_prec, d_scale = db_col['type'].precision, db_col['type'].scale
                            if m_prec != d_prec or m_scale != d_scale:
                                print(f"🔬 TÍPUS ELTÉRÉS [NUMERIC]: {sc}.{t_name}.{col.name} (Kód: {m_prec},{m_scale} vs DB: {d_prec},{d_scale})")
                                mismatches += 1

                        # 3. ENUM Ellenőrzés
                        elif isinstance(col.type, ENUM):
                            enum_name = col.type.name
                            res = await conn.execute(text(
                                "SELECT EXISTS (SELECT 1 FROM pg_type WHERE typname = :name)"), 
                                {"name": enum_name}
                            )
                            if not res.scalar():
                                print(f"🔬 HIÁNYZÓ ENUM TÍPUS: {enum_name} ({sc}.{t_name}.{col.name})")
                                mismatches += 1

                print(f"✅ {sc}.{t_name:30} | Átvizsgálva.")

        print("\n" + "="*50)
        if mismatches == 0:
            print("✨ GRATULÁLOK! A fájlrendszer és az adatbázis szinkronban van. ✨")
        else:
            print(f"⚠️  ÖSSZESEN {mismatches} ELTÉRÉS TALÁLHATÓ!")
            print("\nJAVÍTÁSI JAVASLATOK (Copy-Paste SQL):")
            for s in suggestions:
                print(f"  {s}")
        print("="*50 + "\n")

if __name__ == "__main__":
    asyncio.run(run_unified_audit())