import { httpExternal } from '~/utils/httpExternal'

// Autocomplétion d'adresse branchée sur la Base Adresse Nationale (BAN),
// `api-adresse.data.gouv.fr` — service public français, gratuit, CORS ouvert.
//
// Appel HTTP DIRECT depuis le front (pas de proxy back) : la BAN est un domaine
// externe, sans cookie de session ni enveloppe Hydra → on passe par
// `httpExternal` et NON `useApi()`.
//
// Contrat :
//   searchCity(postalCode)       -> liste { city, postalCode }
//   searchAddress(query, cp?)    -> liste { label, street, postalCode, city }
//   En cas d'erreur/timeout, la méthode THROW une
//   AddressAutocompleteUnavailableError. Le composant consommateur catch,
//   avertit l'utilisateur et bascule en saisie libre.

/** URL de l'endpoint de recherche BAN. */
const BAN_SEARCH_URL = 'https://api-adresse.data.gouv.fr/search/'

/** Une suggestion de ville renvoyée à partir d'un code postal. */
export interface CitySuggestion {
    city: string
    postalCode: string
}

/** Une suggestion d'adresse complète (saisie assistée du champ « Rue »). */
export interface AddressSuggestion {
    label: string
    street: string
    postalCode: string
    city: string
}

export interface AddressAutocomplete {
    searchCity(postalCode: string): Promise<CitySuggestion[]>
    searchAddress(query: string, postalCode?: string): Promise<AddressSuggestion[]>
}

/** Erreur signalant que le service d'autocomplétion BAN n'est pas disponible. */
export class AddressAutocompleteUnavailableError extends Error {
    constructor() {
        super('Address autocomplete (BAN) is not available.')
        this.name = 'AddressAutocompleteUnavailableError'
    }
}

/** Propriétés d'une « feature » GeoJSON renvoyée par la BAN (champs utilisés). */
interface BanFeatureProperties {
    label?: string
    name?: string
    street?: string
    postcode?: string
    city?: string
}

/** Réponse GeoJSON FeatureCollection de la BAN. */
interface BanResponse {
    features?: { properties?: BanFeatureProperties }[]
}

export function useAddressAutocomplete(): AddressAutocomplete {
    return {
        async searchCity(postalCode: string): Promise<CitySuggestion[]> {
            let res: BanResponse
            try {
                res = await httpExternal<BanResponse>(BAN_SEARCH_URL, {
                    query: { q: postalCode, type: 'municipality' },
                })
            }
            catch {
                throw new AddressAutocompleteUnavailableError()
            }

            return (res.features ?? []).map((feature) => {
                const props = feature.properties ?? {}
                return {
                    city: props.city ?? props.name ?? '',
                    postalCode: props.postcode ?? '',
                }
            })
        },

        async searchAddress(query: string, postalCode?: string): Promise<AddressSuggestion[]> {
            // Pas de `type=housenumber` ici : sans filtre, la BAN classe rues +
            // numéros par pertinence (comportement d'autocomplétion attendu).
            // On n'ajoute `postcode` que s'il est fourni (sinon recherche large).
            const banQuery: Record<string, string> = { q: query }
            if (postalCode) {
                banQuery.postcode = postalCode
            }

            let res: BanResponse
            try {
                res = await httpExternal<BanResponse>(BAN_SEARCH_URL, { query: banQuery })
            }
            catch {
                throw new AddressAutocompleteUnavailableError()
            }

            return (res.features ?? []).map((feature) => {
                const props = feature.properties ?? {}
                return {
                    label: props.label ?? '',
                    // `name` porte la ligne d'adresse complète (numéro + voie) ;
                    // `street` ne contient que la voie. On privilégie `name`.
                    street: props.name ?? props.street ?? '',
                    postalCode: props.postcode ?? '',
                    city: props.city ?? '',
                }
            })
        },
    }
}
