import { BARI_BOUNDS, isWithinBariBounds } from '~/utils/bari' interface NominatimAddress { road?: string house_number?: string pedestrian?: string footway?: string path?: string cycleway?: string suburb?: string neighbourhood?: string city?: string town?: string village?: string municipality?: string } interface NominatimResult { lat: string lon: string display_name: string address?: NominatimAddress } export interface GeocodingSuggestion { label: string latitude: number longitude: number } const NOMINATIM_BASE_URL = 'https://nominatim.openstreetmap.org' const bariViewbox = `${BARI_BOUNDS.west},${BARI_BOUNDS.north},${BARI_BOUNDS.east},${BARI_BOUNDS.south}` const compactAddress = (displayName: string, address?: NominatimAddress) => { if (!address) { return displayName } const streetName = address.road || address.pedestrian || address.footway || address.path || address.cycleway const street = [streetName, address.house_number].filter(Boolean).join(' ') const locality = address.city || address.town || address.village || address.municipality || 'Bari' const area = address.suburb || address.neighbourhood const formatted = [street, locality, area] .filter(Boolean) .filter((part, index, all) => all.indexOf(part) === index) .join(', ') return formatted || displayName } const toSuggestion = (result: NominatimResult): GeocodingSuggestion | null => { const latitude = Number.parseFloat(result.lat) const longitude = Number.parseFloat(result.lon) if (!Number.isFinite(latitude) || !Number.isFinite(longitude)) { return null } return { label: compactAddress(result.display_name, result.address), latitude, longitude } } export const searchAddresses = async (query: string, limit = 5) => { const params = new URLSearchParams({ q: query, format: 'jsonv2', addressdetails: '1', 'accept-language': 'it', countrycodes: 'it', bounded: '1', viewbox: bariViewbox, limit: String(limit) }) const results = await $fetch(`${NOMINATIM_BASE_URL}/search?${params.toString()}`) return results .map(toSuggestion) .filter((result): result is GeocodingSuggestion => Boolean(result)) .filter((result) => isWithinBariBounds(result.latitude, result.longitude)) } export const reverseGeocode = async (latitude: number, longitude: number) => { const params = new URLSearchParams({ lat: String(latitude), lon: String(longitude), zoom: '18', format: 'jsonv2', addressdetails: '1', 'accept-language': 'it' }) const result = await $fetch(`${NOMINATIM_BASE_URL}/reverse?${params.toString()}`) if (!result) { return '' } return compactAddress(result.display_name, result.address) }