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 ---
logging.basicConfig(
    level=logging.INFO, 
    format='%(asctime)s [R2-BIKE-DEPTH] %(message)s',
    handlers=[logging.StreamHandler()]
)
logger = logging.getLogger("R2")

async def get_page_safe(page, url):
    """
    Bot védelem kijátszása valós viselkedéssel és Cloudflare ellenőrzéssel.
    """
    delay = random.uniform(4, 7)
    await asyncio.sleep(delay)
    
    try:
        await page.goto(url, wait_until="domcontentloaded", timeout=60000)
        title = await page.title()
        if "Just a moment" in title or "Cloudflare" in title:
            logger.error(f"Bot védelem észlelve: {url}")
            raise Exception("Bot védelem (CF) megállította a robotot.")
        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):
    """
    MÉLYSÉGI FELDERÍTÉS: Generation -> Engine variációk kinyerése.
    Scope-Lock: Csak az adott márkán belüli linkeket követi.
    """
    # Kinyerjük a márka nevét az URL-ből a scope-lockhoz
    path_segments = current_url.strip('/').split('/')
    if len(path_segments) < 5: 
        return 0
    brand_anchor = path_segments[4] 
    
    hrefs = await page.eval_on_selector_all(
        "a[href*='/moto/']", 
        "nodes => nodes.map(n => ({ 'name': n.innerText.trim(), 'url': n.href }))"
    )
    
    junk = ['privacy', 'cookie', 'settings', 'contact', 'terms', 'advertising', 'login', 'about', 'copyright']
    found_count = 0

    async with AsyncSessionLocal() as db:
        for link in hrefs:
            # TISZTÍTÁS: Levágjuk a horgonyt, hogy az adatlapot lássuk
            clean_url = link['url'].split('#')[0].split('?')[0].rstrip('/')
            name = link['name'].replace('\n', ' ').strip()
            
            # Alap szűrések
            if not name or len(name) < 2: continue
            if re.search(r'[^\x00-\x7F]+', name): continue 
            if any(k in name.lower() for k in junk): continue

            # SCOPE LOCK: Csak az adott márkához tartozó linkeket engedjük át
            if brand_anchor not in clean_url.lower(): 
                continue
            
            # Navigációs szűrés
            if any(x in clean_url for x in ['-brand-', 'allbrands', 'en/brands', '/moto/']): 
                if clean_url.count('/') < 5: continue

            # Önhivatkozás elkerülése
            if clean_url == current_url.rstrip('/'): 
                continue

            # Szintek meghatározása
            if clean_url.endswith(".html"):
                target_level = 'engine'
            elif clean_url.count('/') >= 6:
                target_level = 'generation'
            else:
                continue

            # 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', 'bike')
                ON CONFLICT (url) DO NOTHING
            """), {"url": clean_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):
    """
    Egy adott feladat (URL) teljes körű feldolgozása.
    """
    page = await context.new_page()
    try:
        logger.info(f"🚀 Mélységi fúrás [{t_level}]: {t_name}")
        await get_page_safe(page, t_url)
        
        # Variációk és generációk kinyeré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 variáció rögzítve.")

    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():
    """
    Fő hurok mélységi stratégiával (level ASC).
    """
    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) Chrome/122.0.0.0",
            viewport={'width': 1920, 'height': 1080}
        )
        
        logger.info("🤖 R2 Motoros Mélységi Felderítő aktív.")
        
        while True:
            async with AsyncSessionLocal() as db:
                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 = 'bike'
                          AND url LIKE '%autoevolution.com%'
                        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("🏁 Minden variáció felderítve. 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("🛑 Leállítás.")