/**
 * Resolve the state/province for a destination address via public geo services.
 * Used by the commissioning address wizard (Magic Fix) to PROPOSE a state when
 * the address has none at all — e.g. US shipments, where DHL requires
 * consignee.state but the order data often carries no region.
 *
 * Query: country (ISO2, default US), postal, city (fallback when no postal).
 * Returns { status, stateCode, stateName, city, source } — status 404 when
 * nothing could be resolved. Always fail-soft: never throws to the client.
 *
 * 1) zippopotam.us — deterministic postal-code → state, no API key
 * 2) Nominatim (OpenStreetMap) — structured search fallback, also city-only
 */

// ZIP→state never changes: cache resolved lookups in-process.
const lookupCache = new Map<string, any>()

const handleFunc = async (event: any) => {
  const query = getQuery(event)
  const country = String(query.country || 'US').toUpperCase().slice(0, 2)
  const postalRaw = String(query.postal || '').trim().slice(0, 20)
  const city = String(query.city || '').trim().slice(0, 60)
  if (!postalRaw && !city) return { status: 404 }

  const cacheKey = `${country}|${postalRaw.toUpperCase()}|${postalRaw ? '' : city.toLowerCase()}`
  if (lookupCache.has(cacheKey)) return lookupCache.get(cacheKey)
  if (lookupCache.size > 2000) lookupCache.clear()

  let result: any = { status: 404 }

  // 1) zippopotam.us — postal code lookup (US wants the plain 5-digit ZIP)
  if (postalRaw) {
    const zip = country === 'US' ? ((postalRaw.match(/\d{5}/) || [])[0] || '') : postalRaw
    if (zip) {
      try {
        const res: any = await $fetch(`https://api.zippopotam.us/${country.toLowerCase()}/${encodeURIComponent(zip)}`, { timeout: 6000 })
        const place = res?.places?.[0]
        if (place && (place['state abbreviation'] || place['state'])) {
          result = {
            status: 200,
            stateCode: String(place['state abbreviation'] || '').toUpperCase(),
            stateName: String(place['state'] || ''),
            city: String(place['place name'] || ''),
            source: 'zippopotam.us'
          }
        }
      } catch {
        // fall through to Nominatim
      }
    }
  }

  // 2) Nominatim fallback — postal code the primary DB missed, or city-only
  if (result.status !== 200) {
    try {
      const params: any = { format: 'jsonv2', addressdetails: 1, limit: 1, countrycodes: country.toLowerCase() }
      if (postalRaw) params.postalcode = postalRaw
      else params.city = city
      const res: any = await $fetch('https://nominatim.openstreetmap.org/search', {
        params,
        timeout: 6000,
        headers: { 'User-Agent': 'LogShip-ERP/1.0 (+https://app.logship.de)' }
      })
      const addr = res?.[0]?.address
      if (addr?.state || addr?.['ISO3166-2-lvl4']) {
        // "ISO3166-2-lvl4": "US-NY" → "NY"
        const iso = String(addr['ISO3166-2-lvl4'] || '')
        const code = iso.toUpperCase().startsWith(country + '-') ? iso.slice(country.length + 1) : ''
        result = {
          status: 200,
          stateCode: String(code || '').toUpperCase(),
          stateName: String(addr.state || ''),
          city: String(addr.city || addr.town || addr.village || ''),
          source: 'openstreetmap.org'
        }
      }
    } catch {
      // stay 404
    }
  }

  if (result.status === 200) lookupCache.set(cacheKey, result)
  return result
}

export default defineEventHandler(async (event) => {
  try {
    return await handleFunc(event)
  } catch {
    return { status: 404 }
  }
})
