#!/usr/bin/env python3
import asyncio
import logging
import random
import json
import sys
from playwright.async_api import async_playwright
from sqlalchemy import text
from app.database import AsyncSessionLocal

# --- NAPLÓZÁS KONFIGURÁCIÓ ---
logging.basicConfig(level=logging.INFO, format='%(asctime)s [R4-HARVESTER-v1.2] %(message)s')
logger = logging.getLogger("R4")

# --- KONFIGURÁCIÓS PARAMÉTEREK ---
MAX_RETRY_LIMIT = 5  # Max 5 próbálkozás járművenként

async def parse_specs(page):
    """
    A GYŐZTES DOM PARSZOLÓ LOGIKA (HIÁNYTALAN)
    Ez a script felismeri a hibás táblázatokat, a dt/dd listákat és a sima vastagított szövegeket is.
    """
    script = """
    () => {
        let results = {};
        
        // 1. MÓDSZER: Régi motorok (pl. BMW F650GS) -> td.left és td.right
        let leftCells = document.querySelectorAll('td.left');
        leftCells.forEach(cell => {
            let key = cell.innerText.replace(/:$/, '').trim();
            let rightCell = cell.nextElementSibling;
            if(rightCell && rightCell.classList.contains('right')) {
                results[key] = rightCell.innerText.trim();
            }
        });

        // 2. MÓDSZER: Modern motorok (pl. Aprilia) -> dt és dd
        let dts = document.querySelectorAll('dt');
        dts.forEach(dt => {
            let key = dt.innerText.replace(/:$/, '').trim();
            let dd = dt.nextElementSibling;
            if(dd && dd.tagName.toLowerCase() === 'dd') {
                results[key] = dd.innerText.trim();
            }
        });

        // 3. MÓDSZER: Alternatív modern layout -> span.label és span.value
        let specRows = document.querySelectorAll('.spec-row');
        specRows.forEach(row => {
            let label = row.querySelector('.label');
            let value = row.querySelector('.value');
            if(label && value) {
                let key = label.innerText.replace(/:$/, '').trim();
                if (!results[key]) {
                    results[key] = value.innerText.trim();
                }
            }
        });
        
        // 4. MÓDSZER: Veterán ("Adler") fallback -> Vastagított szöveg
        if (Object.keys(results).length === 0) {
            document.querySelectorAll('b, strong').forEach(b => {
                 let key = b.innerText.replace(/:$/, '').trim();
                 if(key.length > 2 && key.length < 30) {
                     let val = "";
                     if(b.nextSibling && b.nextSibling.nodeType === 3) {
                         val = b.nextSibling.textContent.trim();
                     } 
                     else if (b.nextElementSibling && b.nextElementSibling.tagName !== 'B') {
                         val = b.nextElementSibling.innerText.trim();
                     }
                     if(val && !results[key]) {
                         results[key] = val;
                     }
                 }
            });
        }
        
        return results;
    }
    """
    try:
        data = await page.evaluate(script)
        
        if data and len(data) > 0:
            relevant_keys = [
                "Production", "Year", "Segment",
                "Type", "Displacement", "Bore X Stroke", "Compression Ratio", 
                "Horsepower", "Torque", "Fuel System", "Gearbox", "Clutch", 
                "Final Drive", "Frame", "Front Suspension", "Rear Suspension", 
                "Front Brake", "Rear Brake", "Overall Length", "Overall Width", 
                "Seat Height", "Wheelbase", "Fuel Capacity", "Weight", "Dry Weight", 
                "Wet Weight", "Front", "Rear"
            ]
            
            filtered_data = {k: v for k, v in data.items() if any(rk.lower() in k.lower() for rk in relevant_keys)}
            return filtered_data if len(filtered_data) > 0 else data
            
        return None
        
    except Exception as e:
        logger.error(f"❌ Parszolási hiba a JS kiértékeléskor: {e}")
        return None

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        context = await browser.new_context(
            user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
            viewport={'width': 1920, 'height': 1080}
        )
        logger.info("🤖 R4 Motor Adat-Arató v1.2 elindult.")
        
        while True:
            target = None
            try:
                async with AsyncSessionLocal() as db:
                    # JAVÍTÁS: Kikerült a completed_empty a választható státuszok közül!
                    # Csak 'pending' és 'error' jöhet, ha a retry_count < 5.
                    res = await db.execute(text("""
                        UPDATE vehicle.auto_data_crawler_queue SET status = 'processing'
                        WHERE id = (
                            SELECT id FROM vehicle.auto_data_crawler_queue 
                            WHERE status IN ('pending', 'error') 
                              AND retry_count < 5
                              AND level = 'engine' AND category = 'bike'
                            ORDER BY id ASC LIMIT 1 FOR UPDATE SKIP LOCKED
                        ) RETURNING id, url, name, retry_count
                    """))
                    target = res.fetchone()
                    await db.commit()
            except Exception as e:
                logger.error(f"❌ DB Hiba a feladatfelvételnél: {e}")
                await asyncio.sleep(5)
                continue

            if not target:
                logger.info("🏁 Minden motor feldolgozva vagy manuális felülvizsgálatra vár. Alvás 60mp...")
                await asyncio.sleep(60)
                continue

            t_id, t_url, t_name, t_retry_count = target
            if t_retry_count is None: t_retry_count = 0
            
            page = await context.new_page()
            
            try:
                logger.info(f"📊 [{t_retry_count + 1}/5] Adatbányászat: {t_name}")
                await page.goto(t_url, wait_until="domcontentloaded", timeout=60000)
                await asyncio.sleep(2) 
                
                data = await parse_specs(page)
                
                async with AsyncSessionLocal() as db:
                    if data and len(data) > 0:
                        # SIKERES MENTÉS
                        await db.execute(text("""
                            INSERT INTO vehicle.motorcycle_specs (crawler_id, full_name, raw_data, url)
                            VALUES (:cid, :name, :data, :url)
                            ON CONFLICT (crawler_id) DO UPDATE SET raw_data = :data, updated_at = NOW()
                        """), {"cid": t_id, "name": t_name, "data": json.dumps(data), "url": t_url})
                        
                        await db.execute(text("UPDATE vehicle.auto_data_crawler_queue SET status = 'completed', updated_at = NOW() WHERE id = :id"), {"id": t_id})
                        await db.commit()
                        logger.info(f"✅ Mentve: {t_name} ({len(data)} paraméter)")
                    else:
                        # ÜRES OLDAL VAGY HIÁNYZÓ ADAT
                        new_retry_count = t_retry_count + 1
                        
                        if new_retry_count >= 5:
                            # Elérte a limitet -> JAVÍTANDÓ (manual_review_needed)
                            await db.execute(text("""
                                UPDATE vehicle.auto_data_crawler_queue 
                                SET status = 'manual_review_needed', 
                                    retry_count = :rc,
                                    error_msg = 'Sikertelen adatgyűjtés 5 próbálkozás után (üres oldal)',
                                    updated_at = NOW() 
                                WHERE id = :id
                            """), {"rc": new_retry_count, "id": t_id})
                            logger.error(f"🚨 LIMIT ELÉRVE: {t_name} -> manuális javításra jelölve.")
                        else:
                            # Még próbálkozhat -> státusz visszaállítása hibára
                            await db.execute(text("""
                                UPDATE vehicle.auto_data_crawler_queue 
                                SET status = 'error', 
                                    retry_count = :rc, 
                                    updated_at = NOW() 
                                WHERE id = :id
                            """), {"rc": new_retry_count, "id": t_id})
                            logger.warning(f"⚠️ Üres maradt: {t_name} (Próbálkozás: {new_retry_count}/5)")
                        
                        await db.commit()
                        
            except Exception as e:
                logger.error(f"❌ Hiba a feldolgozás során: {t_name} -> {e}")
                async with AsyncSessionLocal() as db:
                    new_retry_count = t_retry_count + 1
                    status = 'error' if new_retry_count < 5 else 'manual_review_needed'
                    await db.execute(text("""
                        UPDATE vehicle.auto_data_crawler_queue 
                        SET status = :st, 
                            retry_count = :rc, 
                            error_msg = :msg, 
                            updated_at = NOW() 
                        WHERE id = :id
                    """), {"st": status, "rc": new_retry_count, "msg": str(e), "id": t_id})
                    await db.commit()
            finally:
                await page.close()
                await asyncio.sleep(random.uniform(2.0, 4.0))
                
        await browser.close()

if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        logger.info("🛑 Felhasználói leállítás.")