# /opt/docker/dev/service_finder/backend/app/workers/service/service_robot_1_scout_osm.py
import asyncio
import hashlib
import logging
import httpx
from urllib.parse import quote
from sqlalchemy import select, text
from app.database import AsyncSessionLocal
from app.models.marketplace.service import ServiceStaging # JAVÍTOTT IMPORT ÚTVONAL!
import re

# Logolás MB 2.0 szabvány szerint
logging.basicConfig(level=logging.INFO, format='%(asctime)s [%(levelname)s] %(name)s: %(message)s')
logger = logging.getLogger("Service-Robot-1-OSM")

class OSMScout:
    """
    Service Robot 1: OSM Scout
    Feladata: Új szerviz jelöltek porszívózása az OpenStreetMap-ről.
    """
    HUNGARY_BBOX = "45.7,16.1,48.6,22.9"
    OVERPASS_URL = "http://overpass-api.de/api/interpreter?data="

    @staticmethod
    def normalize_name(text_val: str) -> str:
        """ Alapvető tisztítás a pontosabb ujjlenyomathoz. """
        if not text_val: return ""
        # Kisbetű, ékezetek maradnak, de a felesleges szóközök és írásjelek mennek
        text_val = text_val.lower().strip()
        text_val = re.sub(r'\s+', ' ', text_val)
        return text_val

    @staticmethod
    def generate_fingerprint(name: str, city: str) -> str:
        """ Egyedi azonosító generálása a duplikációk elkerülésére. """
        n = OSMScout.normalize_name(name)
        c = OSMScout.normalize_name(city)
        raw = f"{n}|{c}"
        return hashlib.md5(raw.encode()).hexdigest()

    async def fetch_osm_data(self, query_part: str):
        """ Lekérdezés az Overpass API-tól. """
        query = f'[out:json][timeout:120];(node{query_part}({self.HUNGARY_BBOX});way{query_part}({self.HUNGARY_BBOX}););out center;'
        async with httpx.AsyncClient(timeout=150.0) as client:
            for attempt in range(3):
                try:
                    resp = await client.get(self.OVERPASS_URL + quote(query))
                    if resp.status_code == 200:
                        return resp.json().get('elements', [])
                    elif resp.status_code == 429: # Túl sok kérés az OSM felé
                        logger.warning(f"⚠️ OSM Rate Limit, várakozás...")
                        await asyncio.sleep(5 * (attempt + 1))
                    else:
                        logger.warning(f"⚠️ OSM API válasz: {resp.status_code}")
                except Exception as e:
                    if attempt == 2:
                        logger.error(f"❌ Overpass hiba végleges: {e}")
                    await asyncio.sleep(2)
        return []

    async def run_once(self):
        """ Egy teljes kör lefutása. """
        logger.info("🛰️ OSM Scout porszívózás indítása...")
        
        # Keressük az összes autóval kapcsolatos shop-ot és amenitit
        queries = ['["shop"~"car_repair|tyres|car_parts"]', '["amenity"~"car_wash|fuel"]']
        all_elements = []
        for q in queries:
            elements = await self.fetch_osm_data(q)
            all_elements.extend(elements)
            logger.info(f"🔍 Lekérdezés kész: {q} -> {len(elements)} találat")
            await asyncio.sleep(2) # Kíméljük az OSM szervereket
        
        async with AsyncSessionLocal() as db:
            added = 0
            skipped = 0
            
            for node in all_elements:
                tags = node.get('tags', {})
                name = tags.get('name', tags.get('operator'))
                if not name: continue

                city = tags.get('addr:city', 'Ismeretlen')
                postcode = tags.get('addr:postcode', '')
                f_print = self.generate_fingerprint(name, city)

                # Ellenőrizzük, hogy létezik-e már ez a szerviz a Staging táblában
                stmt = select(ServiceStaging.id).where(ServiceStaging.fingerprint == f_print)
                existing = (await db.execute(stmt)).scalar_one_or_none()
                
                if existing is None:
                    full_addr = f"{postcode} {city}, {tags.get('addr:street', '')} {tags.get('addr:housenumber', '')}".strip(" ,")
                    
                    # Bővített JSON a nyers adatokhoz, mert a modelled nem tartalmazza a source és trust oszlopokat
                    raw_payload = {
                        "osm_tags": tags,
                        "source": "osm_scout_v2",
                        "trust_score": 20
                    }
                    
                    new_entry = ServiceStaging(
                        name=name,
                        postal_code=postcode,
                        city=city,
                        full_address=full_addr,
                        fingerprint=f_print,
                        status="pending",
                        raw_data=raw_payload
                    )
                    db.add(new_entry)
                    added += 1
                else:
                    skipped += 1
            
            try:
                await db.commit()
                logger.info(f"✅ Kör véget ért. Új szervizek: {added}, Ismert (kihagyva): {skipped}")
            except Exception as e:
                await db.rollback()
                logger.error(f"❌ Adatbázis mentési hiba: {e}")

    async def loop(self):
        """ Folyamatos működés (hetente egyszer frissít). """
        logger.info("🤖 OSM Scout ONLINE")
        while True:
            try:
                await self.run_once()
            except Exception as e:
                logger.error(f"Kritikus hiba a főciklusban: {e}")
            
            logger.info("😴 Robot elalvás (7 nap)... OSM adatok ritkán változnak.")
            await asyncio.sleep(86400 * 7) # 7 naponta egyszer nézzük át (felesleges naponta)

if __name__ == "__main__":
    scout = OSMScout()
    asyncio.run(scout.loop())