import type {
  FeaturesRequestOptions,
  FeaturesResponse,
} from '@carto/api-client'
import { createModel, type ModelQueryFactory } from './utils/create-model'
import { getModelQueryOptions } from './utils/get-model-query-options'
import { useSourceSlices } from './utils/use-source-slices'
import type {
  FeaturesWidgetProps,
  ModelComponentProps,
  ModelHookResponse,
  ModelProps,
} from './types'

export const getFeatures: ModelQueryFactory<
  FeaturesWidgetProps,
  FeaturesResponse
> = (args) =>
  getModelQueryOptions<FeaturesWidgetProps, FeaturesResponse>({
    queryKeyPrefix: ['features'],
    getWidgetMethod: (widgetModel) => (params) =>
      widgetModel.getFeatures(params as FeaturesRequestOptions),
    ...args,
  })

const { useModelHook: useFeaturesQuery } = createModel<
  FeaturesWidgetProps,
  FeaturesResponse
>({ buildQuery: getFeatures })

/**
 * `useFeatures` is a hook that retrieves geospatial feature data (GeoJSON) with associated properties for spatial analysis.
 * `FeaturesModel` is the render-props component equivalent.
 */
function useFeatures<
  P extends ModelProps<FeaturesWidgetProps, FeaturesResponse>,
>(props: P): ModelHookResponse<P, FeaturesResponse> {
  const { sourceId, sourcesId } = props
  const slices = useSourceSlices(sourceId ? [sourceId] : (sourcesId ?? []))
  return useFeaturesQuery(props, slices)
}

function FeaturesModel<
  P extends ModelProps<FeaturesWidgetProps, FeaturesResponse>,
>(
  props: ModelComponentProps<FeaturesWidgetProps, FeaturesResponse, P>,
): React.ReactElement {
  return props.children(useFeatures(props)) as React.ReactElement
}

export { useFeatures, FeaturesModel }
