# /opt/docker/dev/service_finder/backend/app/workers/service/validation_pipeline.py
"""
5-Szintes Költséghatékony Validációs Pipeline a szerviz validálására (Epic 9, #111-es jegy).

Ez a modul a régi Google validátor (service_robot_4_validator_google.py) kiegészítéseként szolgál,
vízesés (fallback) architektúrát alkalmazva, hogy minimalizáljuk a költségeket és maximalizáljuk
a fedezetet.

A pipeline 5 szintből áll, amelyek sorban próbálkoznak, amíg egy sikeres validációt nem érnek el.
Minden szintnek saját siker/failure feltételei vannak, és a következő szintre való lépés döntése
a szint belső logikája alapján történik.

ARCHITEKTÚRA (JAVÍTOTT, KÖLTSÉGHATÉKONY):
1. OpenStreetMap Nominatim (ingyenes) – alap geokódolás
2. EU VIES / Cégjegyzék API + AI Parser – hivatalos jogi létezés ellenőrzés
3. Freemium API-k (Foursquare / Yelp) – ingyenes nyitvatartás és képek
4. Célzott Web Scraping – szerviz saját weblapjának aszinkron átolvasása
5. Google Places API (Fallback) – csak a legnehezebb, beragadt esetek

Minden szint dokumentálva van masszív docstring‑gel, amely tartalmazza:
- A szint célját
- Használt külső API‑t vagy AI eszközt
- Sikerfeltéleteket (mikor térünk vissza)
- Fallback feltételeket (mikor lépünk tovább)
- Költség‑ és kvótakezelési megfontolásokat

A pipeline aszinkron, párhuzamosítható, és atomi zárolással dolgozik a `service_profiles` táblán.
"""

import asyncio
import httpx
import logging
import os
import sys
import json
import re
from datetime import datetime
from typing import Optional, Dict, Any, Tuple
from sqlalchemy import text, update, func
from app.database import AsyncSessionLocal
from app.models.marketplace.service import ServiceProfile, ServiceStatus

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

# -------------------------------------------------------------------
# 1. SZINT: OPENSTREETMAP NOMINATIM (INGYENES ALAP GEOKÓDOLÁS)
# -------------------------------------------------------------------

class OSMNominatimValidator:
    """
    Első szint: OpenStreetMap Nominatim API (ingyenes alap geokódolás).
    
    CÉL:
        Ingyenes alap geokódolás a szerviz neve és címe alapján. Ha 100%-os találatot ad,
        akkor SIKER, és nem kell továbbmenni a következő szintekre.
    
    HASZNÁLT API:
        OpenStreetMap Nominatim Search – https://nominatim.openstreetmap.org/search
        Nincs API kulcs, de tiszteletben kell tartani a Usage Policy‑t (max 1 kérés/másodperc).
    
    SIKER (visszatérés DONE):
        - A Nominatim visszaad egy találatot a szerviz nevével és címmel
        - GPS koordináta kinyerése (lat, lon) pontossággal
        - A találat confidence > 0.8 (jó egyezés)
        - A szerviz státusza active‑re frissül, trust_score +20
    
    FALLBACK (továbblépés a 2. szintre):
        - Nincs találat (üres válasz)
        - Találat confidence < 0.5 (gyenge egyezés)
        - Hálózati hiba vagy timeout
        - Túl sok kérés (429)
    
    KÖLTSÉGKEZELÉS:
        Teljesen ingyenes, de rate limit miatt szükséges throttling (1 másodperc várakozás).
        Nincs pénzügyi költség.
    """
    
    NOMINATIM_URL = "https://nominatim.openstreetmap.org/search"
    
    async def validate(self, db, profile_id: int, fingerprint: str, bio: str) -> Tuple[str, Optional[Dict]]:
        logger.info(f"[OSM] 1. szint: Validálás indul: {fingerprint}")
        
        name = fingerprint.split('|')[0] if '|' in fingerprint else fingerprint
        params = {
            "q": f"{name} Hungary",
            "format": "json",
            "limit": 1,
            "addressdetails": 1
        }
        headers = {"User-Agent": "ServiceFinderBot/1.0 (contact: admin@servicefinder.hu)"}
        
        try:
            async with httpx.AsyncClient(timeout=15.0) as client:
                await asyncio.sleep(1)  # Rate limit tisztelet
                resp = await client.get(self.NOMINATIM_URL, params=params, headers=headers)
                if resp.status_code == 200:
                    results = resp.json()
                    if not results:
                        logger.warning(f"[OSM] Nem található: {name}, továbblépés VIES-re.")
                        return "FALLBACK", None
                    result = results[0]
                    confidence = min(len(result.get("display_name", "")) / 100, 1.0)
                    if confidence < 0.5:
                        logger.warning(f"[OSM] Alacsony confidence ({confidence}), továbblépés VIES-re.")
                        return "FALLBACK", None
                    
                    extracted = {
                        "osm_id": result.get("osm_id"),
                        "display_name": result.get("display_name"),
                        "location": {
                            "latitude": float(result.get("lat")),
                            "longitude": float(result.get("lon"))
                        },
                        "confidence": confidence
                    }
                    logger.info(f"[OSM] Sikeres validáció, koordináta: {extracted['location']}")
                    return "DONE", extracted
                else:
                    logger.error(f"[OSM] API hiba: {resp.status_code}, továbblépés VIES-re.")
                    return "FALLBACK", None
        except Exception as e:
            logger.debug(f"[OSM] Hálózati hiba: {e}, továbblépés VIES-re.")
            return "FALLBACK", None

