import type { InstantSearchGeoParams } from '../../types/index.js'

export function adaptGeoSearch({
  insidePolygon,
  insideBoundingBox,
  aroundLatLng,
  aroundRadius,
  minimumAroundRadius,
}: InstantSearchGeoParams): string | undefined {
  let middlePoint: string[] | undefined
  let radius: number | undefined
  let filter: string | undefined

  // Highest precedence: insidePolygon
  if (Array.isArray(insidePolygon) && insidePolygon.length >= 3) {
    const invalidPairs: unknown[] = []

    const formattedPoints = insidePolygon
      .map((pair) => {
        if (!Array.isArray(pair) || pair.length < 2) {
          invalidPairs.push(pair)
          return null
        }
        const lat = Number.parseFloat(String(pair[0]))
        const lng = Number.parseFloat(String(pair[1]))
        if (Number.isNaN(lat) || Number.isNaN(lng)) {
          invalidPairs.push(pair)
          return null
        }
        return `[${lat}, ${lng}]`
      })
      .filter((pt): pt is string => pt !== null)

    if (invalidPairs.length > 0) {
      console.warn(
        'instant-meilisearch: insidePolygon contains invalid coordinate pairs that were ignored:',
        invalidPairs
      )
    }

    if (formattedPoints.length >= 3) {
      filter = `_geoPolygon(${formattedPoints.join(', ')})`
      return filter
    }
  }

  if (aroundLatLng) {
    const [lat, lng] = aroundLatLng
      .split(',')
      .map((pt) => Number.parseFloat(pt).toFixed(5))

    middlePoint = [lat, lng]
  }

  if (aroundRadius != null || minimumAroundRadius != null) {
    if (aroundRadius === 'all') {
      console.warn(
        'instant-meilisearch is not compatible with the `all` value on the aroundRadius parameter'
      )
    } else if (aroundRadius != null) {
      radius = aroundRadius
    } else {
      radius = minimumAroundRadius
    }
  }

  if (insideBoundingBox && typeof insideBoundingBox === 'string') {
    const [lat1, lng1, lat2, lng2] = insideBoundingBox
      .split(',')
      .map((pt) => parseFloat(pt))

    filter = `_geoBoundingBox([${lat1}, ${lng1}], [${lat2}, ${lng2}])`
  } else if (middlePoint != null && radius != null) {
    const [lat, lng] = middlePoint

    filter = `_geoRadius(${lat}, ${lng}, ${radius})`
  }

  return filter
}
