from __future__ import annotations
from typing import Any, Dict, List, Optional

from .http import HttpClient, AsyncHttpClient
from .types import GeocodeResult
import json
import logging

class GeocodeClient:
    """Geocoding client (sync)."""

    def __init__(self, http: HttpClient, *, logger: logging.Logger | None = None):
        self._http = http
        self._logger = logger or logging.getLogger("lamen.geocode")

    def search(
        self,
        *,
        query: str,
        limit: int = 10,
        country: Optional[str] = None,
    ) -> List[Dict[str, Any]]:
        if not query or not query.strip():
            raise ValueError("Query cannot be empty")

        params: Dict[str, Any] = {
            "q": query,
            "limit": limit,
        }
        if country:
            params["country"] = country

        data = self._http.get("/geocode/search", params=params)

        if isinstance(data, dict) and "value" in data:
            data = data["value"]

        if isinstance(data, str):
            data = json.loads(data)

        if not isinstance(data, list):
            raise ValueError("Unexpected geocode response shape")

        # Now it MUST be a list of dicts
        return [GeocodeResult(**item) for item in data]


class AsyncGeocodeClient:
    """Geocoding client (async)."""

    def __init__(self, http: AsyncHttpClient, *, logger: logging.Logger | None = None):
        self._http = http
        self._logger = logger or logging.getLogger("lamen.geocode")

    async def search(
        self,
        *,
        query: str,
        limit: int = 10,
        country: Optional[str] = None,
    ) -> List[Dict[str, Any]]:
        if not query or not query.strip():
            raise ValueError("Query cannot be empty")

        params: Dict[str, Any] = {
            "q": query,
            "limit": limit,
        }
        if country:
            params["country"] = country

        data = await self._http.get("/geocode/search", params=params)

        #  If Redis-wrapped
        if isinstance(data, dict) and "value" in data:
            data = data["value"]

        #  If JSON string
        if isinstance(data, str):
            data = json.loads(data)

        if not isinstance(data, list):
            raise ValueError("Unexpected geocode response shape")

        # Now it MUST be a list of dicts
        return [GeocodeResult(**item) for item in data]