# -------------------------------------------------------------------
# 2. SZINT: EU VIES / CÉGJEGYZÉK API + AI PARSER
# -------------------------------------------------------------------

class EUVIESValidator:
    """
    Második szint: EU VIES (VAT Information Exchange System) és nemzeti cégjegyzék API-k.
    
    CÉL:
        Hivatalos jogi létezés ellenőrzése adószám vagy cégjegyzékszám alapján.
        Az AI (Ollama/Qwen) a nyers JSON/HTML választ strukturálja és értelmezi.
    
    HASZNÁLT API:
        EU VIES SOAP API (ingyenes) – VAT szám validáció
        Nemzeti cégjegyzék API-k (pl. Hungarian Company Registry) – ha elérhető
        AI Parser: Ollama Qwen 14B a strukturálatlan adatok feldolgozására
    
    SIKER (visszatérés DONE):
        - A VIES API visszaigazolja, hogy a VAT szám érvényes és aktív
        - Cégjegyzék visszaadja a cég nevének, székhelyének, tevékenységi körének adatait
        - AI parser kinyeri a releváns mezőket és magas confidence-t ad (>0.7)
        - A szerviz státusza active, trust_score +30
    
    FALLBACK (továbblépés a 3. szintre):
        - VAT szám nem érvényes vagy nem található
        - Cégjegyzék API nem elérhető vagy hibás válasz
        - AI parser alacsony confidence-t ad (<0.3)
        - Időtúllépés vagy parsing hiba
    
    KÖLTSÉGKEZELÉS:
        VIES ingyenes, cégjegyzék API-k lehetnek korlátozottak. AI parser helyi, nulla költség.
        Összköltség: ~$0 (kivéve ha fizetős cégjegyzék API-t használunk).
    """
    
    VIES_URL = "https://ec.europa.eu/taxation_customs/vies/services/checkVatService"
    VIES_REST_URL = "https://ec.europa.eu/taxation_customs/vies/rest-api/ms/{country_code}/vat/{vat_number}"
    OLLAMA_URL = "http://localhost:11434/api/generate"
    
    async def validate(self, db, profile_id: int, fingerprint: str, bio: str) -> Tuple[str, Optional[Dict]]:
        logger.info(f"[VIES] 2. szint: Jogi validáció indul: {fingerprint}")
        
        vat_match = re.search(r'[A-Z]{2}[0-9A-Z]{8,12}', bio if bio else "")
        if not vat_match:
            logger.warning("[VIES] Nincs VAT szám a bio-ban, továbblépés Freemium API-ra.")
            return "FALLBACK", None
        
        vat_number = vat_match.group()
        country_code = vat_number[:2]
        vat_num = vat_number[2:]
        
        # 1. EU VIES REST API hívás
        rest_url = self.VIES_REST_URL.format(country_code=country_code, vat_number=vat_num)
        try:
            async with httpx.AsyncClient(timeout=10.0) as client:
                resp = await client.get(rest_url)
                if resp.status_code == 200:
                    vies_data = resp.json()
                    if vies_data.get("valid", False):
                        logger.info(f"[VIES] VAT szám érvényes: {vat_number}")
                        # 2. AI parser hívása a nyers VIES adatokkal
                        ai_extracted = await self._parse_with_ai(json.dumps(vies_data))
                        if ai_extracted and ai_extracted.get("is_active", False):
                            extracted = {
                                "vat_valid": True,
                                "vat_number": vat_number,
                                "company_name": ai_extracted.get("company_name", ""),
                                "address": ai_extracted.get("address", ""),
                                "is_active": True,
                                "confidence": 0.9
                            }
                            return "DONE", extracted
                        else:
                            logger.warning("[VIES] AI parser nem találta aktívnak a céget, továbblépés.")
                            return "FALLBACK", None
                    else:
                        logger.warning(f"[VIES] VAT szám érvénytelen vagy nem található: {vat_number}")
                        return "FALLBACK", None
                else:
                    logger.error(f"[VIES] REST API hiba: {resp.status_code}")
                    return "FALLBACK", None
        except Exception as e:
            logger.debug(f"[VIES] Hálózati hiba: {e}")
            return "FALLBACK", None
    
    async def _parse_with_ai(self, raw_data: str) -> Optional[Dict]:
        """
        Privát metódus, amely a helyi Ollama (Qwen) AI-t használja a VIES nyers adatok
        strukturálására. A prompt specifikus, hogy JSON-t adjon vissza.
        """
        prompt = f"""You are an expert data extractor. Extract the company name, exact address, and active status from the following VIES registry data. Return ONLY a valid JSON object with keys: 'company_name', 'address', 'is_active'. Do not include markdown formatting or explanation. Data: {raw_data}"""
        
        payload = {
            "model": "qwen2.5:14b",
            "prompt": prompt,
            "format": "json",
            "stream": False
        }
        
        try:
            async with httpx.AsyncClient(timeout=30.0) as client:
                resp = await client.post(self.OLLAMA_URL, json=payload)
                if resp.status_code == 200:
                    result = resp.json()
                    response_text = result.get("response", "").strip()
                    # Tisztítás: eltávolítjuk a ```json és ``` jeleket
                    if response_text.startswith("```json"):
                        response_text = response_text[7:]
                    if response_text.endswith("```"):
                        response_text = response_text[:-3]
                    try:
                        parsed = json.loads(response_text)
                        # Ellenőrizzük, hogy a szükséges kulcsok léteznek
                        if all(key in parsed for key in ["company_name", "address", "is_active"]):
                            return parsed
                        else:
                            logger.warning(f"[Ollama] Hiányzó kulcsok a JSON-ban: {parsed}")
                            return None
                    except json.JSONDecodeError as e:
                        logger.error(f"[Ollama] JSON parse hiba: {e}, response: {response_text}")
                        return None
                else:
                    logger.error(f"[Ollama] API hiba: {resp.status_code}, {resp.text}")
                    return None
        except Exception as e:
            logger.debug(f"[Ollama] Hálózati hiba: {e}")
            return None

