from __future__ import annotations from typing import Any from .evidence import make_evidence from .http_client import get_json from .models import EvidenceItem NOMINATIM_REVERSE_URL = "https://nominatim.openstreetmap.org/reverse" def reverse_geocode_site(lat: float, lon: float) -> tuple[dict[str, Any], list[EvidenceItem]]: """Return an OSM-derived address identity for the site anchor. This is intentionally treated as contextual identity, not official address verification. Nominatim public usage is kept to one generate-time reverse lookup instead of interactive autocomplete. """ try: payload = get_json( NOMINATIM_REVERSE_URL, { "format": "jsonv2", "lat": lat, "lon": lon, "addressdetails": 1, "zoom": 18, }, timeout=18, ) address = payload.get("address") or {} identity = { "display_name": payload.get("display_name"), "road": address.get("road") or address.get("pedestrian") or address.get("path"), "neighbourhood": address.get("neighbourhood") or address.get("suburb") or address.get("quarter"), "city": address.get("city") or address.get("town") or address.get("village"), "district": address.get("county") or address.get("state_district"), "state": address.get("state"), "postcode": address.get("postcode"), "country": address.get("country"), "lat": lat, "lon": lon, } evidence = [ make_evidence( category="Site identity", finding="Approximate address and administrative context were reverse-geocoded from the site anchor.", source_name="OpenStreetMap Nominatim", source_url="https://nominatim.org/release-docs/latest/api/Reverse/", source_type="open geocoding service", resolution_or_scope="single reverse-geocoding request at site anchor/centroid", confidence="medium" if identity.get("display_name") else "low", limitation="OSM-derived address context may be incomplete, approximate, or outdated. It is not legal address verification.", design_implication="Use this to label the site and organize studio research by street, city, state, and country.", verification_needed="Confirm final address and administrative names from project brief, faculty, client, or local records.", output_label="public_data", ) ] return identity, evidence except Exception as exc: # noqa: BLE001 return { "display_name": None, "lat": lat, "lon": lon, "error": f"{type(exc).__name__}: {exc}", }, [ make_evidence( category="Site identity", finding="Reverse-geocoded address could not be retrieved.", source_name="OpenStreetMap Nominatim", source_url="https://nominatim.org/release-docs/latest/api/Reverse/", source_type="open geocoding service", resolution_or_scope="not available", confidence="low", limitation=f"Reverse geocoder failed: {type(exc).__name__}.", design_implication="Do not infer street/city/state labels from missing geocoding data.", verification_needed="Enter address details manually from the project brief or site documents.", output_label="site_visit_required", ) ]