import type { FormulaRequestOptions, FormulaResponse } 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 {
  FormulaWidgetProps,
  ModelComponentProps,
  ModelHookResponse,
  ModelProps,
} from './types'

export const getFormula: ModelQueryFactory<
  FormulaWidgetProps,
  FormulaResponse
> = (args) =>
  getModelQueryOptions<FormulaWidgetProps, FormulaResponse>({
    queryKeyPrefix: ['formula'],
    getWidgetMethod: (widgetModel) => (params) =>
      widgetModel.getFormula(params as FormulaRequestOptions),
    ...args,
  })

const { useModelHook: useFormulaQuery } = createModel<
  FormulaWidgetProps,
  FormulaResponse
>({ buildQuery: getFormula })

/**
 * `useFormula` is a hook that performs an aggregation operation (count, sum, avg, min, max) on a single column.
 * `FormulaModel` is the render-props component equivalent.
 *
 * @example
 * ```tsx
 * <FormulaModel
 *   accessToken={token}
 *   sourceId="my_source"
 *   widgetProps={{ column: 'population', operation: 'sum' }}
 * >
 *   {({ data, isLoading }) => <span>{data?.value}</span>}
 * </FormulaModel>
 * ```
 */
function useFormula<P extends ModelProps<FormulaWidgetProps, FormulaResponse>>(
  props: P,
): ModelHookResponse<P, FormulaResponse> {
  const { sourceId, sourcesId } = props
  const slices = useSourceSlices(sourceId ? [sourceId] : (sourcesId ?? []))
  return useFormulaQuery(props, slices)
}

function FormulaModel<
  P extends ModelProps<FormulaWidgetProps, FormulaResponse>,
>(
  props: ModelComponentProps<FormulaWidgetProps, FormulaResponse, P>,
): React.ReactElement {
  return props.children(useFormula(props)) as React.ReactElement
}

export { useFormula, FormulaModel }