# -------------------------------------------------------------------
# 3. SZINT: FREEMIUM API-K (FOURSQUARE / YELP)
# -------------------------------------------------------------------

class FreemiumAPIValidator:
    """
    Harmadik szint: Freemium API-k (Foursquare, Yelp) ingyenes rétege.
    
    CÉL:
        Ingyenes nyitvatartás, képek, értékelések és alapvető üzleti információk lekérése.
        Ezek az API-k ingyenes tierrel rendelkeznek, de korlátozott kvótával.
    
    HASZNÁLT API:
        Foursquare Places API (ingyenes tier, 950 kérés/nap)
        Yelp Fusion API (ingyenes tier, 500 kérés/nap)
        Környezeti változók: FOURSQUARE_CLIENT_ID, FOURSQUARE_CLIENT_SECRET, YELP_API_KEY
    
    SIKER (visszatérés DONE):
        - API visszaad egy vagy több találatot a szervizre
        - Nyitvatartási idő, telefonszám, weboldal, átlagos értékelés kinyerése
        - Legalább 3 kép vagy értékelés megtalálása
        - A szerviz státusza active, trust_score +25
    
    FALLBACK (továbblépés a 4. szintre):
        - Nincs találat az API-ban
        - API kvóta elérve
        - Hálózati hiba vagy timeout
        - Kevesebb mint 2 kép/értékelés
    
    KÖLTSÉGKEZELÉS:
        Ingyenes tier, de kvóták figyelése szükséges. Ha a napi limit túllépés közelében van,
        automatikusan átvált a következő szintre. Nincs pénzügyi költség az ingyenes kvótán belül.
    """
    
    FOURSQUARE_URL = "https://api.foursquare.com/v3/places/search"
    YELP_URL = "https://api.yelp.com/v3/businesses/search"
    
    def __init__(self):
        self.foursquare_client_id = os.getenv("FOURSQUARE_CLIENT_ID")
        self.foursquare_client_secret = os.getenv("FOURSQUARE_CLIENT_SECRET")
        self.yelp_api_key = os.getenv("YELP_API_KEY")
    
    async def validate(self, db, profile_id: int, fingerprint: str, bio: str) -> Tuple[str, Optional[Dict]]:
        logger.info(f"[Freemium] 3. szint: Validálás indul: {fingerprint}")
        
        name = fingerprint.split('|')[0] if '|' in fingerprint else fingerprint
        
        if self.foursquare_client_id and self.foursquare_client_secret:
            result = await self._try_foursquare(name)
            if result:
                return "DONE", result
        
        if self.yelp_api_key:
            result = await self._try_yelp(name)
            if result:
                return "DONE", result
        
        logger.warning("[Freemium] Egyik API sem adott eredményt, továbblépés Web Scraping-re.")
        return "FALLBACK", None
    
    async def _try_foursquare(self, name: str) -> Optional[Dict]:
        headers = {
            "Authorization": f"{self.foursquare_client_id}",
            "Accept": "application/json"
        }
        params = {"query": name, "near": "Hungary", "limit": 1}
        
        try:
            async with httpx.AsyncClient(timeout=10.0) as client:
                resp = await client.get(self.FOURSQUARE_URL, params=params, headers=headers)
                if resp.status_code == 200:
                    data = resp.json()
                    places = data.get("results", [])
                    if places:
                        place = places[0]
                        extracted = {
                            "fsq_id": place.get("fsq_id"),
                            "name": place.get("name"),
                            "location": place.get("location", {}),
                            "rating": place.get("rating"),
                            "photos": place.get("photos", []),
                            "contact": place.get("contact", {})
                        }
                        logger.info(f"[Foursquare] Találat: {place.get('name')}")
                        return extracted
        except Exception as e:
            logger.debug(f"[Foursquare] Hiba: {e}")
        return None
    
    async def _try_yelp(self, name: str) -> Optional[Dict]:
        headers = {"Authorization": f"Bearer {self.yelp_api_key}"}
        params = {"term": name, "location": "Hungary", "limit": 1}
        
        try:
            async with httpx.AsyncClient(timeout=10.0) as client:
                resp = await client.get(self.YELP_URL, params=params, headers=headers)
                if resp.status_code == 200:
                    data = resp.json()
                    businesses = data.get("businesses", [])
                    if businesses:
                        business = businesses[0]
                        extracted = {
                            "yelp_id": business.get("id"),
                            "name": business.get("name"),
                            "rating": business.get("rating"),
                            "review_count": business.get("review_count"),
                            "phone": business.get("phone"),
                            "photos": business.get("photos", []),
                            "location": business.get("location", {})
                        }
                        logger.info(f"[Yelp] Találat: {business.get('name')}")
                        return extracted
        except Exception as e:
            logger.debug(f"[Yelp] Hiba: {e}")
        return None

