import asyncio
import logging
import random
import re
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 [R2-AUTOS-ONLY] %(message)s',
    handlers=[logging.StreamHandler()]
)
logger = logging.getLogger("R2")

async def get_page_safe(page, url):
    """
    Gondolatmenet: Az anti-bot védelem (Cloudflare) kijátszása érdekében 
    véletlenszerű várakozást és valós User-Agent viselkedést szimulálunk.
    """
    delay = random.uniform(4, 7)
    await asyncio.sleep(delay)
    
    try:
        # A domcontentloaded gyorsabb, mint a networkidle, de elég a linkgyűjtéshez
        await page.goto(url, wait_until="domcontentloaded", timeout=60000)
        
        # Ellenőrizzük, hogy nem kaptunk-e blokkoló oldalt
        title = await page.title()
        if "Just a moment" in title or "Cloudflare" in title:
            raise Exception(f"Bot védelem észlelve az URL-en: {url}")
            
        return page
    except Exception as e:
        logger.error(f"Hiba az oldal betöltésekor: {url} -> {e}")
        raise

async def extract_scoped_links(page, p_id, current_url):
    """
    Gondolatmenet: A 'Scope-Lock' technika lényege, hogy az URL-kből kinyert
    márkanév horgony (anchor) segítségével megakadályozzuk, hogy a robot 
    kilépjen a jelenlegi autócsalád környezetéből.
    
    Javítás: Beépített nyelvi szűrő és 'Language Shield' a nem kívánt (görög, spanyol, bolgár stb.) 
    változatok elkerülésére. Minden talált új linket 'car' kategóriával mentünk el.
    """
    # Kinyerjük a márka/típus nevét az URL-ből (pl. 'alfa-romeo')
    url_parts = current_url.split('/')[-1].split('-')
    brand_anchor = "-".join(url_parts[:2]) 
    
    # Csak azokat a linkeket gyűjtjük, amik valódi navigációt jelentenek
    hrefs = await page.eval_on_selector_all(
        "a", 
        "nodes => nodes.map(n => ({ 'name': n.innerText.trim(), 'url': n.href }))"
    )
    
    found_count = 0
    async with AsyncSessionLocal() as db:
        for link in hrefs:
            url = link['url']
            name = link['name'].replace('\n', ' ').strip()
            
            # --- 1. ALAPVETŐ ÉRVÉNYESSÉG ---
            if not name or len(name) < 2: 
                continue

            # --- 2. LANGUAGE SHIELD (ÚJ VÉDELEM) ---
            # Karakterkészlet ellenőrzés: Ha görög, cirill vagy egyéb nem latin karakter van benne, eldobjuk.
            if re.search(r'[^\x00-\x7F]+', name): 
                continue

            # Szigorított angol-kényszerítés az URL-ben
            if '/en/' not in url:
                continue

            # Szövegalapú zajszűrés (Meta-linkek kizárása)
            junk_keywords = [
                'privacy', 'configuracion', 'ρυθμίσεις', 'cookie', 'settings', 
                'contact', 'about us', 'terms', 'advertising', 'login', 'registration',
                'pribatutasun', 'configuració', 'naslovnica', 'stisni',
                'personvern', 'prywatnosci', 'ustawienia', 'endre', 'zmień'
            ]
            if any(junk in name.lower() for junk in junk_keywords):
                continue

            # --- 3. EREDETI NYELVI SZŰRŐ (Language Lock) ---
            # Megtartva az eredeti logikát: domain.com/bg/..., domain.com/se/...
            path_segments = url.split('/')
            if len(path_segments) > 3:
                lang_segment = path_segments[3]
                if len(lang_segment) == 2 and lang_segment != 'en':
                    continue

            # --- 4. SCOPE SZŰRÉS ---
            # Csak az adott márkához tartozó linkeket engedjük át
            if brand_anchor not in url: 
                continue
            
            # --- 5. NAVIGÁCIÓS SZŰRÉS ---
            # Ne lépjen vissza a listákhoz, és zárjuk ki az idegen nyelvű könyvtárakat (teljes lista)
            excluded_patterns = [
                '-brand-', 'allbrands', 'en/brands', 
                '/bg/', '/ru/', '/de/', '/it/', '/fr/', '/es/', 
                '/tr/', '/ro/', '/fi/', '/se/', '/no/', '/pl/', '/gr/',
                '/hr/', '/cz/', '/sk/', '/ua/'
            ]
            if any(x in url for x in excluded_patterns): 
                continue
            
            # --- 6. ÖNHIVATKOZÁS SZŰRÉS ---
            if url.strip('/') == current_url.strip('/'): 
                continue

            # --- 7. SZINT MEGHATÁROZÁSA MINTÁZAT ALAPJÁN ---
            if '-generation-' in url:
                target_level = 'generation'
            elif re.search(r'-\d+$', url) and '-model-' not in url:
                target_level = 'engine'
            else:
                continue

            # --- 8. MENTÉS AZ ADATBÁZISBA ---
            await db.execute(text("""
                INSERT INTO vehicle.auto_data_crawler_queue (url, level, parent_id, name, status, category)
                VALUES (:url, :level, :p_id, :name, 'pending', 'car')
                ON CONFLICT (url) DO NOTHING
            """), {"url": url, "level": target_level, "p_id": p_id, "name": name})
            found_count += 1
            
        await db.commit()
    return found_count

