import {
  centroid,
  lineString,
  multiLineString,
  multiPoint,
  multiPolygon,
  point,
  polygon,
} from '@turf/turf'
import type { Feature, Geometry, Position } from 'geojson'

type GeometryHandler = (geometry: Geometry) => Feature<Geometry> | undefined

/**
 * Mapping of geometry types to their corresponding Turf.js factory functions.
 */
const geometryTypeHandlers: Record<string, GeometryHandler | undefined> = {
  Point: (g) => point((g as Extract<Geometry, { type: 'Point' }>).coordinates),
  LineString: (g) =>
    lineString((g as Extract<Geometry, { type: 'LineString' }>).coordinates),
  Polygon: (g) =>
    polygon((g as Extract<Geometry, { type: 'Polygon' }>).coordinates),
  MultiPoint: (g) =>
    multiPoint((g as Extract<Geometry, { type: 'MultiPoint' }>).coordinates),
  MultiLineString: (g) =>
    multiLineString(
      (g as Extract<Geometry, { type: 'MultiLineString' }>).coordinates,
    ),
  MultiPolygon: (g) =>
    multiPolygon(
      (g as Extract<Geometry, { type: 'MultiPolygon' }>).coordinates,
    ),
}

/**
 * Returns the centroid of a geometry.
 *
 * @param geometry - The geometry to get the centroid of
 * @returns The centroid coordinates [longitude, latitude] or undefined if geometry is invalid
 *
 * @example
 * ```typescript
 * const geometry = {
 *   type: 'Polygon',
 *   coordinates: [
 *     [[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]
 *   ]
 * }
 * const center = getCentroid(geometry)
 * console.log(center) // [0.5, 0.5]
 * ```
 */
export function getCentroid(geometry: Geometry): Position | undefined {
  const handler = geometryTypeHandlers[geometry.type]
  const feature = handler?.(geometry)

  if (!feature) {
    return
  }

  return centroid(feature).geometry.coordinates
}
