import type { RangeRequestOptions, RangeResponse } 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 {
  ModelComponentProps,
  ModelHookResponse,
  ModelProps,
  SpreadWidgetProps,
} from './types'

export const getSpread: ModelQueryFactory<SpreadWidgetProps, RangeResponse> = (
  args,
) =>
  getModelQueryOptions<SpreadWidgetProps, RangeResponse>({
    queryKeyPrefix: ['spread'],
    getWidgetMethod: (widgetModel) => (params) =>
      widgetModel.getRange(params as RangeRequestOptions),
    ...args,
  })

const { useModelHook: useSpreadQuery } = createModel<
  SpreadWidgetProps,
  RangeResponse
>({ buildQuery: getSpread })

/**
 * `useSpread` is a hook that calculates the spread (max - min) of a numerical column using the Range API internally.
 * `SpreadModel` is the render-props component equivalent.
 */
function useSpread<P extends ModelProps<SpreadWidgetProps, RangeResponse>>(
  props: P,
): ModelHookResponse<P, RangeResponse> {
  const { sourceId, sourcesId } = props
  const slices = useSourceSlices(sourceId ? [sourceId] : (sourcesId ?? []))
  return useSpreadQuery(props, slices)
}

function SpreadModel<P extends ModelProps<SpreadWidgetProps, RangeResponse>>(
  props: ModelComponentProps<SpreadWidgetProps, RangeResponse, P>,
): React.ReactElement {
  return props.children(useSpread(props)) as React.ReactElement
}

export { useSpread, SpreadModel }