async def process_target(context, t_id, t_url, t_name, t_level):
    """
    Gondolatmenet: Egy adott feladat (URL) teljes körű feldolgozása. 
    A volume mapping miatt a módosítás azonnal látszik a konténerben is.
    """
    page = await context.new_page()
    try:
        logger.info(f"🚀 Autós felderítés indítása [{t_level}]: {t_name}")
        await get_page_safe(page, t_url)
        
        # Linkek kinyerése és mentése
        found = await extract_scoped_links(page, t_id, t_url)
        
        async with AsyncSessionLocal() as db:
            new_status = 'completed' if found > 0 else 'completed_leaf'
            await db.execute(text("""
                UPDATE vehicle.auto_data_crawler_queue 
                SET status = :s, error_msg = NULL, updated_at = NOW() 
                WHERE id = :id
            """), {"s": new_status, "id": t_id})
            await db.commit()
            
            logger.info(f"✅ Befejezve: {t_name} -> {found} új link.")

    except Exception as e:
        logger.error(f"❌ Kritikus hiba feldolgozás közben ({t_name}): {e}")
        async with AsyncSessionLocal() as db:
            await db.execute(text("""
                UPDATE vehicle.auto_data_crawler_queue 
                SET status = 'error', error_msg = :msg, updated_at = NOW() 
                WHERE id = :id
            """), {"msg": str(e), "id": t_id})
            await db.commit()
    finally:
        await page.close()

async def main():
    """
    Gondolatmenet: A fő vezérlő hurok. 
    STRATÉGIA: Csak a 'car' kategóriájú feladatokat vesszük fel (category='car').
    """
    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("🤖 R2 Autós Felderítő Robot aktív. (Filter: category='car')")
        
        while True:
            async with AsyncSessionLocal() as db:
                # Csak 'car' kategóriájú, pending feladatok lekérése
                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 = 'pending' 
                          AND level IN ('model', 'generation')
                          AND category = 'car'
                        ORDER BY level ASC, id ASC 
                        LIMIT 1 FOR UPDATE SKIP LOCKED
                    ) RETURNING id, url, name, level
                """))
                target = res.fetchone()
                await db.commit()

            if not target:
                logger.info("🏁 Nincs több autós feladat (car). Alvás 60mp...")
                await asyncio.sleep(60)
                continue
            
            await process_target(context, target[0], target[1], target[2], target[3])

        await browser.close()

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