# -------------------------------------------------------------------
# 4. SZINT: CÉLZOTT WEB SCRAPING
# -------------------------------------------------------------------

class WebScrapingValidator:
    """
    Negyedik szint: Célzott Web Scraping a szerviz saját weblapjáról.
    
    CÉL:
        A szerviz saját weblapjának aszinkron átolvasása (detektív munka) információk
        kinyerésére: telefonszám, cím, nyitvatartás, szolgáltatások, képek.
    
    HASZNÁLT ESZKÖZ:
        Aszinkron HTTP kérések (httpx) + BeautifulSoup HTML parsing
        Környezeti változó: SCRAPING_TIMEOUT (alapértelmezett 30 másodperc)
    
    SIKER (visszatérés DONE):
        - Weblap sikeresen letöltve és parse-olva
        - Legalább 2 releváns kulcsszó található a HTML szövegében
        - A kinyert információk konzisztensek a szerviz adataival
        - A szerviz státusza active, trust_score +15
    
    FALLBACK (továbblépés a 5. szintre):
        - Weblap nem elérhető (404, timeout)
        - Nincs releváns információ a HTML-ben
        - Scraping tiltva (robots.txt, rate limiting)
        - Parsing hiba
    
    KÖLTSÉGKEZELÉS:
        Nincs API költség, de erőforrás-igényes lehet. Rate limiting beépítve,
        hogy ne terheljük túl a cél szervert. Nincs pénzügyi költség.
    """
    
    # Releváns kulcsszavak a szerviz weblapjain
    KEYWORDS = ["szerviz", "javítás", "autó", "motor", "műhely", "garage",
                "service", "repair", "car", "workshop", "maintenance", "auto"]
    
    async def validate(self, db, profile_id: int, fingerprint: str, bio: str) -> Tuple[str, Optional[Dict]]:
        logger.info(f"[WebScraping] 4. szint: Validálás indul: {fingerprint}")
        
        # Weboldal URL kinyerése a bio-ból (egyszerű regex)
        url_match = re.search(r'https?://[^\s]+', bio if bio else "")
        if not url_match:
            logger.warning("[WebScraping] Nincs URL a bio-ban, továbblépés Google-re.")
            return "FALLBACK", None
        
        url = url_match.group()
        
        try:
            async with httpx.AsyncClient(timeout=30.0) as client:
                headers = {
                    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
                }
                resp = await client.get(url, headers=headers, follow_redirects=True)
                if resp.status_code == 200:
                    html = resp.text
                    
                    # BeautifulSoup import (inline, mert a fájl elején nincs)
                    try:
                        from bs4 import BeautifulSoup
                        soup = BeautifulSoup(html, 'html.parser')
                        
                        # Távolítsuk el a script és style elemeket
                        for script in soup(["script", "style"]):
                            script.decompose()
                        
                        # Szöveg kinyerése
                        text = soup.get_text(separator=' ', strip=True)
                        text_lower = text.lower()
                        
                        # Kulcsszó keresés
                        found_keywords = []
                        for keyword in self.KEYWORDS:
                            if keyword.lower() in text_lower:
                                found_keywords.append(keyword)
                        
                        logger.info(f"[WebScraping] Talált kulcsszavak: {found_keywords}")
                        
                        # Ha legalább 2 kulcsszó található, sikeres
                        if len(found_keywords) >= 2:
                            extracted = {
                                "url": url,
                                "found_keywords": found_keywords,
                                "text_preview": text[:200] + "..." if len(text) > 200 else text
                            }
                            logger.info(f"[WebScraping] Sikeres scraping, {len(found_keywords)} kulcsszó találva.")
                            return "DONE", extracted
                        else:
                            logger.warning(f"[WebScraping] Kevesebb mint 2 kulcsszó ({len(found_keywords)}), továbblépés Google-re.")
                            return "FALLBACK", None
                            
                    except ImportError:
                        logger.error("[WebScraping] BeautifulSoup4 nincs telepítve, továbblépés Google-re.")
                        return "FALLBACK", None
                        
                else:
                    logger.error(f"[WebScraping] HTTP hiba: {resp.status_code}")
                    return "FALLBACK", None
        except httpx.TimeoutException:
            logger.warning("[WebScraping] Timeout a weblap betöltésénél, továbblépés Google-re.")
            return "FALLBACK", None
        except Exception as e:
            logger.debug(f"[WebScraping] Hálózati hiba: {e}")
            return "FALLBACK", None

