import asyncio, httpx, logging, os, re, sys, json
from sqlalchemy import text
from sqlalchemy.dialects.postgresql import insert
from app.database import AsyncSessionLocal
from app.models.vehicle_definitions import VehicleModelDefinition

logging.basicConfig(level=logging.INFO, format='%(asctime)s [%(levelname)s] Robot-1-Hunter: %(message)s', stream=sys.stdout)
logger = logging.getLogger("Robot-1")

class CatalogHunter:
    RDW_MAIN = "https://opendata.rdw.nl/resource/m9d7-ebf2.json"
    RDW_FUEL = "https://opendata.rdw.nl/resource/8ys7-d773.json"
    RDW_ENGINE = "https://opendata.rdw.nl/resource/jh96-v4pq.json"
    RDW_TOKEN = os.getenv("RDW_APP_TOKEN")
    HEADERS = {"X-App-Token": RDW_TOKEN} if RDW_TOKEN else {}
    BATCH_SIZE = 50

    @classmethod
    def normalize(cls, text_val: str) -> str:
        return re.sub(r'[^a-zA-Z0-9]', '', text_val).lower() if text_val else "UNKNOWN"

    @classmethod
    def parse_int(cls, value) -> int:
        try: return int(float(value)) if value and str(value).strip() else 0
        except: return 0

    @classmethod
    def parse_float(cls, value) -> float:
        try: return float(value) if value and str(value).strip() else 0.0
        except: return 0.0

    @classmethod
    async def fetch_tech_details(cls, client, plate):
        res = {"power_kw": 0, "engine_code": None, "euro_class": None, "fuel_desc": "Unknown", "co2": 0, "consumption": 0.0}
        try:
            f_resp = await client.get(f"{cls.RDW_FUEL}?kenteken={plate}", headers=cls.HEADERS)
            if f_resp.status_code == 200 and f_resp.json():
                f = f_resp.json()[0]
                p1, p2 = cls.parse_int(f.get("netto_maximum_vermogen")), cls.parse_int(f.get("nominaal_continu_maximum_vermogen"))
                res.update({
                    "power_kw": max(p1, p2),
                    "fuel_desc": f.get("brandstof_omschrijving") or "Unknown",
                    "euro_class": f.get("euro_klasse") or f.get("uitlaatemissieniveau"),
                    "co2": cls.parse_int(f.get("co2_uitstoot_gecombineerd")),
                    "consumption": cls.parse_float(f.get("brandstofverbruik_gecombineerd"))
                })
            e_resp = await client.get(f"{cls.RDW_ENGINE}?kenteken={plate}", headers=cls.HEADERS)
            if e_resp.status_code == 200 and e_resp.json():
                res["engine_code"] = e_resp.json()[0].get("motorcode")
        except Exception: pass
        return res

    @classmethod
    async def process_task(cls, db, task):
        clean_make, clean_model = task.make.strip().upper(), task.model.strip().upper()
        logger.info(f"🎯 ADATGYŰJTÉS INDUL: {clean_make} {clean_model}")

        async with httpx.AsyncClient(timeout=30.0) as client:
            offset = 0
            while True:
                params = f"merk={clean_make}" + (f"&handelsbenaming={clean_model}" if clean_model != 'ALL_VARIANTS' else "") + f"&$limit={cls.BATCH_SIZE}&$offset={offset}&$order=kenteken DESC"
                try:
                    r = await client.get(f"{cls.RDW_MAIN}?{params}", headers=cls.HEADERS)
                    batch = r.json() if r.status_code == 200 else []
                except Exception: break
                if not batch: break 

                for item in batch:
                    plate = item.get("kenteken", "UNKNOWN")
                    try:
                        async with db.begin_nested():
                            tech = await cls.fetch_tech_details(client, plate)
                            actual_model = (item.get("handelsbenaming") or clean_model).upper()
                            norm_name = cls.normalize(actual_model.replace(clean_make, "").strip() or actual_model)
                            
                            datum = str(item.get("datum_eerste_toelating", ""))
                            year_from = cls.parse_int(datum[:4]) if len(datum) >= 4 else 0
                            
                            engine_ccm, power_kw, fuel_type = cls.parse_int(item.get("cilinderinhoud")), tech["power_kw"], tech["fuel_desc"]

                            # FAST-TRACK LOGIKA: Ha van KW és CCM, egyből ARANY!
                            is_gold = (power_kw > 0 and engine_ccm > 0) or (power_kw > 0 and "elektri" in fuel_type.lower())
                            final_status = "gold_enriched" if is_gold else "unverified"

                            stmt = insert(VehicleModelDefinition).values(
                                market='EU', make=clean_make, marketing_name=actual_model, normalized_name=norm_name,
                                variant_code=item.get("variant", "UNKNOWN"), version_code=item.get("uitvoering", "UNKNOWN"),
                                technical_code=plate, type_approval_number=item.get("typegoedkeuringsnummer"),
                                seats=cls.parse_int(item.get("aantal_zitplaatsen")), doors=cls.parse_int(item.get("aantal_deuren")),
                                width=cls.parse_int(item.get("breedte")), wheelbase=cls.parse_int(item.get("wielbasis")),
                                list_price=cls.parse_int(item.get("catalogusprijs")), max_speed=cls.parse_int(item.get("maximale_constructiesnelheid")),
                                curb_weight=cls.parse_int(item.get("massa_ledig_voertuig")), max_weight=cls.parse_int(item.get("technische_max_massa_voertuig")),
                                fuel_consumption_combined=tech["consumption"], co2_emissions_combined=tech["co2"],
                                vehicle_class=task.vehicle_class, body_type=item.get("inrichting"), fuel_type=fuel_type, 
                                engine_capacity=engine_ccm, power_kw=power_kw, cylinders=cls.parse_int(item.get("aantal_cilinders")),
                                engine_code=tech["engine_code"], euro_classification=tech["euro_class"], year_from=year_from,
                                priority_score=task.priority_score, status=final_status, source="MEGA-HUNTER-v2.2.0-FAST",
                                raw_search_context='', research_metadata={}, specifications={"fast_track": True} if is_gold else {}, marketing_name_aliases=[]
                            ).on_conflict_do_nothing(
                                index_elements=['make', 'normalized_name', 'variant_code', 'version_code', 'fuel_type', 'market', 'year_from']
                            ).returning(VehicleModelDefinition.id)
                            
                            res = await db.execute(stmt)
                            vmd_id = res.scalar()

                            # Automatikus Publikálás (Ha Arany)
                            if is_gold and vmd_id:
                                cat_stmt = text("""
                                    INSERT INTO vehicle.vehicle_catalog (master_definition_id, make, model, power_kw, engine_capacity, fuel_type, factory_data)
                                    VALUES (:m_id, :make, :model, :kw, :ccm, :fuel, :factory)
                                    ON CONFLICT ON CONSTRAINT uix_vehicle_catalog_full DO NOTHING;
                                """)
                                await db.execute(cat_stmt, {"m_id": vmd_id, "make": clean_make, "model": actual_model[:50], "kw": power_kw, "ccm": engine_ccm, "fuel": fuel_type, "factory": '{"source": "RDW Fast-Track"}'})
                                logger.info(f"✨ FAST-TRACK ARANY: {clean_make} {actual_model}")

                    except Exception as e: logger.warning(f"⚠️ Sor hiba ({plate}): {e}")
                
                await db.commit()
                offset += len(batch)
                if offset >= 500: break 
                await asyncio.sleep(0.5)
                
            await db.execute(text("UPDATE vehicle.catalog_discovery SET status = 'processed' WHERE id = :id"), {"id": task.id})
            await db.commit()

    @classmethod
    async def run(cls):
        logger.info("🤖 Mega-Hunter v2.2.0 (Fast-Track) ONLINE")
        while True:
            try:
                async with AsyncSessionLocal() as db:
                    res = await db.execute(text("UPDATE vehicle.catalog_discovery SET status = 'processing' WHERE id = (SELECT id FROM vehicle.catalog_discovery WHERE status = 'pending' ORDER BY priority_score DESC FOR UPDATE SKIP LOCKED LIMIT 1) RETURNING id, make, model, vehicle_class, priority_score;"))
                    task = res.fetchone()
                    await db.commit()
                    if task: await cls.process_task(db, task)
                    else: await asyncio.sleep(30)
            except Exception: await asyncio.sleep(10)

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