from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import text
from typing import Optional, List
import uuid

class GeoService:
    @staticmethod
    async def get_street_suggestions(db: AsyncSession, zip_code: str, q: str) -> List[str]:
        """Azonnali utca-kiegészítés (Autocomplete) támogatása."""
        query = text("""
            SELECT s.name 
            FROM data.geo_streets s
            JOIN data.geo_postal_codes p ON s.postal_code_id = p.id
            WHERE p.zip_code = :zip AND s.name ILIKE :q
            ORDER BY s.name ASC LIMIT 10
        """)
        res = await db.execute(query, {"zip": zip_code, "q": f"{q}%"})
        return [row[0] for row in res.fetchall()]

    @staticmethod
    async def get_or_create_full_address(
        db: AsyncSession, 
        zip_code: str, city: str, street_name: str, 
        street_type: str, house_number: str, 
        parcel_id: Optional[str] = None
    ) -> uuid.UUID:
        """Hibrid címrögzítés: ellenőrzi a szótárakat és létrehozza a központi címet."""
        # 1. Zip/City szótár frissítése (Auto-learning)
        zip_id_res = await db.execute(text("""
            INSERT INTO data.geo_postal_codes (zip_code, city) VALUES (:z, :c)
            ON CONFLICT (country_code, zip_code, city) DO UPDATE SET city = EXCLUDED.city
            RETURNING id
        """), {"z": zip_code, "c": city})
        zip_id = zip_id_res.scalar()

        # 2. Utca szótár frissítése (Auto-learning)
        await db.execute(text("""
            INSERT INTO data.geo_streets (postal_code_id, name) VALUES (:zid, :n)
            ON CONFLICT (postal_code_id, name) DO NOTHING
        """), {"zid": zip_id, "n": street_name})

        # 3. Közterület típus (út, utca...) szótár
        await db.execute(text("""
            INSERT INTO data.geo_street_types (name) VALUES (:n) ON CONFLICT DO NOTHING
        """), {"n": street_type.lower()})

        # 4. Központi Address rekord rögzítése
        full_text = f"{zip_code} {city}, {street_name} {street_type} {house_number}"
        addr_res = await db.execute(text("""
            INSERT INTO data.addresses (postal_code_id, street_name, street_type, house_number, parcel_id, full_address_text)
            VALUES (:zid, :sn, :st, :hn, :pid, :txt)
            ON CONFLICT DO NOTHING
            RETURNING id
        """), {
            "zid": zip_id, "sn": street_name, "st": street_type, "hn": house_number, "pid": parcel_id, "txt": full_text
        })
        addr_id = addr_res.scalar()

        if not addr_id:
            # Ha már létezett, lekérjük az azonosítót
            addr_id = (await db.execute(text("""
                SELECT id FROM data.addresses 
                WHERE postal_code_id = :zid AND street_name = :sn AND street_type = :st AND house_number = :hn
            """), {"zid": zip_id, "sn": street_name, "st": street_type, "hn": house_number})).scalar()

        return addr_id