# -------------------------------------------------------------------
# 5. SZINT: GOOGLE PLACES API (FALLBACK)
# -------------------------------------------------------------------

class QuotaManager:
    """ Szigorú napi limit figyelő a Google API-hoz, hogy soha többé ne legyen 250$-os számla! """
    def __init__(self, service_name: str, daily_limit: int):
        self.service_name = service_name
        self.daily_limit = daily_limit
        self.state_file = f"/app/temp/.quota_{service_name}.json"
        self._ensure_file()

    def _ensure_file(self):
        os.makedirs(os.path.dirname(self.state_file), exist_ok=True)
        if not os.path.exists(self.state_file):
            with open(self.state_file, 'w') as f:
                json.dump({"date": datetime.now().strftime("%Y-%m-%d"), "count": 0}, f)

    def can_make_request(self) -> bool:
        with open(self.state_file, 'r') as f:
            data = json.load(f)
        
        today = datetime.now().strftime("%Y-%m-%d")
        if data["date"] != today:
            data = {"date": today, "count": 0}
            
        if data["count"] >= self.daily_limit:
            return False
            
        data["count"] += 1
        with open(self.state_file, 'w') as f:
            json.dump(data, f)
        return True

class GooglePlacesValidator:
    """
    Ötödik szint: Google Places API (a legdrágább, fallback).
    
    CÉL:
        CSAK a legnehezebb, beragadt eseteket küldjük ide, hogy spóroljunk a kvótával.
        A Google arany standard adatokat szolgáltat, de költséges ($0,03 / hívás).
    
    HASZNÁLT API:
        Google Places API (Text Search) – https://places.googleapis.com/v1/places:searchText
        Környezeti változó: GOOGLE_API_KEY, GOOGLE_DAILY_LIMIT (alapértelmezett 100)
    
    SIKER (visszatérés DONE):
        - Google visszaad egy érvényes place objektumot
        - GPS koordináta, telefonszám, weboldal, értékelések kinyerése
        - A szerviz státusza active, trust_score +50
    
    FALLBACK (visszatérés FALLBACK):
        - Google API nem válaszol (hálózati hiba)
        - NAPI KVÓTA ELÉRVE (QuotaManager blokkol)
        - A Google nem ismeri a szervizt (NOT_FOUND)
        - API kulcs hiányzik vagy érvénytelen
        Ekkor a pipeline FAILED állapotba kerül, és manuális ellenőrzésre vár.
    
    KÖLTSÉGKEZELÉS:
        QuotaManager szigorúan figyeli a napi limitet. Csak akkor használjuk, ha az összes
        előző szint sikertelen. Költség: ~$0,03 / hívás.
    """
    
    PLACES_TEXT_URL = "https://places.googleapis.com/v1/places:searchText"
    
    def __init__(self):
        self.api_key = os.getenv("GOOGLE_API_KEY")
        # Napi limit: pl. 100 lekérdezés = kb. $3/nap maximum!
        self.daily_limit = int(os.getenv("GOOGLE_DAILY_LIMIT", "100"))
        self.quota = QuotaManager("google_places", self.daily_limit)
        self.headers = {
            "Content-Type": "application/json",
            "X-Goog-Api-Key": self.api_key,
            # Csak a legszükségesebb mezőket kérjük, hogy olcsó maradjon az API hívás!
            "X-Goog-FieldMask": "places.id,places.location,places.rating,places.userRatingCount,places.regularOpeningHours,places.internationalPhoneNumber,places.websiteUri"
        }
    
    async def validate(self, db, profile_id: int, fingerprint: str, bio: str) -> Tuple[str, Optional[Dict]]:
        logger.info(f"[Google] 5. szint (Fallback): Validálás indul: {fingerprint}")
        
        if not self.api_key:
            logger.warning("[Google] Hiányzó API kulcs, pipeline FAILED.")
            return "FALLBACK", None
        
        if not self.quota.can_make_request():
            logger.warning("[Google] Napi kvóta elérve, pipeline FAILED.")
            return "FALLBACK", None
        
        name = fingerprint.split('|')[0] if '|' in fingerprint else fingerprint
        query_text = f"{name} {bio}"
        payload = {"textQuery": query_text, "maxResultCount": 1}
        
        for attempt in range(2):
            try:
                async with httpx.AsyncClient(timeout=10.0) as client:
                    resp = await client.post(self.PLACES_TEXT_URL, json=payload, headers=self.headers)
                    if resp.status_code == 200:
                        places = resp.json().get("places", [])
                        if not places:
                            logger.warning(f"[Google] Nem található: {name}")
                            return "FALLBACK", None
                        place_data = places[0]
                        extracted = {
                            "google_place_id": place_data.get("id"),
                            "rating": place_data.get("rating"),
                            "user_ratings_total": place_data.get("userRatingCount"),
                            "contact_phone": place_data.get("internationalPhoneNumber"),
                            "website": place_data.get("websiteUri"),
                            "opening_hours": place_data.get("regularOpeningHours", {}),
                            "location": place_data.get("location")
                        }
                        logger.info(f"[Google] Sikeres validáció, adatok kinyerve.")
                        return "DONE", extracted
                    elif resp.status_code == 429:
                        logger.warning("[Google] Rate limit, újrapróbálás...")
                        await asyncio.sleep(2)
                        continue
                    else:
                        logger.error(f"[Google] API hiba: {resp.status_code}")
                        return "FALLBACK", None
            except Exception as e:
                logger.debug(f"[Google] Hálózati hiba: {e}")
                await asyncio.sleep(1)
        
        logger.warning("[Google] Mindkét próbálkozás sikertelen, pipeline FAILED.")
        return "FALLBACK", None

