"""Geocoder para location_agent.

Wrapper sobre el Census Geocoder existente en data_fetchers/census_geocode.py.
Si falla Census, intenta Nominatim (OpenStreetMap) como fallback gratuito.
"""

from __future__ import annotations

import sys
import time
from pathlib import Path

import requests

_PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent
if str(_PROJECT_ROOT) not in sys.path:
    sys.path.insert(0, str(_PROJECT_ROOT))

from data_fetchers.census_geocode import fetch_geocode
from data_fetchers.base import FetcherError, USER_AGENT, DEFAULT_TIMEOUT

NOMINATIM_URL = "https://nominatim.openstreetmap.org/search"


def geocode(address: str) -> dict:
    """Geocodifica una dirección USA. Census primero, Nominatim como fallback.

    Returns dict con: address, lat, lon, city, state, zip, county,
                      county_fips, state_fips, tract_geoid, source
    Raises ValueError si no se puede geocodificar.
    """
    # 1. Census Geocoder (preferido — devuelve tract FIPS)
    try:
        result = fetch_geocode(address)
        if result.get("lat") and result.get("lng"):
            return {
                "address": result.get("matched_address", address),
                "lat": float(result["lat"]),
                "lon": float(result["lng"]),
                "city": result.get("city", ""),
                "state": result.get("state", ""),
                "zip": result.get("zip", ""),
                "county": result.get("county_name", ""),
                "county_fips": result.get("county_fips", ""),
                "state_fips": result.get("state_fips", ""),
                "tract_geoid": result.get("tract_geoid", ""),
                "source": "census",
            }
    except (FetcherError, Exception):
        pass

    # 2. Nominatim fallback
    try:
        params = {
            "q": address,
            "format": "json",
            "addressdetails": 1,
            "limit": 1,
            "countrycodes": "us",
        }
        headers = {"User-Agent": USER_AGENT}
        time.sleep(1)
        r = requests.get(NOMINATIM_URL, params=params, headers=headers, timeout=DEFAULT_TIMEOUT)
        r.raise_for_status()
        results = r.json()
        if results:
            m = results[0]
            addr = m.get("address", {})
            return {
                "address": m.get("display_name", address),
                "lat": float(m["lat"]),
                "lon": float(m["lon"]),
                "city": addr.get("city") or addr.get("town") or addr.get("village", ""),
                "state": addr.get("state", ""),
                "zip": addr.get("postcode", ""),
                "county": addr.get("county", ""),
                "county_fips": "",
                "state_fips": "",
                "tract_geoid": "",
                "source": "nominatim",
            }
    except Exception:
        pass

    raise ValueError(f"No se pudo geocodificar: {address!r}")