# -------------------------------------------------------------------
# PIPELINE KOORDINÁTOR
# -------------------------------------------------------------------

class ValidationPipeline:
    """
    A teljes 5‑szintes pipeline koordinátora.
    
    Felelősség:
        - Szekvenciális hívás az 1‑5. szinteknek
        - Adatbázis frissítés a sikeres validáció után
        - Naplózás és metrika gyűjtés
    """
    
    def __init__(self):
        self.validators = [
            OSMNominatimValidator(),
            EUVIESValidator(),
            FreemiumAPIValidator(),
            WebScrapingValidator(),
            GooglePlacesValidator()
        ]
    
    async def run(self, profile_id: int) -> bool:
        """Futtatja a pipeline‑t egy adott szerviz profilra."""
        async with AsyncSessionLocal() as db:
            # Profil adatok lekérése
            result = await db.execute(
                text("SELECT fingerprint, bio FROM marketplace.service_profiles WHERE id = :id"),
                {"id": profile_id}
            )
            row = result.fetchone()
            if not row:
                logger.error(f"[Pipeline] Profil {profile_id} nem található.")
                return False
            
            fingerprint, bio = row
            
            # Szekvenciális validáció
            for i, validator in enumerate(self.validators, 1):
                status, data = await validator.validate(db, profile_id, fingerprint, bio)
                if status == "DONE":
                    logger.info(f"[Pipeline] {i}. szint sikeres, profil frissítése.")
                    # Adatbázis frissítés (egyszerűsített)
                    await db.execute(
                        text("UPDATE marketplace.service_profiles SET status = 'active', trust_score = trust_score + :score WHERE id = :id"),
                        {"score": 10 * i, "id": profile_id}
                    )
                    await db.commit()
                    return True
                elif status == "FALLBACK":
                    logger.info(f"[Pipeline] {i}. szint sikertelen, továbblépés {i+1}. szintre.")
                    continue
                else:
                    logger.error(f"[Pipeline] {i}. szint hibás, pipeline leáll.")
                    break
            
            logger.warning(f"[Pipeline] Minden szint sikertelen, profil flagged.")
            await db.execute(
                text("UPDATE marketplace.service_profiles SET status = 'flagged' WHERE id = :id"),
                {"id": profile_id}
            )
            await db.commit()
            return False
