packages feed

bloodhound-1.0.0.0: src/Database/Bloodhound/ElasticSearch9/Requests.hs

{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TupleSections #-}

module Database.Bloodhound.ElasticSearch9.Requests
  ( module Reexport,
    openPointInTime,
    openPointInTimeWith,
    openPointInTimeWithBody,
    closePointInTime,
    esql,
    esqlWith,
    esqlAsync,
    esqlAsyncWith,
    getAsyncESQL,
    getAsyncESQLWith,
    deleteAsyncESQL,
    stopAsyncESQL,
    putESQLView,
    getESQLView,
    deleteESQLView,
    getESQLQuery,
    getESQLQueries,
    putInferenceEndpoint,
    putInferenceEndpointWith,
    updateInferenceEndpoint,
    getInferenceEndpoints,
    deleteInferenceEndpoint,
    deleteInferenceEndpointWith,
    runInference,
    runInferenceWith,
    streamCompletionInference,
    streamCompletionInferenceWith,
    streamChatCompletionInference,
    streamChatCompletionInferenceWith,
    putQueryRuleset,
    getQueryRuleset,
    deleteQueryRuleset,
    testQueryRuleset,
    putSearchApplication,
    putSearchApplicationWith,
    getSearchApplication,
    deleteSearchApplication,
    searchApplication,
    searchApplicationWith,
    listSearchApplications,
    listSearchApplicationsWith,
    renderSearchApplicationQuery,
    putDataStreamLifecycle,
    putDataStreamsLifecycle,
    getDataStreamLifecycle,
    deleteDataStreamLifecycle,
    getDataStreamOptions,
    updateDataStreamOptions,
    deleteDataStreamOptions,
    getDataStreamLifecycleStats,
    explainDataStreamLifecycle,
    explainDataStreamLifecycleWith,
    getDataStreamMappings,
    getDataStreamMappingsWith,
    putDataStreamMappings,
    putDataStreamMappingsWith,
    getDataStreamSettings,
    getDataStreamSettingsWith,
    putDataStreamSettings,
    putDataStreamSettingsWith,
    eqlSearch,
    eqlSearchWith,
    getEQLSearch,
    getEQLStatus,
    deleteEQLSearch,
    getTermsEnum,
    getTermsEnumWith,
    getStreamsStatus,
    getStreamsStatusWith,
    enableStream,
    enableStreamWith,
    disableStream,
    disableStreamWith,
    downsampleIndex,
    downsampleIndexWith,
    migrateReindex,
    cancelMigrateReindex,
    getMigrateReindexStatus,
    createIndexFrom,
    createIndexFromWith,
    getGeoIpStats,
    getGeoIpDatabases,
    getGeoIpDatabase,
    putGeoIpDatabase,
    deleteGeoIpDatabase,
    getIpLocationDatabases,
    getIpLocationDatabase,
    putIpLocationDatabase,
    deleteIpLocationDatabase,
    simulateIngest,
    simulateIngestWith,
    simulateIngestIndex,
    simulateIngestIndexWith,
    simulateIngestGet,
    simulateIngestWithGet,
    simulateIngestIndexGet,
    simulateIngestIndexWithGet,
    resolveCluster,
    resolveClusterWith,
    getHealthReport,
    getHealthReportWith,
    getFeatures,
    getFeaturesWith,
    resetFeatures,
    resetFeaturesWith,
    putMlDataFrameAnalytics,
    putMlDataFrameAnalyticsWith,
    getMlDataFrameAnalytics,
    getMlDataFrameAnalyticsWith,
    updateMlDataFrameAnalytics,
    updateMlDataFrameAnalyticsWith,
    deleteMlDataFrameAnalytics,
    deleteMlDataFrameAnalyticsWith,
    startMlDataFrameAnalytics,
    startMlDataFrameAnalyticsWith,
    stopMlDataFrameAnalytics,
    stopMlDataFrameAnalyticsWith,
    getMlDataFrameAnalyticsStats,
    getMlDataFrameAnalyticsStatsWith,
    previewMlDataFrameAnalytics,
    putMlTrainedModel,
    putMlTrainedModelWith,
    getMlTrainedModels,
    getMlTrainedModelsWith,
    getMlTrainedModelDefinition,
    getMlTrainedModelDefinitionWith,
    updateMlTrainedModel,
    updateMlTrainedModelWith,
    deleteMlTrainedModel,
    deleteMlTrainedModelWith,
    deployMlTrainedModel,
    deployMlTrainedModelWith,
    undeployMlTrainedModel,
    undeployMlTrainedModelWith,
    startMlTrainedModelDeployment,
    startMlTrainedModelDeploymentWith,
    stopMlTrainedModelDeployment,
    stopMlTrainedModelDeploymentWith,
    getMlTrainedModelStats,
    getMlTrainedModelStatsWith,
    inferMlTrainedModel,
    putMlAnomalyJob,
    getMlAnomalyJobs,
    getMlAnomalyJobsWith,
    updateMlAnomalyJob,
    deleteMlAnomalyJob,
    deleteMlAnomalyJobWith,
    openMlAnomalyJob,
    closeMlAnomalyJob,
    forecastMlAnomalyJob,
    flushMlAnomalyJob,
    validateMlAnomalyJob,
    getMlAnomalyJobStats,
    getMlAnomalyJobStatsWith,
    getMlAnomalyJobResults,
    getMlAnomalyJobResultsWith,
    getMlModelSnapshots,
    getMlModelSnapshotsWith,
    getMlModelSnapshot,
    getMlModelSnapshotWith,
    updateMlModelSnapshot,
    deleteMlModelSnapshot,
    deleteMlModelSnapshotWith,
    revertMlModelSnapshot,
    revertMlModelSnapshotWith,
    putMlDatafeed,
    getMlDatafeeds,
    getMlDatafeedsWith,
    updateMlDatafeed,
    deleteMlDatafeed,
    startMlDatafeed,
    stopMlDatafeed,
    previewMlDatafeed,
    putMlFilter,
    getMlFilters,
    getMlFiltersWith,
    deleteMlFilter,
    putMlCalendar,
    getMlCalendars,
    getMlCalendarsWith,
    deleteMlCalendar,
    setMlScheduledEvents,
    getMlScheduledEvents,
  )
where

import Data.Aeson
import Data.ByteString.Lazy qualified as L
import Data.List.NonEmpty (NonEmpty)
import Data.Maybe (catMaybes)
import Data.Text (Text)
import Data.Text qualified as T
import Database.Bloodhound.Client.Cluster
import Database.Bloodhound.Common.Requests as Reexport
import Database.Bloodhound.Common.Types
import Database.Bloodhound.ElasticSearch8.Requests qualified as Requests8
import Database.Bloodhound.ElasticSearch9.Types
import Database.Bloodhound.Internal.Utils.Requests
import Database.Bloodhound.Internal.Versions.Common.Types.KeepAlive ()
import Prelude hiding (filter, head)

-- | 'openPointInTime' opens a point in time for a single index given an
-- 'IndexName', using the supplied 'KeepAlive' duration (e.g.
-- @keepAliveMinutes 1@). Note that the point in time should be closed
-- with 'closePointInTime' as soon as it is no longer needed.
--
-- This is a convenience wrapper around 'openPointInTimeWith' that lifts
-- the single 'IndexName' into an 'IndexPattern'. To target multiple
-- comma-joined indices or a wildcard pattern (e.g. @\"logs-*,app-*\"@),
-- use 'openPointInTimeWith' directly with an 'IndexPattern'.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/point-in-time-api.html>.
openPointInTime ::
  IndexName ->
  KeepAlive ->
  BHRequest StatusDependant (ParsedEsResponse OpenPointInTimeResponse)
openPointInTime indexName keepAlive =
  openPointInTimeWith (IndexPattern (unIndexName indexName)) keepAlive defaultPITOptions

-- | 'openPointInTimeWith' is the parameterized variant of
-- 'openPointInTime' on Elasticsearch 9: it takes an 'IndexPattern' as
-- the target, which may be a single index name, a comma-separated list
-- of indices, or a wildcard pattern (e.g. @\"logs-*\"@,
-- @\"logs-2024,logs-2025\"@). It forwards the supplied 'PITOptions' as
-- query-string parameters in addition to the mandatory @keep_alive@.
-- Only the parameters accepted by the Elasticsearch PIT endpoint are
-- emitted (@routing@, @preference@, @expand_wildcards@,
-- @ignore_unavailable@, @allow_partial_search_results@,
-- @max_concurrent_shard_requests@); the OpenSearch-only
-- 'Database.Bloodhound.Internal.Versions.Common.Types.PointInTime.pitoAllowPartialPITCreation'
-- field is silently dropped by this builder. Pass
-- 'Database.Bloodhound.Internal.Versions.Common.Types.PointInTime.defaultPITOptions'
-- to reproduce the wire shape of 'openPointInTime'. To send an
-- @index_filter@ body, use 'openPointInTimeWithBody'.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/point-in-time-api.html>.
openPointInTimeWith ::
  IndexPattern ->
  KeepAlive ->
  PITOptions ->
  BHRequest StatusDependant (ParsedEsResponse OpenPointInTimeResponse)
openPointInTimeWith indexPattern keepAlive opts =
  withBHResponseParsedEsResponse $
    post @StatusDependant endpoint emptyBody
  where
    endpoint =
      [unIndexPattern indexPattern, "_pit"]
        `withQueries` (("keep_alive", Just (keepAliveToText keepAlive)) : pitOptionsParams opts)

-- | 'openPointInTimeWithBody' is the body-carrying variant of
-- 'openPointInTimeWith' on Elasticsearch 9: in addition to the
-- 'PITOptions' URI parameters (forwarded exactly as in
-- 'openPointInTimeWith') and the mandatory @keep_alive@, it sends the
-- supplied 'OpenPointInTimeBody' as the JSON request body. This is the
-- only way to supply an @index_filter@ query, which filters indices out
-- of the PIT when it rewrites to @match_none@ on every shard. The
-- 'IndexPattern' target follows the same rules as 'openPointInTimeWith'
-- (single name, comma-list, or wildcard). Pass
-- 'defaultOpenPointInTimeBody' to send an empty (@{}@) body.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/point-in-time-api.html>.
openPointInTimeWithBody ::
  IndexPattern ->
  KeepAlive ->
  OpenPointInTimeBody ->
  PITOptions ->
  BHRequest StatusDependant (ParsedEsResponse OpenPointInTimeResponse)
openPointInTimeWithBody indexPattern keepAlive body opts =
  withBHResponseParsedEsResponse $
    post @StatusDependant endpoint (encode body)
  where
    endpoint =
      [unIndexPattern indexPattern, "_pit"]
        `withQueries` (("keep_alive", Just (keepAliveToText keepAlive)) : pitOptionsParams opts)

-- | 'closePointInTime' closes a point in time given a 'ClosePointInTime'.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/point-in-time-api.html>.
closePointInTime ::
  ClosePointInTime ->
  BHRequest StatusDependant (ParsedEsResponse ClosePointInTimeResponse)
closePointInTime q =
  withBHResponseParsedEsResponse $
    deleteWithBody @StatusDependant ["_pit"] (encode q)

-- | 'esql' builds the 'BHRequest' for the ES|QL @POST /_query@ endpoint
-- (Elasticsearch 9.x). The body is the encoded ES9 'ESQLRequest', which is a
-- superset of the ES8 wire shape: it additionally carries the ES9-only
-- @time_zone@ and @include_execution_metadata@ fields when set. The response
-- is parsed into 'ESQLResult'.
--
-- Equivalent to @'esqlWith' req 'defaultESQLQueryOptions'@ — emits no
-- query string.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-esql-query>.
esql ::
  ESQLRequest ->
  BHRequest StatusDependant (ParsedEsResponse ESQLResult)
esql = flip esqlWith defaultESQLQueryOptions

-- | 'esqlWith' builds the 'BHRequest' for the ES|QL @POST /_query@
-- endpoint on Elasticsearch 9 with the documented URI query parameters
-- ('ESQLQueryOptions'). The body is the encoded ES9 'ESQLRequest'; the
-- response is parsed into 'ESQLResult'.
--
-- Pass 'defaultESQLQueryOptions' to emit no query string (identical
-- wire shape to 'esql').
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-esql-query>.
esqlWith ::
  ESQLRequest ->
  ESQLQueryOptions ->
  BHRequest StatusDependant (ParsedEsResponse ESQLResult)
esqlWith req opts =
  withBHResponseParsedEsResponse $
    post @StatusDependant endpoint (encode req)
  where
    endpoint =
      mkEndpoint ["_query"]
        `withQueries` esqlOptionsParams opts

-- | 'esqlAsync' builds the 'BHRequest' for the async ES|QL
-- @POST /_query\/async@ endpoint on Elasticsearch 9. The body is the
-- encoded 'AsyncESQLRequest' (an ES9 'ESQLRequest' plus the async-only
-- @wait_for_completion_timeout@, @keep_alive@ and @keep_on_completion@
-- body fields).
--
-- Equivalent to @'esqlAsyncWith' req 'defaultESQLQueryOptions'@ — emits
-- no query string.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-esql-async-query>.
esqlAsync ::
  AsyncESQLRequest ->
  BHRequest StatusDependant (ParsedEsResponse AsyncESQLResult)
esqlAsync = flip esqlAsyncWith defaultESQLQueryOptions

-- | 'esqlAsyncWith' builds the 'BHRequest' for the async ES|QL
-- @POST /_query\/async@ endpoint on Elasticsearch 9 with the documented
-- URI query parameters. The body is the encoded 'AsyncESQLRequest'; the
-- response is parsed into 'AsyncESQLResult'.
--
-- Pass 'defaultESQLQueryOptions' to emit no query string (identical
-- wire shape to 'esqlAsync').
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-esql-async-query>.
esqlAsyncWith ::
  AsyncESQLRequest ->
  ESQLQueryOptions ->
  BHRequest StatusDependant (ParsedEsResponse AsyncESQLResult)
esqlAsyncWith req opts =
  withBHResponseParsedEsResponse $
    post @StatusDependant endpoint (encode req)
  where
    endpoint =
      mkEndpoint ["_query", "async"]
        `withQueries` esqlOptionsParams opts

-- | 'getAsyncESQL' builds the 'BHRequest' for
-- @GET /_query\/async\/{id}@ on Elasticsearch 9. The wire format is
-- identical to ES8, so the ES8 request builder is reused verbatim.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-async.html>.
getAsyncESQL ::
  AsyncESQLId ->
  Maybe Text ->
  BHRequest StatusDependant (ParsedEsResponse AsyncESQLResult)
getAsyncESQL = Requests8.getAsyncESQL

-- | 'getAsyncESQLWith' is the fully-parameterised form of
-- 'getAsyncESQL' on Elasticsearch 9. The wire format is identical to
-- ES8, so the ES8 request builder is reused verbatim.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-async.html>.
getAsyncESQLWith ::
  AsyncESQLId ->
  GetAsyncESQLOptions ->
  BHRequest StatusDependant (ParsedEsResponse AsyncESQLResult)
getAsyncESQLWith = Requests8.getAsyncESQLWith

-- | 'deleteAsyncESQL' builds the 'BHRequest' for
-- @DELETE /_query\/async\/{id}@ on Elasticsearch 9. The wire format is
-- identical to ES8, so the ES8 request builder is reused verbatim.
-- Like the ES8 builder, this is 'StatusDependant': deleting a
-- non-existent or already-purged async id surfaces as an 'EsError';
-- wrap with 'tryPerformBHRequest' for miss-tolerant deletion.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-async.html>.
deleteAsyncESQL ::
  AsyncESQLId ->
  BHRequest StatusDependant Acknowledged
deleteAsyncESQL = Requests8.deleteAsyncESQL

-- | 'stopAsyncESQL' builds the 'BHRequest' for
-- @POST /_query\/async\/{id}\/stop@ (Elasticsearch 8.11+) on
-- Elasticsearch 9. The wire format is identical to ES8, so the ES8
-- request builder is reused verbatim.
--
-- For more information see
-- <https://www.elastic.co/docs/reference/elasticsearch/rest-apis/esql-async-api>.
stopAsyncESQL ::
  AsyncESQLId ->
  BHRequest StatusDependant (ParsedEsResponse AsyncESQLResult)
stopAsyncESQL = Requests8.stopAsyncESQL

-- | 'putESQLView' builds the 'BHRequest' for
-- @PUT \/_query\/view\/{name}@ (Elasticsearch 9.4+, experimental),
-- which creates or replaces an ES|QL view — a stored, named ES|QL
-- query string that can be referenced from other queries via
-- @FROM <view_name>@. The body is a single required @query@ field;
-- the response is the shared 'Acknowledged' wrapper
-- (@{\"acknowledged\": true\}@).
--
-- This endpoint does not exist on Elasticsearch 8.x (it returns a
-- @404@ against any ES8 cluster), so the canonical builder lives here
-- in the ES9 module rather than in
-- "Database.Bloodhound.ElasticSearch8.Requests".
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-esql-put-view>.
putESQLView ::
  ESQLViewName ->
  Text ->
  BHRequest StatusDependant Acknowledged
putESQLView viewName query =
  put @StatusDependant endpoint (encode (object ["query" .= query]))
  where
    endpoint = mkEndpoint ["_query", "view", unESQLViewName viewName]

-- | 'getESQLView' builds the 'BHRequest' for
-- @GET \/_query\/view\/{name}@ (Elasticsearch 9.4+, experimental),
-- which returns the stored 'ESQLView' — its @name@ (echoed from the
-- path) and @query@. A @404@ for a missing view surfaces as an
-- 'EsError'; wrap with 'tryPerformBHRequest' for miss-tolerant reads.
--
-- This endpoint does not exist on Elasticsearch 8.x, so the canonical
-- builder lives here in the ES9 module.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-esql-get-view>.
getESQLView ::
  ESQLViewName ->
  BHRequest StatusDependant ESQLView
getESQLView viewName =
  get @StatusDependant endpoint
  where
    endpoint = mkEndpoint ["_query", "view", unESQLViewName viewName]

-- | 'deleteESQLView' builds the 'BHRequest' for
-- @DELETE \/_query\/view\/{name}@ (Elasticsearch 9.4+, experimental),
-- which removes an ES|QL view. Returns 'Acknowledged' on success.
-- Deleting a non-existent view surfaces as an 'EsError'; wrap with
-- 'tryPerformBHRequest' for miss-tolerant deletion.
--
-- This endpoint does not exist on Elasticsearch 8.x, so the canonical
-- builder lives here in the ES9 module.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-esql-delete-view>.
deleteESQLView ::
  ESQLViewName ->
  BHRequest StatusDependant Acknowledged
deleteESQLView viewName =
  delete (mkEndpoint ["_query", "view", unESQLViewName viewName])

-- | 'getESQLQuery' builds the 'BHRequest' for
-- @GET \/_query\/queries\/{id}@ (Elasticsearch 9.1+, experimental),
-- which returns information about a currently-running ES|QL query —
-- its numeric task id, the node running it, start time and running
-- time, the query source, and the coordinating\/data nodes involved.
--
-- The @id@ path segment is the same encoded async-id string returned
-- by @POST \/_query\/async@ (wrapped as 'AsyncESQLId' here); the
-- response's numeric @id@ field is the underlying task identifier, not
-- the encoded string. A query that has already completed and been
-- purged surfaces as a 500 'EsError'; callers typically use this
-- endpoint to inspect a specific query discovered via 'getESQLQueries'.
--
-- This endpoint does not exist on Elasticsearch 8.x, so the canonical
-- builder lives here in the ES9 module.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-esql-get-query>.
getESQLQuery ::
  AsyncESQLId ->
  BHRequest StatusDependant ESQLQueryInfo
getESQLQuery (AsyncESQLId queryId) =
  get @StatusDependant endpoint
  where
    endpoint = mkEndpoint ["_query", "queries", queryId]

-- | 'getESQLQueries' builds the 'BHRequest' for
-- @GET \/_query\/queries@ (Elasticsearch 9.1+, experimental), the
-- list-all sibling of 'getESQLQuery'. It returns information about every
-- currently-running ES|QL query.
--
-- The response is a JSON object keyed by each query's encoded async-id
-- (the same string 'AsyncESQLId' wraps); each value carries the
-- 'ESQLQueryInfo' for that query. The decoder flattens this into
-- @[(AsyncESQLId, ESQLQueryInfo)]@ so the caller keeps the id it needs to
-- subsequently 'getESQLQuery', 'stopAsyncESQL' or 'deleteAsyncESQL' a
-- listed query.
--
-- This endpoint does not exist on Elasticsearch 8.x, so the canonical
-- builder lives here in the ES9 module.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-esql-list-queries>.
getESQLQueries ::
  BHRequest StatusDependant [(AsyncESQLId, ESQLQueryInfo)]
getESQLQueries =
  unESQLQueryListResponse <$> get @StatusDependant endpoint
  where
    endpoint = mkEndpoint ["_query", "queries"]

-- | 'putInferenceEndpoint' builds the 'BHRequest' for
-- @PUT \/_inference\/{task_type}\/{inference_id}@ on Elasticsearch 9. The wire
-- format is identical to ES8, so the ES8 request builder is reused verbatim.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/inference-apis.html>.
putInferenceEndpoint ::
  TaskType ->
  InferenceId ->
  InferenceConfig ->
  BHRequest StatusDependant (ParsedEsResponse InferencePutResponse)
putInferenceEndpoint = Requests8.putInferenceEndpoint

-- | 'putInferenceEndpointWith' is the fully-parameterised form of
-- 'putInferenceEndpoint' on Elasticsearch 9. The wire format is identical
-- to ES8, so the ES8 request builder is reused verbatim. See
-- 'Requests8.putInferenceEndpointWith' for the semantics of the @timeout@
-- query parameter.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/inference-apis.html>.
putInferenceEndpointWith ::
  TaskType ->
  InferenceId ->
  InferenceConfig ->
  PutInferenceOptions ->
  BHRequest StatusDependant (ParsedEsResponse InferencePutResponse)
putInferenceEndpointWith = Requests8.putInferenceEndpointWith

-- | 'updateInferenceEndpoint' builds the 'BHRequest' for
-- @PUT \/_inference\/{task_type}\/{inference_id}\/_update@ on Elasticsearch 9.
-- The wire format is identical to ES8, so the ES8 request builder is reused
-- verbatim.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-update>.
updateInferenceEndpoint ::
  TaskType ->
  InferenceId ->
  InferenceConfig ->
  BHRequest StatusDependant (ParsedEsResponse InferenceInfo)
updateInferenceEndpoint = Requests8.updateInferenceEndpoint

-- | 'getInferenceEndpoints' builds the 'BHRequest' for the
-- @GET \/_inference@ family on Elasticsearch 9. The wire format is
-- identical to ES8, so the ES8 request builder is reused verbatim.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/get-inference-api.html>.
getInferenceEndpoints ::
  Maybe TaskType ->
  Maybe InferenceId ->
  BHRequest StatusDependant [InferenceInfo]
getInferenceEndpoints = Requests8.getInferenceEndpoints

-- | 'deleteInferenceEndpoint' builds the 'BHRequest' for
-- @DELETE \/_inference\/{task_type}\/{inference_id}@ on Elasticsearch 9. The
-- wire format is identical to ES8, so the ES8 request builder is reused
-- verbatim.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/delete-inference-api.html>.
deleteInferenceEndpoint ::
  TaskType ->
  InferenceId ->
  BHRequest StatusDependant Acknowledged
deleteInferenceEndpoint = Requests8.deleteInferenceEndpoint

-- | 'deleteInferenceEndpointWith' is the fully-parameterised form of
-- 'deleteInferenceEndpoint' on Elasticsearch 9. The wire format is identical
-- to ES8, so the ES8 request builder is reused verbatim. See
-- 'Requests8.deleteInferenceEndpointWith' for the semantics of the
-- @dry_run@ and @force@ query parameters.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/delete-inference-api.html>.
deleteInferenceEndpointWith ::
  TaskType ->
  InferenceId ->
  DeleteInferenceOptions ->
  BHRequest StatusDependant Acknowledged
deleteInferenceEndpointWith = Requests8.deleteInferenceEndpointWith

-- | 'runInference' builds the 'BHRequest' for
-- @POST \/_inference\/{task_type}\/{inference_id}@ on Elasticsearch 9. The
-- wire format is identical to ES8, so the ES8 request builder is reused.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/inference-apis.html>.
runInference ::
  TaskType ->
  InferenceId ->
  InferenceInput ->
  BHRequest StatusDependant (ParsedEsResponse InferenceResult)
runInference = Requests8.runInference

-- | 'runInferenceWith' is the fully-parameterised form of 'runInference' on
-- Elasticsearch 9. The wire format is identical to ES8, so the ES8 request
-- builder is reused verbatim. See 'Requests8.runInferenceWith' for the
-- semantics of the @timeout@ query parameter.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/inference-apis.html>.
runInferenceWith ::
  TaskType ->
  InferenceId ->
  InferenceInput ->
  RunInferenceOptions ->
  BHRequest StatusDependant (ParsedEsResponse InferenceResult)
runInferenceWith = Requests8.runInferenceWith

-- | 'streamCompletionInference' builds the 'BHRequest' for
-- @POST \/_inference\/completion\/{inference_id}\/_stream@ on Elasticsearch 9.
-- The wire format is identical to ES8, so the ES8 request builder is reused
-- verbatim.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-stream-completion>.
streamCompletionInference ::
  InferenceId ->
  InferenceInput ->
  BHRequest StatusDependant L.ByteString
streamCompletionInference = Requests8.streamCompletionInference

-- | 'streamCompletionInferenceWith' is the fully-parameterised form of
-- 'streamCompletionInference' on Elasticsearch 9. The wire format is identical
-- to ES8, so the ES8 request builder is reused verbatim. See
-- 'Requests8.streamCompletionInferenceWith' for the semantics of the @timeout@
-- query parameter.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-stream-completion>.
streamCompletionInferenceWith ::
  InferenceId ->
  InferenceInput ->
  StreamCompletionInferenceOptions ->
  BHRequest StatusDependant L.ByteString
streamCompletionInferenceWith = Requests8.streamCompletionInferenceWith

-- | 'streamChatCompletionInference' builds the 'BHRequest' for
-- @POST \/_inference\/chat_completion\/{inference_id}\/_stream@ on
-- Elasticsearch 9. The wire format is identical to ES8, so the ES8 request
-- builder is reused verbatim.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-chat-completion-unified>.
streamChatCompletionInference ::
  InferenceId ->
  ChatCompletionRequest ->
  BHRequest StatusDependant L.ByteString
streamChatCompletionInference = Requests8.streamChatCompletionInference

-- | 'streamChatCompletionInferenceWith' is the fully-parameterised form of
-- 'streamChatCompletionInference' on Elasticsearch 9. The wire format is
-- identical to ES8, so the ES8 request builder is reused verbatim. See
-- 'Requests8.streamChatCompletionInferenceWith' for the semantics of the
-- @timeout@ query parameter.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-chat-completion-unified>.
streamChatCompletionInferenceWith ::
  InferenceId ->
  ChatCompletionRequest ->
  StreamChatCompletionInferenceOptions ->
  BHRequest StatusDependant L.ByteString
streamChatCompletionInferenceWith = Requests8.streamChatCompletionInferenceWith

-- | 'putDataStreamLifecycle' builds the 'BHRequest' for
-- @PUT /_data_stream\/{name}/_lifecycle@ on Elasticsearch 9. The wire
-- format is identical to ES8, so the ES8 request builder is reused
-- verbatim.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/data-stream-lifecycle.html#put-data-stream-lifecycle>.
putDataStreamLifecycle ::
  DataStreamName ->
  DataStreamLifecycle ->
  BHRequest StatusDependant Acknowledged
putDataStreamLifecycle = Requests8.putDataStreamLifecycle

-- | 'putDataStreamsLifecycle' builds the 'BHRequest' for the bulk
-- @PUT /_data_stream/_lifecycle@ on Elasticsearch 9. The wire format
-- is identical to ES8, so the ES8 request builder is reused verbatim.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/data-stream-lifecycle.html#put-data-streams-lifecycle>.
putDataStreamsLifecycle ::
  PutDataStreamsLifecycleRequest ->
  BHRequest StatusDependant Acknowledged
putDataStreamsLifecycle = Requests8.putDataStreamsLifecycle

-- | 'getDataStreamLifecycle' builds the 'BHRequest' for
-- @GET /_data_stream\/{name}/_lifecycle@ on Elasticsearch 9. The wire
-- format is identical to ES8, so the ES8 request builder is reused
-- verbatim.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/data-stream-lifecycle.html#get-data-stream-lifecycle>.
getDataStreamLifecycle ::
  Maybe [DataStreamName] ->
  BHRequest StatusDependant GetDataStreamLifecyclesResponse
getDataStreamLifecycle = Requests8.getDataStreamLifecycle

-- | 'deleteDataStreamLifecycle' builds the 'BHRequest' for
-- @DELETE /_data_stream\/{name}/_lifecycle@ on Elasticsearch 9. The
-- wire format is identical to ES8, so the ES8 request builder is
-- reused verbatim.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/data-stream-lifecycle.html#delete-data-stream-lifecycle>.
deleteDataStreamLifecycle ::
  DataStreamName ->
  BHRequest StatusDependant Acknowledged
deleteDataStreamLifecycle = Requests8.deleteDataStreamLifecycle

-- | 'getDataStreamOptions' builds the 'BHRequest' for
-- @GET /_data_stream\/{name}/_options@ on Elasticsearch 9. The wire
-- format is identical to ES8, so the ES8 request builder is reused
-- verbatim.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-indices-get-data-stream-options>.
getDataStreamOptions ::
  Maybe [DataStreamName] ->
  BHRequest StatusDependant GetDataStreamOptionsResponse
getDataStreamOptions = Requests8.getDataStreamOptions

-- | 'updateDataStreamOptions' builds the 'BHRequest' for
-- @PUT /_data_stream\/{name}/_options@ on Elasticsearch 9. The wire
-- format is identical to ES8, so the ES8 request builder is reused
-- verbatim.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-indices-put-data-stream-options>.
updateDataStreamOptions ::
  Maybe [DataStreamName] ->
  UpdateDataStreamOptionsRequest ->
  BHRequest StatusDependant Acknowledged
updateDataStreamOptions = Requests8.updateDataStreamOptions

-- | 'deleteDataStreamOptions' builds the 'BHRequest' for
-- @DELETE /_data_stream\/{name}/_options@ on Elasticsearch 9. The wire
-- format is identical to ES8, so the ES8 request builder is reused
-- verbatim.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-indices-delete-data-stream-options>.
deleteDataStreamOptions ::
  Maybe [DataStreamName] ->
  BHRequest StatusDependant Acknowledged
deleteDataStreamOptions = Requests8.deleteDataStreamOptions

-- $dataStreamLifecycleStatsAndExplain
--
-- /Data Stream Lifecycle Stats and Explain/ are available on ES 9.x
-- (and ES 8.11+\/8.12+). The wire format is identical across versions,
-- so the ES8 request builders are reused verbatim.

-- | 'getDataStreamLifecycleStats' builds the 'BHRequest' for
-- @GET /_lifecycle/stats@ on Elasticsearch 9. The wire format is
-- identical to ES8, so the ES8 request builder is reused verbatim.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-indices-get-data-lifecycle-stats>.
getDataStreamLifecycleStats ::
  BHRequest StatusDependant DataStreamLifecycleStats
getDataStreamLifecycleStats = Requests8.getDataStreamLifecycleStats

-- | 'explainDataStreamLifecycle' builds the 'BHRequest' for
-- @GET /{index}/_lifecycle/explain@ on Elasticsearch 9. The wire
-- format is identical to ES8, so the ES8 request builder is reused
-- verbatim.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-indices-explain-data-lifecycle>.
explainDataStreamLifecycle ::
  Maybe [IndexName] ->
  BHRequest StatusDependant ExplainDataStreamLifecycleResponse
explainDataStreamLifecycle = Requests8.explainDataStreamLifecycle

-- | 'explainDataStreamLifecycleWith' is the fully-parameterised form
-- of 'explainDataStreamLifecycle'. The wire format is identical to
-- ES8, so the ES8 request builder is reused verbatim.
explainDataStreamLifecycleWith ::
  Maybe [IndexName] ->
  ExplainDataStreamLifecycleOptions ->
  BHRequest StatusDependant ExplainDataStreamLifecycleResponse
explainDataStreamLifecycleWith = Requests8.explainDataStreamLifecycleWith

-- $dataStreamMappings
--
-- /Data Stream Mappings/ (ES 9.1+ for GET, 9.2+ for PUT) expose and
-- override the mapping configuration at the data-stream level. The
-- endpoints live under @/_data_stream\/{name}/_mappings@ (note the
-- plural @_mappings@ segment). These are ES9-new endpoints; the
-- request builders are defined here rather than delegated to ES8.

-- | Render 'GetDataStreamMappingsOptions' as a list of @(key, value)@
-- query parameters suitable for 'withQueries'. 'Nothing' fields are
-- omitted.
getDataStreamMappingsOptionsParams :: GetDataStreamMappingsOptions -> [(Text, Maybe Text)]
getDataStreamMappingsOptionsParams opts =
  catMaybes
    [ ("master_timeout",) . Just <$> getDataStreamMappingsOptionsMasterTimeout opts
    ]

-- | 'getDataStreamMappings' retrieves the mapping configuration of
-- one or more data streams. Equivalent to
-- @'getDataStreamMappingsWith' names 'defaultGetDataStreamMappingsOptions'@.
--
-- * @'Nothing'@ or @'Just' []@  → @GET /_data_stream/_mappings@
--   returns mappings for every data stream on the cluster.
-- * @'Just' names@              → @GET /_data_stream\/{a,b,c}/_mappings@
--   returns only the mappings of the named data streams (comma-joined
--   path segment). Wildcards (@*@) are accepted by the server.
--
-- See
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-indices-get-data-stream-mappings>.
getDataStreamMappings ::
  Maybe [DataStreamName] ->
  BHRequest StatusDependant GetDataStreamMappingsResponse
getDataStreamMappings names =
  getDataStreamMappingsWith names defaultGetDataStreamMappingsOptions

-- | 'getDataStreamMappingsWith' is the fully-parameterised form of
-- 'getDataStreamMappings'. Pass 'defaultGetDataStreamMappingsOptions'
-- to reproduce a parameterless call.
getDataStreamMappingsWith ::
  Maybe [DataStreamName] ->
  GetDataStreamMappingsOptions ->
  BHRequest StatusDependant GetDataStreamMappingsResponse
getDataStreamMappingsWith mNames opts =
  get @StatusDependant (endpoint `withQueries` getDataStreamMappingsOptionsParams opts)
  where
    endpoint = renderGetDataStreamNameEndpoint mNames "_mappings"

-- | 'putDataStreamMappings' updates the mapping configuration of one
-- or more data streams. Equivalent to
-- @'putDataStreamMappingsWith' names mapping 'defaultUpdateDataStreamMappingsOptions'@.
-- The body is any 'ToJSON'able mapping object (the ES mapping schema
-- is open-ended); see 'GetDataStreamMappingsEntry' for the response
-- shape.
--
-- /CAUTION/: when given @'Nothing'@ or @'Just' []@, the builder
-- substitutes the wildcard @*@ for the @{name}@ path segment, so the
-- mapping override is applied to /every/ data stream on the cluster.
-- Pass an explicit 'DataStreamName' list if you want to scope the
-- update.
--
-- The override takes precedence over the template's mappings and is
-- applied to the write index on the next rollover (no existing
-- backing indices are changed).
--
-- See
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-indices-put-data-stream-mappings>.
putDataStreamMappings ::
  (ToJSON mapping) =>
  Maybe [DataStreamName] ->
  mapping ->
  BHRequest StatusDependant UpdateDataStreamMappingsResponse
putDataStreamMappings names mapping =
  putDataStreamMappingsWith names mapping defaultUpdateDataStreamMappingsOptions

-- | 'putDataStreamMappingsWith' is the fully-parameterised form of
-- 'putDataStreamMappings'. Pass
-- 'defaultUpdateDataStreamMappingsOptions' to reproduce a
-- parameterless call. The @dry_run@ option simulates the update
-- without applying it; the response carries the mappings that /would/
-- result from the change.
putDataStreamMappingsWith ::
  (ToJSON mapping) =>
  Maybe [DataStreamName] ->
  mapping ->
  UpdateDataStreamMappingsOptions ->
  BHRequest StatusDependant UpdateDataStreamMappingsResponse
putDataStreamMappingsWith mNames mapping opts =
  put @StatusDependant (endpoint `withQueries` updateDataStreamMappingsOptionsParams opts) (encode mapping)
  where
    endpoint = renderPutDataStreamNameEndpoint mNames "_mappings"

-- | Render 'UpdateDataStreamMappingsOptions' as a list of
-- @(key, value)@ query parameters. 'Nothing' fields are omitted;
-- booleans render as @"true"@\/@"false"@.
updateDataStreamMappingsOptionsParams :: UpdateDataStreamMappingsOptions -> [(Text, Maybe Text)]
updateDataStreamMappingsOptionsParams opts =
  catMaybes
    [ ("dry_run",) . Just . boolQP <$> updateDataStreamMappingsOptionsDryRun opts,
      ("master_timeout",) . Just <$> updateDataStreamMappingsOptionsMasterTimeout opts,
      ("timeout",) . Just <$> updateDataStreamMappingsOptionsTimeout opts
    ]
  where
    boolQP True = "true"
    boolQP False = "false"

-- $dataStreamSettings
--
-- /Data Stream Settings/ (ES 9.1+ for GET and PUT; PUT also
-- documented as available in 8.19) expose and override the
-- index-settings configuration at the data-stream level. The
-- endpoints live under @/_data_stream\/{name}/_settings@.

-- | Render 'GetDataStreamSettingsOptions' as a list of @(key, value)@
-- query parameters. 'Nothing' fields are omitted.
getDataStreamSettingsOptionsParams :: GetDataStreamSettingsOptions -> [(Text, Maybe Text)]
getDataStreamSettingsOptionsParams opts =
  catMaybes
    [ ("master_timeout",) . Just <$> getDataStreamSettingsOptionsMasterTimeout opts
    ]

-- | 'getDataStreamSettings' retrieves the settings configuration of
-- one or more data streams. Equivalent to
-- @'getDataStreamSettingsWith' names 'defaultGetDataStreamSettingsOptions'@.
--
-- * @'Nothing'@ or @'Just' []@  → @GET /_data_stream/_settings@
-- * @'Just' names@              → @GET /_data_stream\/{a,b,c}/_settings@
--
-- /Numeric-as-string/: ES returns numeric settings values as JSON
-- strings inside the @settings@ object; the opaque 'Value' preserves
-- them verbatim.
--
-- See
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-indices-get-data-stream-settings>.
getDataStreamSettings ::
  Maybe [DataStreamName] ->
  BHRequest StatusDependant GetDataStreamSettingsResponse
getDataStreamSettings names =
  getDataStreamSettingsWith names defaultGetDataStreamSettingsOptions

-- | 'getDataStreamSettingsWith' is the fully-parameterised form of
-- 'getDataStreamSettings'.
getDataStreamSettingsWith ::
  Maybe [DataStreamName] ->
  GetDataStreamSettingsOptions ->
  BHRequest StatusDependant GetDataStreamSettingsResponse
getDataStreamSettingsWith mNames opts =
  get @StatusDependant (endpoint `withQueries` getDataStreamSettingsOptionsParams opts)
  where
    endpoint = renderGetDataStreamNameEndpoint mNames "_settings"

-- | 'putDataStreamSettings' updates the settings configuration of one
-- or more data streams. Equivalent to
-- @'putDataStreamSettingsWith' names settings 'defaultUpdateDataStreamSettingsOptions'@.
-- The body is any 'ToJSON'able settings object (flat dotted keys like
-- @"index.lifecycle.name"@ are accepted alongside nested objects).
--
-- /CAUTION/: when given @'Nothing'@ or @'Just' []@, the builder
-- substitutes the wildcard @*@ for the @{name}@ path segment, so the
-- settings override is applied to /every/ data stream on the cluster.
-- Pass an explicit 'DataStreamName' list if you want to scope the
-- update.
--
-- See
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-indices-put-data-stream-settings>.
putDataStreamSettings ::
  (ToJSON settings) =>
  Maybe [DataStreamName] ->
  settings ->
  BHRequest StatusDependant UpdateDataStreamSettingsResponse
putDataStreamSettings names settings =
  putDataStreamSettingsWith names settings defaultUpdateDataStreamSettingsOptions

-- | 'putDataStreamSettingsWith' is the fully-parameterised form of
-- 'putDataStreamSettings'. Pass
-- 'defaultUpdateDataStreamSettingsOptions' to reproduce a
-- parameterless call.
putDataStreamSettingsWith ::
  (ToJSON settings) =>
  Maybe [DataStreamName] ->
  settings ->
  UpdateDataStreamSettingsOptions ->
  BHRequest StatusDependant UpdateDataStreamSettingsResponse
putDataStreamSettingsWith mNames settings opts =
  put @StatusDependant (endpoint `withQueries` updateDataStreamSettingsOptionsParams opts) (encode settings)
  where
    endpoint = renderPutDataStreamNameEndpoint mNames "_settings"

-- | Render 'UpdateDataStreamSettingsOptions' as a list of
-- @(key, value)@ query parameters. 'Nothing' fields are omitted;
-- booleans render as @"true"@\/@"false"@.
updateDataStreamSettingsOptionsParams :: UpdateDataStreamSettingsOptions -> [(Text, Maybe Text)]
updateDataStreamSettingsOptionsParams opts =
  catMaybes
    [ ("dry_run",) . Just . boolQP <$> updateDataStreamSettingsOptionsDryRun opts,
      ("master_timeout",) . Just <$> updateDataStreamSettingsOptionsMasterTimeout opts,
      ("timeout",) . Just <$> updateDataStreamSettingsOptionsTimeout opts
    ]
  where
    boolQP True = "true"
    boolQP False = "false"

-- | Shared path builder for the GET @/_data_stream\/{name}/_<suffix>@
-- endpoints (mappings, settings). When given @'Nothing'@ or
-- @'Just' []@, the @{name}@ segment is omitted entirely (yielding
-- @/_data_stream/_<suffix>@), matching 'getDataStreamOptions'. Pass
-- an explicit name list (which may include the wildcard
-- @'DataStreamName \"*\"'@) to scope the response.
renderGetDataStreamNameEndpoint ::
  Maybe [DataStreamName] ->
  Text ->
  Endpoint
renderGetDataStreamNameEndpoint mNames suffix = case mNames of
  Nothing -> ["_data_stream", suffix]
  Just [] -> ["_data_stream", suffix]
  Just (first : rest) ->
    ["_data_stream", T.intercalate "," (renderName <$> (first : rest)), suffix]
  where
    renderName (DataStreamName n) = n

-- | Shared path builder for the PUT @/_data_stream\/{name}/_<suffix>@
-- endpoints (mappings, settings). The ES API requires the @{name}@
-- segment on PUT, so when given @'Nothing'@ or @'Just' []@ the
-- wildcard @*@ is substituted (cluster-wide fan-out) — matching
-- 'updateDataStreamOptions'. Pass an explicit 'DataStreamName' list
-- if you want to scope the update.
renderPutDataStreamNameEndpoint ::
  Maybe [DataStreamName] ->
  Text ->
  Endpoint
renderPutDataStreamNameEndpoint mNames suffix = case mNames of
  Nothing -> ["_data_stream", "*", suffix]
  Just [] -> ["_data_stream", "*", suffix]
  Just (first : rest) ->
    ["_data_stream", T.intercalate "," (renderName <$> (first : rest)), suffix]
  where
    renderName (DataStreamName n) = n

-- | 'eqlSearch' builds the 'BHRequest' for the EQL
-- @POST /{index}/_eql/search@ endpoint on Elasticsearch 9. The wire
-- format is identical to ES 7.10+\/8.x, so the ES8 request builder is
-- reused verbatim.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/eql-search-api.html>.
eqlSearch ::
  (FromJSON a) =>
  IndexName ->
  EQLRequest ->
  BHRequest StatusDependant (ParsedEsResponse (EQLResult a))
eqlSearch = Requests8.eqlSearch

-- | 'eqlSearchWith' is the fully-parameterised form of 'eqlSearch' on
-- Elasticsearch 9. The wire format is identical to ES 7.10+\/8.x, so the
-- ES8 request builder is reused verbatim. See 'Requests8.eqlSearchWith'
-- for the parameter semantics.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/eql-search-api.html>.
eqlSearchWith ::
  (FromJSON a) =>
  IndexName ->
  EQLSearchOptions ->
  EQLRequest ->
  BHRequest StatusDependant (ParsedEsResponse (EQLResult a))
eqlSearchWith = Requests8.eqlSearchWith

-- | 'getEQLSearch' builds the 'BHRequest' for the async EQL
-- @GET /_eql/search\/{id}@ endpoint on Elasticsearch 9. The wire format
-- is identical to ES 7.10+\/8.x, so the ES8 request builder is reused
-- verbatim.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-eql-get>.
getEQLSearch ::
  (FromJSON a) =>
  EQLSearchId ->
  Maybe Text ->
  BHRequest StatusDependant (ParsedEsResponse (EQLResult a))
getEQLSearch = Requests8.getEQLSearch

-- | 'getEQLStatus' builds the 'BHRequest' for the async EQL status
-- @GET /_eql/search/status\/{id}@ endpoint on Elasticsearch 9. The wire
-- format is identical to ES 7.10+\/8.x, so the ES8 request builder is
-- reused verbatim (which itself delegates to ES7).
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-eql-get-status>.
getEQLStatus ::
  EQLSearchId ->
  BHRequest StatusDependant EQLStatus
getEQLStatus = Requests8.getEQLStatus

-- | 'deleteEQLSearch' builds the 'BHRequest' for the EQL
-- @DELETE /_eql/search/{id}@ endpoint on Elasticsearch 9. The wire
-- format is identical to ES 7.10+, so the ES8 request builder is
-- reused verbatim (which itself delegates to ES7).
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-eql-delete>.
deleteEQLSearch ::
  EQLSearchId ->
  BHRequest StatusIndependant Acknowledged
deleteEQLSearch = Requests8.deleteEQLSearch

-- | 'putQueryRuleset' builds the 'BHRequest' for
-- @PUT \/_query_rules\/{ruleset_id}@ on Elasticsearch 9. The wire
-- format is identical to ES8, so the ES8 request builder is reused
-- verbatim.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/put-query-ruleset.html>.
putQueryRuleset ::
  RulesetId ->
  QueryRuleset ->
  BHRequest StatusDependant QueryRulesetPutResponse
putQueryRuleset = Requests8.putQueryRuleset

-- | 'getQueryRuleset' builds the 'BHRequest' for
-- @GET \/_query_rules\/{ruleset_id}@ on Elasticsearch 9. The wire
-- format is identical to ES8, so the ES8 request builder is reused
-- verbatim.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/get-query-ruleset.html>.
getQueryRuleset ::
  RulesetId ->
  BHRequest StatusDependant QueryRulesetInfo
getQueryRuleset = Requests8.getQueryRuleset

-- | 'deleteQueryRuleset' builds the 'BHRequest' for
-- @DELETE \/_query_rules\/{ruleset_id}@ on Elasticsearch 9. The wire
-- format is identical to ES8, so the ES8 request builder is reused
-- verbatim.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/delete-query-ruleset.html>.
deleteQueryRuleset ::
  RulesetId ->
  BHRequest StatusDependant Acknowledged
deleteQueryRuleset = Requests8.deleteQueryRuleset

-- | 'testQueryRuleset' builds the 'BHRequest' for
-- @POST \/_query_rules\/{ruleset_id}\/_test@ on Elasticsearch 9. The
-- wire format is identical to ES8, so the ES8 request builder is
-- reused verbatim.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/test-query-ruleset.html>.
testQueryRuleset ::
  RulesetId ->
  QueryRulesetTest ->
  BHRequest StatusDependant QueryRulesetTestResponse
testQueryRuleset = Requests8.testQueryRuleset

-- | 'putSearchApplication' builds the 'BHRequest' for
-- @PUT \/_application\/search_application\/{name}@ on Elasticsearch 9.
-- The wire format is identical to ES8, so the ES8 request builder is
-- reused verbatim. The body is a 'SearchApplication' record whose
-- required @indices@ field names the target indices; see
-- "Database.Bloodhound.ElasticSearch8.Requests" for full semantics.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/search-application-apis.html>.
putSearchApplication ::
  SearchApplicationName ->
  SearchApplication ->
  BHRequest StatusDependant SearchApplicationPutResponse
putSearchApplication = Requests8.putSearchApplication

-- | 'putSearchApplicationWith' is the fully-parameterised form of
-- 'putSearchApplication' on Elasticsearch 9. The wire format is
-- identical to ES8, so the ES8 request builder is reused verbatim.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-search-application-put>.
putSearchApplicationWith ::
  SearchApplicationName ->
  SearchApplicationPutOptions ->
  SearchApplication ->
  BHRequest StatusDependant SearchApplicationPutResponse
putSearchApplicationWith = Requests8.putSearchApplicationWith

-- | 'getSearchApplication' builds the 'BHRequest' for
-- @GET \/_application\/search_application\/{name}@ on Elasticsearch 9.
-- The wire format is identical to ES8, so the ES8 request builder is
-- reused verbatim.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/search-application-apis.html>.
getSearchApplication ::
  SearchApplicationName ->
  BHRequest StatusDependant SearchApplicationInfo
getSearchApplication = Requests8.getSearchApplication

-- | 'deleteSearchApplication' builds the 'BHRequest' for
-- @DELETE \/_application\/search_application\/{name}@ on Elasticsearch 9.
-- The wire format is identical to ES8, so the ES8 request builder is
-- reused verbatim.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/search-application-apis.html>.
deleteSearchApplication ::
  SearchApplicationName ->
  BHRequest StatusDependant Acknowledged
deleteSearchApplication = Requests8.deleteSearchApplication

-- | 'searchApplication' builds the 'BHRequest' for
-- @POST \/_application\/search_application\/{name}\/_search@ on
-- Elasticsearch 9. The wire format is identical to ES8, so the ES8
-- request builder is reused verbatim.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/search-application-apis.html>.
searchApplication ::
  (FromJSON a) =>
  SearchApplicationName ->
  Maybe SearchApplicationSearchParams ->
  BHRequest StatusDependant (ParsedEsResponse (SearchResult a))
searchApplication = Requests8.searchApplication

-- | 'searchApplicationWith' is the fully-parameterised form of
-- 'searchApplication' on Elasticsearch 9. The wire format is identical to
-- ES8, so the ES8 request builder is reused verbatim. See
-- 'Requests8.searchApplicationWith' for the semantics of the @typed_keys@
-- query parameter.
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/search-application-apis.html>.
searchApplicationWith ::
  (FromJSON a) =>
  SearchApplicationName ->
  Maybe SearchApplicationSearchParams ->
  SearchApplicationOptions ->
  BHRequest StatusDependant (ParsedEsResponse (SearchResult a))
searchApplicationWith = Requests8.searchApplicationWith

-- | 'listSearchApplications' builds the 'BHRequest' for
-- @GET \/_application\/search_application@ on Elasticsearch 9. The wire
-- format is identical to ES8, so the ES8 request builder is reused
-- verbatim. See 'Requests8.listSearchApplications' for semantics.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-search-application-list>.
listSearchApplications ::
  BHRequest StatusDependant SearchApplicationListResponse
listSearchApplications = Requests8.listSearchApplications

-- | 'listSearchApplicationsWith' is the fully-parameterised form of
-- 'listSearchApplications' on Elasticsearch 9. The wire format is
-- identical to ES8, so the ES8 request builder is reused verbatim. See
-- 'Requests8.listSearchApplicationsWith' for the semantics of the
-- @q@\/@from@\/@size@ query parameters.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-search-application-list>.
listSearchApplicationsWith ::
  SearchApplicationListOptions ->
  BHRequest StatusDependant SearchApplicationListResponse
listSearchApplicationsWith = Requests8.listSearchApplicationsWith

-- | 'renderSearchApplicationQuery' builds the 'BHRequest' for
-- @POST \/_application\/search_application\/{name}\/_render_query@ on
-- Elasticsearch 9. The wire format is identical to ES8, so the ES8
-- request builder is reused verbatim. See
-- 'Requests8.renderSearchApplicationQuery' for semantics.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-search-application-render-query>.
renderSearchApplicationQuery ::
  SearchApplicationName ->
  Maybe SearchApplicationSearchParams ->
  BHRequest StatusDependant Value
renderSearchApplicationQuery = Requests8.renderSearchApplicationQuery

-- | 'getTermsEnum' builds the 'BHRequest' for the terms enum
-- @GET \/{index}\/_terms_enum@ endpoint on Elasticsearch 9. The wire
-- format is identical to ES 7.10+\/8.x, so the ES8 request builder is
-- reused verbatim (which itself delegates to ES7).
--
-- For more information see
-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/search-terms-enum.html>.
getTermsEnum ::
  Maybe [IndexName] ->
  FieldName ->
  Maybe Text ->
  BHRequest StatusDependant TermsEnumResponse
getTermsEnum = Requests8.getTermsEnum

-- | 'getTermsEnumWith' is the fully-parameterised variant of
-- 'getTermsEnum' on Elasticsearch 9. The wire format is identical to
-- ES 7.10+\/8.x, so the ES8 request builder is reused verbatim.
getTermsEnumWith ::
  Maybe [IndexName] ->
  TermsEnumOptions ->
  TermsEnumRequest ->
  BHRequest StatusDependant TermsEnumResponse
getTermsEnumWith = Requests8.getTermsEnumWith

-- | 'getStreamsStatus' builds the 'BHRequest' for
-- @GET /_streams/status@ (Elasticsearch 9.1+, experimental), which
-- returns the enabled state of every named stream (e.g. @logs@,
-- @logs.otel@, @logs.ecs@). The response is decoded into a
-- 'StreamsStatusResponse' (a 'Map' from stream name to 'StreamStatus').
-- Equivalent to @'getStreamsStatusWith' 'defaultGetStreamsStatusOptions'@
-- — emits no query string.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-streams-status>.
getStreamsStatus ::
  BHRequest StatusDependant StreamsStatusResponse
getStreamsStatus = getStreamsStatusWith defaultGetStreamsStatusOptions

-- | 'getStreamsStatusWith' is the fully-parameterised variant of
-- 'getStreamsStatus', forwarding the @master_timeout@ query parameter
-- via 'GetStreamsStatusOptions'.
getStreamsStatusWith ::
  GetStreamsStatusOptions ->
  BHRequest StatusDependant StreamsStatusResponse
getStreamsStatusWith opts =
  get @StatusDependant (endpoint `withQueries` getStreamsStatusOptionsParams opts)
  where
    endpoint = mkEndpoint ["_streams", "status"]

-- | 'enableStream' builds the 'BHRequest' for
-- @POST /_streams/{name}/_enable@ (Elasticsearch 9.1+, experimental),
-- which enables a named stream. Equivalent to
-- @'enableStreamWith' name 'defaultStreamsActionOptions'@ — emits no
-- query string. Returns 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-streams-logs-enable>.
enableStream ::
  StreamName ->
  BHRequest StatusDependant Acknowledged
enableStream name = enableStreamWith name defaultStreamsActionOptions

-- | 'enableStreamWith' is the fully-parameterised variant of
-- 'enableStream', forwarding the @master_timeout@ \/ @timeout@ query
-- parameters via 'StreamsActionOptions'.
enableStreamWith ::
  StreamName ->
  StreamsActionOptions ->
  BHRequest StatusDependant Acknowledged
enableStreamWith name opts =
  post @StatusDependant endpoint emptyBody
  where
    endpoint =
      mkEndpoint ["_streams", unStreamName name, "_enable"]
        `withQueries` streamsActionOptionsParams opts

-- | 'disableStream' builds the 'BHRequest' for
-- @POST /_streams/{name}/_disable@ (Elasticsearch 9.1+, experimental),
-- which disables a named stream. Equivalent to
-- @'disableStreamWith' name 'defaultStreamsActionOptions'@. Returns
-- 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-streams-logs-disable>.
disableStream ::
  StreamName ->
  BHRequest StatusDependant Acknowledged
disableStream name = disableStreamWith name defaultStreamsActionOptions

-- | 'disableStreamWith' is the fully-parameterised variant of
-- 'disableStream', forwarding the @master_timeout@ \/ @timeout@ query
-- parameters via 'StreamsActionOptions'.
disableStreamWith ::
  StreamName ->
  StreamsActionOptions ->
  BHRequest StatusDependant Acknowledged
disableStreamWith name opts =
  post @StatusDependant endpoint emptyBody
  where
    endpoint =
      mkEndpoint ["_streams", unStreamName name, "_disable"]
        `withQueries` streamsActionOptionsParams opts

-- | 'downsampleIndex' builds the 'BHRequest' for
-- @POST /{index}/_downsample/{target_index}@ (Elasticsearch 9.x), which
-- rolls up an existing time-series index into a new, coarser-grained
-- index at the supplied 'FixedInterval'. The @targetIndex@ is the name
-- of the new downsampled index and is a mandatory path segment.
-- Equivalent to
-- @'downsampleIndexWith' index targetIndex body 'defaultDownsampleOptions'@
-- — emits no query string. Returns 'DownsampleResponse' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-indices-downsample>.
downsampleIndex ::
  IndexName ->
  IndexName ->
  DownsampleRequest ->
  BHRequest StatusDependant DownsampleResponse
downsampleIndex index targetIndex body =
  downsampleIndexWith index targetIndex body defaultDownsampleOptions

-- | 'downsampleIndexWith' is the fully-parameterised variant of
-- 'downsampleIndex', forwarding the @master_timeout@ \/ @timeout@ query
-- parameters via 'DownsampleOptions'.
downsampleIndexWith ::
  IndexName ->
  IndexName ->
  DownsampleRequest ->
  DownsampleOptions ->
  BHRequest StatusDependant DownsampleResponse
downsampleIndexWith index targetIndex body opts =
  post @StatusDependant endpoint (encode body)
  where
    endpoint =
      mkEndpoint [unIndexName index, "_downsample", unIndexName targetIndex]
        `withQueries` downsampleOptionsParams opts

-- | 'getGeoIpStats' builds the 'BHRequest' for
-- @GET /_ingest/geoip/stats@, which returns GeoIP downloader
-- statistics as a 'GeoIpStatsResponse' (aggregate counts plus per-node
-- cached database files).
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ingest-geo-ip-stats>.
getGeoIpStats ::
  BHRequest StatusDependant GeoIpStatsResponse
getGeoIpStats =
  get @StatusDependant endpoint
  where
    endpoint = mkEndpoint ["_ingest", "geoip", "stats"]

-- | 'getGeoIpDatabases' builds the 'BHRequest' for
-- @GET /_ingest/geoip/database@ (no id), returning every GeoIP database
-- configuration as a 'GeoIpDatabasesResponse'. For a single id, use
-- 'getGeoIpDatabase'.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ingest-get-geoip-database>.
getGeoIpDatabases ::
  BHRequest StatusDependant GeoIpDatabasesResponse
getGeoIpDatabases =
  get @StatusDependant endpoint
  where
    endpoint = mkEndpoint ["_ingest", "geoip", "database"]

-- | 'getGeoIpDatabase' builds the 'BHRequest' for
-- @GET /_ingest/geoip/database/{id}@. The 'GeoIpDatabaseId' may be a
-- single id, a comma-separated list, or the wildcard @"*"@ (the latter
-- is equivalent to 'getGeoIpDatabases').
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ingest-get-geoip-database>.
getGeoIpDatabase ::
  GeoIpDatabaseId ->
  BHRequest StatusDependant GeoIpDatabasesResponse
getGeoIpDatabase dbId =
  get @StatusDependant endpoint
  where
    endpoint = mkEndpoint ["_ingest", "geoip", "database", unGeoIpDatabaseId dbId]

-- | 'putGeoIpDatabase' builds the 'BHRequest' for
-- @PUT /_ingest/geoip/database/{id}@, creating or updating a GeoIP
-- database configuration. The 'GeoIpDatabasePutBody' carries the
-- required @maxmind@ provider. Returns 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ingest-put-geoip-database>.
putGeoIpDatabase ::
  GeoIpDatabaseId ->
  GeoIpDatabasePutBody ->
  BHRequest StatusDependant Acknowledged
putGeoIpDatabase dbId body =
  put @StatusDependant endpoint (encode body)
  where
    endpoint = mkEndpoint ["_ingest", "geoip", "database", unGeoIpDatabaseId dbId]

-- | 'deleteGeoIpDatabase' builds the 'BHRequest' for
-- @DELETE /_ingest/geoip/database/{id}@. The 'GeoIpDatabaseId' may be a
-- single id, a comma-separated list, or the wildcard @"*"@. Returns
-- 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ingest-delete-geoip-database>.
deleteGeoIpDatabase ::
  GeoIpDatabaseId ->
  BHRequest StatusDependant Acknowledged
deleteGeoIpDatabase dbId =
  delete endpoint
  where
    endpoint = mkEndpoint ["_ingest", "geoip", "database", unGeoIpDatabaseId dbId]

-- | 'getIpLocationDatabases' builds the 'BHRequest' for
-- @GET /_ingest/ip_location/database@ (no id), returning every
-- IP-location database configuration.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ingest-get-ip-location-database>.
getIpLocationDatabases ::
  BHRequest StatusDependant GeoIpDatabasesResponse
getIpLocationDatabases =
  get @StatusDependant endpoint
  where
    endpoint = mkEndpoint ["_ingest", "ip_location", "database"]

-- | 'getIpLocationDatabase' builds the 'BHRequest' for
-- @GET /_ingest/ip_location/database/{id}@. The 'GeoIpDatabaseId' may
-- be a single id, a comma-separated list, or the wildcard @"*"@.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ingest-get-ip-location-database>.
getIpLocationDatabase ::
  GeoIpDatabaseId ->
  BHRequest StatusDependant GeoIpDatabasesResponse
getIpLocationDatabase dbId =
  get @StatusDependant endpoint
  where
    endpoint = mkEndpoint ["_ingest", "ip_location", "database", unGeoIpDatabaseId dbId]

-- | 'putIpLocationDatabase' builds the 'BHRequest' for
-- @PUT /_ingest/ip_location/database/{id}@, creating or updating an
-- IP-location database configuration. The 'IpLocationDatabasePutBody'
-- should carry exactly one of @maxmind@ or @ipinfo@. Returns
-- 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ingest-put-ip-location-database>.
putIpLocationDatabase ::
  GeoIpDatabaseId ->
  IpLocationDatabasePutBody ->
  BHRequest StatusDependant Acknowledged
putIpLocationDatabase dbId body =
  put @StatusDependant endpoint (encode body)
  where
    endpoint = mkEndpoint ["_ingest", "ip_location", "database", unGeoIpDatabaseId dbId]

-- | 'deleteIpLocationDatabase' builds the 'BHRequest' for
-- @DELETE /_ingest/ip_location/database/{id}@. The 'GeoIpDatabaseId'
-- may be a single id, a comma-separated list, or the wildcard @"*"@.
-- Returns 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ingest-delete-ip-location-database>.
deleteIpLocationDatabase ::
  GeoIpDatabaseId ->
  BHRequest StatusDependant Acknowledged
deleteIpLocationDatabase dbId =
  delete endpoint
  where
    endpoint = mkEndpoint ["_ingest", "ip_location", "database", unGeoIpDatabaseId dbId]

-- | 'simulateIngest' builds the 'BHRequest' for
-- @POST /_ingest/_simulate@ (simulate-ingest v2), which resolves
-- templates and mappings against the supplied documents. Equivalent to
-- @'simulateIngestWith' body 'defaultSimulateIngestOptions'@.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-simulate-ingest>.
simulateIngest ::
  SimulateIngestRequest ->
  BHRequest StatusDependant SimulateIngestResponse
simulateIngest body =
  simulateIngestWith body defaultSimulateIngestOptions

-- | 'simulateIngestWith' is the fully-parameterised variant of
-- 'simulateIngest', forwarding the @pipeline@ and @merge_type@ query
-- parameters via 'SimulateIngestOptions'.
simulateIngestWith ::
  SimulateIngestRequest ->
  SimulateIngestOptions ->
  BHRequest StatusDependant SimulateIngestResponse
simulateIngestWith body opts =
  post @StatusDependant endpoint (encode body)
  where
    endpoint =
      mkEndpoint ["_ingest", "_simulate"]
        `withQueries` simulateIngestOptionsParams opts

-- | 'simulateIngestIndex' builds the 'BHRequest' for the index-scoped
-- @POST /_ingest/{index}/_simulate@. Equivalent to
-- @'simulateIngestIndexWith' indexName body 'defaultSimulateIngestOptions'@.
simulateIngestIndex ::
  IndexName ->
  SimulateIngestRequest ->
  BHRequest StatusDependant SimulateIngestResponse
simulateIngestIndex indexName body =
  simulateIngestIndexWith indexName body defaultSimulateIngestOptions

-- | 'simulateIngestIndexWith' is the fully-parameterised variant of
-- 'simulateIngestIndex', forwarding the @pipeline@ and @merge_type@
-- query parameters via 'SimulateIngestOptions'.
simulateIngestIndexWith ::
  IndexName ->
  SimulateIngestRequest ->
  SimulateIngestOptions ->
  BHRequest StatusDependant SimulateIngestResponse
simulateIngestIndexWith indexName body opts =
  post @StatusDependant endpoint (encode body)
  where
    endpoint =
      mkEndpoint ["_ingest", unIndexName indexName, "_simulate"]
        `withQueries` simulateIngestOptionsParams opts

-- | 'simulateIngestGet' is the GET-form counterpart of 'simulateIngest',
-- building the 'BHRequest' for @GET /_ingest/_simulate@ (simulate-ingest
-- v2). The Elasticsearch operation documents both GET and POST for this
-- path; the two are semantically identical — the request body is sent
-- with the GET (see 'getWithBody'). POST remains the canonical form, so
-- prefer 'simulateIngest' unless a GET is specifically required.
-- Equivalent to @'simulateIngestWithGet' body 'defaultSimulateIngestOptions'@.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-simulate-ingest>.
simulateIngestGet ::
  SimulateIngestRequest ->
  BHRequest StatusDependant SimulateIngestResponse
simulateIngestGet body =
  simulateIngestWithGet body defaultSimulateIngestOptions

-- | 'simulateIngestWithGet' is the fully-parameterised GET-form variant
-- of 'simulateIngestGet', forwarding the @pipeline@ and @merge_type@
-- query parameters via 'SimulateIngestOptions'.
simulateIngestWithGet ::
  SimulateIngestRequest ->
  SimulateIngestOptions ->
  BHRequest StatusDependant SimulateIngestResponse
simulateIngestWithGet body opts =
  getWithBody @StatusDependant endpoint (encode body)
  where
    endpoint =
      mkEndpoint ["_ingest", "_simulate"]
        `withQueries` simulateIngestOptionsParams opts

-- | 'simulateIngestIndexGet' is the GET-form counterpart of
-- 'simulateIngestIndex', building the 'BHRequest' for the index-scoped
-- @GET /_ingest/{index}/_simulate@. See 'simulateIngestGet' for the
-- GET/POST equivalence note. Equivalent to
-- @'simulateIngestIndexWithGet' indexName body 'defaultSimulateIngestOptions'@.
simulateIngestIndexGet ::
  IndexName ->
  SimulateIngestRequest ->
  BHRequest StatusDependant SimulateIngestResponse
simulateIngestIndexGet indexName body =
  simulateIngestIndexWithGet indexName body defaultSimulateIngestOptions

-- | 'simulateIngestIndexWithGet' is the fully-parameterised GET-form
-- variant of 'simulateIngestIndexGet', forwarding the @pipeline@ and
-- @merge_type@ query parameters via 'SimulateIngestOptions'.
simulateIngestIndexWithGet ::
  IndexName ->
  SimulateIngestRequest ->
  SimulateIngestOptions ->
  BHRequest StatusDependant SimulateIngestResponse
simulateIngestIndexWithGet indexName body opts =
  getWithBody @StatusDependant endpoint (encode body)
  where
    endpoint =
      mkEndpoint ["_ingest", unIndexName indexName, "_simulate"]
        `withQueries` simulateIngestOptionsParams opts

-- ----------------------------------------------------------------------
-- Resolve cluster / Health report / Features (bloodhound-d5kl)
-- ----------------------------------------------------------------------

-- | 'resolveCluster' builds the 'BHRequest' for the
-- @GET /_resolve/cluster[\/{name}]@ endpoint (indices-resolve-cluster),
-- new in Elasticsearch 9. It resolves the cluster-alias component of
-- index expressions — including @\<cluster\>:\<name\>@ remote-cluster
-- references — into the connected remote clusters the caller can search.
--
-- * @'Nothing'@  → @GET /_resolve/cluster@, which returns information
--   about every configured remote cluster without doing index matching.
-- * @'Just' pats@ → @GET /_resolve/cluster\/{name}@, which additionally
--   reports, per cluster, whether @pats@ matches any index there. The
--   patterns are joined with @,@ into a single path segment (matching
--   the server's comma-separated multi-target syntax).
--
-- Equivalent to @'resolveClusterWith' 'defaultResolveClusterOptions'@.
-- Use the @With@ variant to pass @expand_wildcards@,
-- @ignore_unavailable@, @allow_no_indices@ or @timeout@.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-indices-resolve-cluster>.
resolveCluster ::
  Maybe [Text] ->
  BHRequest StatusDependant ResolveClusterResponse
resolveCluster = resolveClusterWith defaultResolveClusterOptions

-- | 'resolveClusterWith' is the fully-parameterised form of
-- 'resolveCluster'. See 'ResolveClusterOptions' for the parameter
-- semantics; pass 'defaultResolveClusterOptions' to emit a request
-- byte-for-byte identical to 'resolveCluster'.
resolveClusterWith ::
  ResolveClusterOptions ->
  Maybe [Text] ->
  BHRequest StatusDependant ResolveClusterResponse
resolveClusterWith opts mPatterns =
  get @StatusDependant (endpoint `withQueries` resolveClusterOptionsParams opts)
  where
    endpoint = case mPatterns of
      Nothing -> mkEndpoint ["_resolve", "cluster"]
      Just patterns -> mkEndpoint ["_resolve", "cluster", T.intercalate "," patterns]

-- | 'getHealthReport' builds the 'BHRequest' for the
-- @GET /_health_report[\/{feature}]@ endpoint (health-report), new in
-- Elasticsearch 9. It returns a high-level health summary of the cluster
-- broken down by indicator (@master_is_stable@, @disk@, @ilm@, ...).
--
-- * @'Nothing'@  → @GET /_health_report@ reports every indicator.
-- * @'Just' feats@ → @GET /_health_report\/{feature}@ restricts the
--   report to the named indicators. The features are joined with @,@.
--
-- Equivalent to @'getHealthReportWith' 'defaultHealthReportOptions'@.
-- Use the @With@ variant to pass @verbose@, @size@ or @timeout@.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-health-report>.
getHealthReport ::
  Maybe [Text] ->
  BHRequest StatusDependant HealthReport
getHealthReport = getHealthReportWith defaultHealthReportOptions

-- | 'getHealthReportWith' is the fully-parameterised form of
-- 'getHealthReport'. See 'HealthReportOptions' for the parameter
-- semantics; pass 'defaultHealthReportOptions' to emit a request
-- byte-for-byte identical to 'getHealthReport'.
getHealthReportWith ::
  HealthReportOptions ->
  Maybe [Text] ->
  BHRequest StatusDependant HealthReport
getHealthReportWith opts mFeatures =
  get @StatusDependant (endpoint `withQueries` healthReportOptionsParams opts)
  where
    endpoint = case mFeatures of
      Nothing -> mkEndpoint ["_health_report"]
      Just features -> mkEndpoint ["_health_report", T.intercalate "," features]

-- | 'getFeatures' builds the 'BHRequest' for the @GET /_features@
-- endpoint (features-get-features). It returns the list of installed
-- features, each as a @name@ + @description@ pair.
--
-- Equivalent to @'getFeaturesWith' 'defaultFeaturesOptions'@.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-features-get-features>.
getFeatures ::
  BHRequest StatusDependant FeaturesResponse
getFeatures = getFeaturesWith defaultFeaturesOptions

-- | 'getFeaturesWith' is the fully-parameterised form of 'getFeatures'.
-- See 'FeaturesOptions' for the parameter semantics; pass
-- 'defaultFeaturesOptions' to emit a request byte-for-byte identical to
-- 'getFeatures'.
getFeaturesWith ::
  FeaturesOptions ->
  BHRequest StatusDependant FeaturesResponse
getFeaturesWith opts =
  get @StatusDependant (endpoint `withQueries` featuresOptionsParams opts)
  where
    endpoint = mkEndpoint ["_features"]

-- | 'resetFeatures' builds the 'BHRequest' for the
-- @POST /_features/_reset@ endpoint (features-reset-features). It resets
-- the state of every feature. The response carries the per-feature
-- outcome; because the documented example differs from the schema,
-- 'ResetFeaturesItem' tolerates both shapes.
--
-- This endpoint is /experimental and mutating/ — it is intended for
-- development/testing clusters, not production. Equivalent to
-- @'resetFeaturesWith' 'defaultFeaturesOptions'@.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-features-reset-features>.
resetFeatures ::
  BHRequest StatusDependant ResetFeaturesResponse
resetFeatures = resetFeaturesWith defaultFeaturesOptions

-- | 'resetFeaturesWith' is the fully-parameterised form of 'resetFeatures'.
-- See 'FeaturesOptions' for the parameter semantics; pass
-- 'defaultFeaturesOptions' to emit a request byte-for-byte identical to
-- 'resetFeatures'.
resetFeaturesWith ::
  FeaturesOptions ->
  BHRequest StatusDependant ResetFeaturesResponse
resetFeaturesWith opts =
  post @StatusDependant (endpoint `withQueries` featuresOptionsParams opts) emptyBody
  where
    endpoint = mkEndpoint ["_features", "_reset"]

------------------------------------------------------------------------------
-- Migration reindex (re-uses the ES8 builders; identical wire format)
------------------------------------------------------------------------------

-- | 'migrateReindex' builds the 'BHRequest' for
-- @POST /_migration/reindex@ on Elasticsearch 9. The wire format is
-- identical to ES8 (the endpoint shipped in 8.18.0), so the ES8 request
-- builder is reused verbatim.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-indices-migrate-reindex>.
migrateReindex ::
  MigrateReindexRequest ->
  BHRequest StatusDependant Acknowledged
migrateReindex = Requests8.migrateReindex

-- | 'cancelMigrateReindex' builds the 'BHRequest' for
-- @POST /_migration/reindex/{index}/_cancel@ on Elasticsearch 9. The
-- wire format is identical to ES8, so the ES8 request builder is reused
-- verbatim.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-indices-cancel-migrate-reindex>.
cancelMigrateReindex ::
  NonEmpty IndexName ->
  BHRequest StatusDependant Acknowledged
cancelMigrateReindex = Requests8.cancelMigrateReindex

-- | 'getMigrateReindexStatus' builds the 'BHRequest' for
-- @GET /_migration/reindex/{index}/_status@ on Elasticsearch 9. The wire
-- format is identical to ES8, so the ES8 request builder is reused
-- verbatim.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-indices-get-migrate-reindex-status>.
getMigrateReindexStatus ::
  NonEmpty IndexName ->
  BHRequest StatusDependant MigrateReindexStatus
getMigrateReindexStatus = Requests8.getMigrateReindexStatus

-- | 'createIndexFrom' builds the 'BHRequest' for
-- @POST /_create_from/{source}/{dest}@ on Elasticsearch 9. The wire
-- format is identical to ES8, so the ES8 request builder is reused
-- verbatim.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-indices-create-from>.
createIndexFrom ::
  IndexName ->
  IndexName ->
  BHRequest StatusDependant CreateIndexFromResponse
createIndexFrom = Requests8.createIndexFrom

-- | 'createIndexFromWith' is the fully-parameterised variant of
-- 'createIndexFrom' on Elasticsearch 9. The wire format is identical to
-- ES8, so the ES8 request builder is reused verbatim.
createIndexFromWith ::
  IndexName ->
  IndexName ->
  Maybe CreateIndexFromBody ->
  BHRequest StatusDependant CreateIndexFromResponse
createIndexFromWith = Requests8.createIndexFromWith

-- =========================================================================
-- ML data frame analytics (X-Pack)
-- =========================================================================

-- | 'putMlDataFrameAnalytics' builds the 'BHRequest' for
-- @PUT /_ml/data_frame/analytics/{id}@ (ml-put-data-frame-analytics),
-- creating a data frame analytics job. Equivalent to
-- @'putMlDataFrameAnalyticsWith' id body 'defaultMlDataFrameAnalyticsOptions'@.
-- Returns 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-put-data-frame-analytics>.
putMlDataFrameAnalytics ::
  MlDataFrameAnalyticsId ->
  MlDataFrameAnalyticsPutBody ->
  BHRequest StatusDependant Acknowledged
putMlDataFrameAnalytics id' body =
  putMlDataFrameAnalyticsWith id' body defaultMlDataFrameAnalyticsOptions

-- | 'putMlDataFrameAnalyticsWith' is the fully-parameterised variant of
-- 'putMlDataFrameAnalytics', forwarding the query parameters via
-- 'MlDataFrameAnalyticsOptions' (e.g. @allow_lazy_start@).
putMlDataFrameAnalyticsWith ::
  MlDataFrameAnalyticsId ->
  MlDataFrameAnalyticsPutBody ->
  MlDataFrameAnalyticsOptions ->
  BHRequest StatusDependant Acknowledged
putMlDataFrameAnalyticsWith id' body opts =
  put @StatusDependant (endpoint `withQueries` mlDataFrameAnalyticsOptionsParams opts) (encode body)
  where
    endpoint =
      mkEndpoint ["_ml", "data_frame", "analytics", unMlDataFrameAnalyticsId id']

-- | 'getMlDataFrameAnalytics' builds the 'BHRequest' for
-- @GET /_ml/data_frame/analytics[/{id}]@ (ml-get-data-frame-analytics).
-- Pass 'Nothing' for the id to list every job, or @'Just' id@ for a
-- single job (the id may also be a comma-separated list or wildcard
-- @"*"@). Equivalent to
-- @'getMlDataFrameAnalyticsWith' mid 'defaultMlDataFrameAnalyticsOptions'@.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-get-data-frame-analytics>.
getMlDataFrameAnalytics ::
  Maybe MlDataFrameAnalyticsId ->
  BHRequest StatusDependant MlDataFrameAnalyticsGetResponse
getMlDataFrameAnalytics mid =
  getMlDataFrameAnalyticsWith mid defaultMlDataFrameAnalyticsOptions

-- | 'getMlDataFrameAnalyticsWith' is the fully-parameterised variant of
-- 'getMlDataFrameAnalytics', forwarding the @from@ \/ @size@ query
-- parameters via 'MlDataFrameAnalyticsOptions'.
getMlDataFrameAnalyticsWith ::
  Maybe MlDataFrameAnalyticsId ->
  MlDataFrameAnalyticsOptions ->
  BHRequest StatusDependant MlDataFrameAnalyticsGetResponse
getMlDataFrameAnalyticsWith mid opts =
  get @StatusDependant (endpoint `withQueries` mlDataFrameAnalyticsOptionsParams opts)
  where
    endpoint =
      mkEndpoint $
        ["_ml", "data_frame", "analytics"]
          ++ maybe [] (\(MlDataFrameAnalyticsId x) -> [x]) mid

-- | 'updateMlDataFrameAnalytics' builds the 'BHRequest' for
-- @POST /_ml/data_frame/analytics/{id}/_update@
-- (ml-update-data-frame-analytics). Equivalent to
-- @'updateMlDataFrameAnalyticsWith' id body 'defaultMlDataFrameAnalyticsOptions'@.
-- Returns 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-update-data-frame-analytics>.
updateMlDataFrameAnalytics ::
  MlDataFrameAnalyticsId ->
  MlDataFrameAnalyticsUpdateBody ->
  BHRequest StatusDependant Acknowledged
updateMlDataFrameAnalytics id' body =
  updateMlDataFrameAnalyticsWith id' body defaultMlDataFrameAnalyticsOptions

-- | 'updateMlDataFrameAnalyticsWith' is the fully-parameterised variant
-- of 'updateMlDataFrameAnalytics'.
updateMlDataFrameAnalyticsWith ::
  MlDataFrameAnalyticsId ->
  MlDataFrameAnalyticsUpdateBody ->
  MlDataFrameAnalyticsOptions ->
  BHRequest StatusDependant Acknowledged
updateMlDataFrameAnalyticsWith id' body opts =
  post @StatusDependant (endpoint `withQueries` mlDataFrameAnalyticsOptionsParams opts) (encode body)
  where
    endpoint =
      mkEndpoint ["_ml", "data_frame", "analytics", unMlDataFrameAnalyticsId id', "_update"]

-- | 'deleteMlDataFrameAnalytics' builds the 'BHRequest' for
-- @DELETE /_ml/data_frame/analytics/{id}@ (ml-delete-data-frame-analytics).
-- Equivalent to
-- @'deleteMlDataFrameAnalyticsWith' id 'defaultMlDataFrameAnalyticsOptions'@.
-- Returns 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-delete-data-frame-analytics>.
deleteMlDataFrameAnalytics ::
  MlDataFrameAnalyticsId ->
  BHRequest StatusDependant Acknowledged
deleteMlDataFrameAnalytics id' =
  deleteMlDataFrameAnalyticsWith id' defaultMlDataFrameAnalyticsOptions

-- | 'deleteMlDataFrameAnalyticsWith' is the fully-parameterised variant
-- of 'deleteMlDataFrameAnalytics', forwarding the @force@ query
-- parameter via 'MlDataFrameAnalyticsOptions'.
deleteMlDataFrameAnalyticsWith ::
  MlDataFrameAnalyticsId ->
  MlDataFrameAnalyticsOptions ->
  BHRequest StatusDependant Acknowledged
deleteMlDataFrameAnalyticsWith id' opts =
  delete (endpoint `withQueries` mlDataFrameAnalyticsOptionsParams opts)
  where
    endpoint =
      mkEndpoint ["_ml", "data_frame", "analytics", unMlDataFrameAnalyticsId id']

-- | 'startMlDataFrameAnalytics' builds the 'BHRequest' for
-- @POST /_ml/data_frame/analytics/{id}/_start@
-- (ml-start-data-frame-analytics). Equivalent to
-- @'startMlDataFrameAnalyticsWith' id 'defaultMlDataFrameAnalyticsOptions'@.
-- Returns 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-start-data-frame-analytics>.
startMlDataFrameAnalytics ::
  MlDataFrameAnalyticsId ->
  BHRequest StatusDependant Acknowledged
startMlDataFrameAnalytics id' =
  startMlDataFrameAnalyticsWith id' defaultMlDataFrameAnalyticsOptions

-- | 'startMlDataFrameAnalyticsWith' is the fully-parameterised variant of
-- 'startMlDataFrameAnalytics'.
startMlDataFrameAnalyticsWith ::
  MlDataFrameAnalyticsId ->
  MlDataFrameAnalyticsOptions ->
  BHRequest StatusDependant Acknowledged
startMlDataFrameAnalyticsWith id' opts =
  post @StatusDependant (endpoint `withQueries` mlDataFrameAnalyticsOptionsParams opts) emptyBody
  where
    endpoint =
      mkEndpoint ["_ml", "data_frame", "analytics", unMlDataFrameAnalyticsId id', "_start"]

-- | 'stopMlDataFrameAnalytics' builds the 'BHRequest' for
-- @POST /_ml/data_frame/analytics/{id}/_stop@
-- (ml-stop-data-frame-analytics). Equivalent to
-- @'stopMlDataFrameAnalyticsWith' id 'defaultMlDataFrameAnalyticsOptions'@.
-- Returns 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-stop-data-frame-analytics>.
stopMlDataFrameAnalytics ::
  MlDataFrameAnalyticsId ->
  BHRequest StatusDependant Acknowledged
stopMlDataFrameAnalytics id' =
  stopMlDataFrameAnalyticsWith id' defaultMlDataFrameAnalyticsOptions

-- | 'stopMlDataFrameAnalyticsWith' is the fully-parameterised variant of
-- 'stopMlDataFrameAnalytics', forwarding the @force@ \/ @timeout@ query
-- parameters via 'MlDataFrameAnalyticsOptions'.
stopMlDataFrameAnalyticsWith ::
  MlDataFrameAnalyticsId ->
  MlDataFrameAnalyticsOptions ->
  BHRequest StatusDependant Acknowledged
stopMlDataFrameAnalyticsWith id' opts =
  post @StatusDependant (endpoint `withQueries` mlDataFrameAnalyticsOptionsParams opts) emptyBody
  where
    endpoint =
      mkEndpoint ["_ml", "data_frame", "analytics", unMlDataFrameAnalyticsId id', "_stop"]

-- | 'getMlDataFrameAnalyticsStats' builds the 'BHRequest' for
-- @GET /_ml/data_frame/analytics/{id}/_stats@
-- (ml-get-data-frame-analytics-stats). Pass 'Nothing' for the id to
-- fetch stats for every job. Equivalent to
-- @'getMlDataFrameAnalyticsStatsWith' mid 'defaultMlDataFrameAnalyticsOptions'@.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-get-data-frame-analytics-stats>.
getMlDataFrameAnalyticsStats ::
  Maybe MlDataFrameAnalyticsId ->
  BHRequest StatusDependant MlDataFrameAnalyticsStatsResponse
getMlDataFrameAnalyticsStats mid =
  getMlDataFrameAnalyticsStatsWith mid defaultMlDataFrameAnalyticsOptions

-- | 'getMlDataFrameAnalyticsStatsWith' is the fully-parameterised variant
-- of 'getMlDataFrameAnalyticsStats', forwarding the @verbose@ query
-- parameter via 'MlDataFrameAnalyticsOptions'.
getMlDataFrameAnalyticsStatsWith ::
  Maybe MlDataFrameAnalyticsId ->
  MlDataFrameAnalyticsOptions ->
  BHRequest StatusDependant MlDataFrameAnalyticsStatsResponse
getMlDataFrameAnalyticsStatsWith mid opts =
  get @StatusDependant (endpoint `withQueries` mlDataFrameAnalyticsOptionsParams opts)
  where
    endpoint =
      mkEndpoint $
        ["_ml", "data_frame", "analytics"]
          ++ maybe [] (\(MlDataFrameAnalyticsId x) -> [x]) mid
          ++ ["_stats"]

-- | 'previewMlDataFrameAnalytics' builds the 'BHRequest' for
-- @POST /_ml/data_frame/analytics/_preview@ (ml-preview-data-frame-analytics),
-- which simulates a data frame analytics config against a source index
-- and returns the would-be destination rows. The
-- 'MlDataFrameAnalyticsPreviewRequest' carries the config (or an
-- existing-id reference) as an opaque 'Value'.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-preview-data-frame-analytics>.
previewMlDataFrameAnalytics ::
  MlDataFrameAnalyticsPreviewRequest ->
  BHRequest StatusDependant MlDataFrameAnalyticsPreviewResponse
previewMlDataFrameAnalytics req =
  post @StatusDependant endpoint (encode req)
  where
    endpoint = mkEndpoint ["_ml", "data_frame", "analytics", "_preview"]

-- =========================================================================
-- ML trained models (X-Pack)
-- =========================================================================

-- | 'putMlTrainedModel' builds the 'BHRequest' for
-- @PUT /_ml/trained_models/{model_id}@ (ml-put-trained-model), creating a
-- trained model. Equivalent to
-- @'putMlTrainedModelWith' id body 'defaultMlTrainedModelOptions'@.
-- Returns 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-put-trained-model>.
putMlTrainedModel ::
  MlTrainedModelId ->
  MlTrainedModelPutBody ->
  BHRequest StatusDependant Acknowledged
putMlTrainedModel id' body =
  putMlTrainedModelWith id' body defaultMlTrainedModelOptions

-- | 'putMlTrainedModelWith' is the fully-parameterised variant of
-- 'putMlTrainedModel'.
putMlTrainedModelWith ::
  MlTrainedModelId ->
  MlTrainedModelPutBody ->
  MlTrainedModelOptions ->
  BHRequest StatusDependant Acknowledged
putMlTrainedModelWith id' body opts =
  put @StatusDependant (endpoint `withQueries` mlTrainedModelOptionsParams opts) (encode body)
  where
    endpoint =
      mkEndpoint ["_ml", "trained_models", unMlTrainedModelId id']

-- | 'getMlTrainedModels' builds the 'BHRequest' for
-- @GET /_ml/trained_models[/{model_id}]@ (ml-get-trained-models). Pass
-- 'Nothing' to list every model, or @'Just' id@ for one (the id may be a
-- comma-separated list or wildcard @"*"@). Equivalent to
-- @'getMlTrainedModelsWith' mid 'defaultMlTrainedModelOptions'@.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-get-trained-models>.
getMlTrainedModels ::
  Maybe MlTrainedModelId ->
  BHRequest StatusDependant MlTrainedModelsResponse
getMlTrainedModels mid =
  getMlTrainedModelsWith mid defaultMlTrainedModelOptions

-- | 'getMlTrainedModelsWith' is the fully-parameterised variant of
-- 'getMlTrainedModels', forwarding the @from@ \/ @size@ \/ @include_definition@
-- query parameters via 'MlTrainedModelOptions'.
getMlTrainedModelsWith ::
  Maybe MlTrainedModelId ->
  MlTrainedModelOptions ->
  BHRequest StatusDependant MlTrainedModelsResponse
getMlTrainedModelsWith mid opts =
  get @StatusDependant (endpoint `withQueries` mlTrainedModelOptionsParams opts)
  where
    endpoint =
      mkEndpoint $
        ["_ml", "trained_models"]
          ++ maybe [] (\(MlTrainedModelId x) -> [x]) mid

-- | 'getMlTrainedModelDefinition' builds the 'BHRequest' for
-- @GET /_ml/trained_models/{model_id}/definition@
-- (ml-get-trained-model-definition). Equivalent to
-- @'getMlTrainedModelDefinitionWith' id 'defaultMlTrainedModelOptions'@.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-get-trained-model-definition>.
getMlTrainedModelDefinition ::
  MlTrainedModelId ->
  BHRequest StatusDependant MlTrainedModelDefinition
getMlTrainedModelDefinition id' =
  getMlTrainedModelDefinitionWith id' defaultMlTrainedModelOptions

-- | 'getMlTrainedModelDefinitionWith' is the fully-parameterised variant
-- of 'getMlTrainedModelDefinition', forwarding the @decompress_definition@
-- query parameter via 'MlTrainedModelOptions'.
getMlTrainedModelDefinitionWith ::
  MlTrainedModelId ->
  MlTrainedModelOptions ->
  BHRequest StatusDependant MlTrainedModelDefinition
getMlTrainedModelDefinitionWith id' opts =
  get @StatusDependant (endpoint `withQueries` mlTrainedModelOptionsParams opts)
  where
    endpoint =
      mkEndpoint ["_ml", "trained_models", unMlTrainedModelId id', "definition"]

-- | 'updateMlTrainedModel' builds the 'BHRequest' for
-- @POST /_ml/trained_models/{model_id}/_update@
-- (ml-update-trained-model). Equivalent to
-- @'updateMlTrainedModelWith' id body 'defaultMlTrainedModelOptions'@.
-- Returns 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-update-trained-model>.
updateMlTrainedModel ::
  MlTrainedModelId ->
  MlTrainedModelUpdateBody ->
  BHRequest StatusDependant Acknowledged
updateMlTrainedModel id' body =
  updateMlTrainedModelWith id' body defaultMlTrainedModelOptions

-- | 'updateMlTrainedModelWith' is the fully-parameterised variant of
-- 'updateMlTrainedModel'.
updateMlTrainedModelWith ::
  MlTrainedModelId ->
  MlTrainedModelUpdateBody ->
  MlTrainedModelOptions ->
  BHRequest StatusDependant Acknowledged
updateMlTrainedModelWith id' body opts =
  post @StatusDependant (endpoint `withQueries` mlTrainedModelOptionsParams opts) (encode body)
  where
    endpoint =
      mkEndpoint ["_ml", "trained_models", unMlTrainedModelId id', "_update"]

-- | 'deleteMlTrainedModel' builds the 'BHRequest' for
-- @DELETE /_ml/trained_models/{model_id}@ (ml-delete-trained-model).
-- Equivalent to @'deleteMlTrainedModelWith' id 'defaultMlTrainedModelOptions'@.
-- Returns 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-delete-trained-model>.
deleteMlTrainedModel ::
  MlTrainedModelId ->
  BHRequest StatusDependant Acknowledged
deleteMlTrainedModel id' =
  deleteMlTrainedModelWith id' defaultMlTrainedModelOptions

-- | 'deleteMlTrainedModelWith' is the fully-parameterised variant of
-- 'deleteMlTrainedModel'.
deleteMlTrainedModelWith ::
  MlTrainedModelId ->
  MlTrainedModelOptions ->
  BHRequest StatusDependant Acknowledged
deleteMlTrainedModelWith id' opts =
  delete (endpoint `withQueries` mlTrainedModelOptionsParams opts)
  where
    endpoint =
      mkEndpoint ["_ml", "trained_models", unMlTrainedModelId id']

-- | 'deployMlTrainedModel' builds the 'BHRequest' for
-- @POST /_ml/trained_models/{model_id}/deployment/_deploy@
-- (ml-deploy-trained-model). Equivalent to
-- @'deployMlTrainedModelWith' id 'defaultMlTrainedModelOptions'@. Returns
-- 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-deploy-trained-model>.
deployMlTrainedModel ::
  MlTrainedModelId ->
  BHRequest StatusDependant Acknowledged
deployMlTrainedModel id' =
  deployMlTrainedModelWith id' defaultMlTrainedModelOptions

-- | 'deployMlTrainedModelWith' is the fully-parameterised variant of
-- 'deployMlTrainedModel', forwarding the @wait_for_completion@ \/
-- @priority@ \/ @threads@ query parameters via 'MlTrainedModelOptions'.
deployMlTrainedModelWith ::
  MlTrainedModelId ->
  MlTrainedModelOptions ->
  BHRequest StatusDependant Acknowledged
deployMlTrainedModelWith id' opts =
  post @StatusDependant (endpoint `withQueries` mlTrainedModelOptionsParams opts) emptyBody
  where
    endpoint =
      mkEndpoint ["_ml", "trained_models", unMlTrainedModelId id', "deployment", "_deploy"]

-- | 'undeployMlTrainedModel' builds the 'BHRequest' for
-- @POST /_ml/trained_models/{model_id}/deployment/_undeploy@
-- (ml-undeploy-trained-model). Equivalent to
-- @'undeployMlTrainedModelWith' id 'defaultMlTrainedModelOptions'@.
-- Returns 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-undeploy-trained-model>.
undeployMlTrainedModel ::
  MlTrainedModelId ->
  BHRequest StatusDependant Acknowledged
undeployMlTrainedModel id' =
  undeployMlTrainedModelWith id' defaultMlTrainedModelOptions

-- | 'undeployMlTrainedModelWith' is the fully-parameterised variant of
-- 'undeployMlTrainedModel', forwarding the @force@ query parameter via
-- 'MlTrainedModelOptions'.
undeployMlTrainedModelWith ::
  MlTrainedModelId ->
  MlTrainedModelOptions ->
  BHRequest StatusDependant Acknowledged
undeployMlTrainedModelWith id' opts =
  post @StatusDependant (endpoint `withQueries` mlTrainedModelOptionsParams opts) emptyBody
  where
    endpoint =
      mkEndpoint ["_ml", "trained_models", unMlTrainedModelId id', "deployment", "_undeploy"]

-- | 'startMlTrainedModelDeployment' builds the 'BHRequest' for
-- @POST /_ml/trained_models/{model_id}/deployment/_start@
-- (ml-start-trained-model-deployment), the 8.12+ alias of
-- 'deployMlTrainedModel'. Equivalent to
-- @'startMlTrainedModelDeploymentWith' id 'defaultMlTrainedModelOptions'@.
-- Returns 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-start-trained-model-deployment>.
startMlTrainedModelDeployment ::
  MlTrainedModelId ->
  BHRequest StatusDependant Acknowledged
startMlTrainedModelDeployment id' =
  startMlTrainedModelDeploymentWith id' defaultMlTrainedModelOptions

-- | 'startMlTrainedModelDeploymentWith' is the fully-parameterised variant
-- of 'startMlTrainedModelDeployment'.
startMlTrainedModelDeploymentWith ::
  MlTrainedModelId ->
  MlTrainedModelOptions ->
  BHRequest StatusDependant Acknowledged
startMlTrainedModelDeploymentWith id' opts =
  post @StatusDependant (endpoint `withQueries` mlTrainedModelOptionsParams opts) emptyBody
  where
    endpoint =
      mkEndpoint ["_ml", "trained_models", unMlTrainedModelId id', "deployment", "_start"]

-- | 'stopMlTrainedModelDeployment' builds the 'BHRequest' for
-- @POST /_ml/trained_models/{model_id}/deployment/_stop@
-- (ml-stop-trained-model-deployment), the 8.12+ alias of
-- 'undeployMlTrainedModel'. Equivalent to
-- @'stopMlTrainedModelDeploymentWith' id 'defaultMlTrainedModelOptions'@.
-- Returns 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-stop-trained-model-deployment>.
stopMlTrainedModelDeployment ::
  MlTrainedModelId ->
  BHRequest StatusDependant Acknowledged
stopMlTrainedModelDeployment id' =
  stopMlTrainedModelDeploymentWith id' defaultMlTrainedModelOptions

-- | 'stopMlTrainedModelDeploymentWith' is the fully-parameterised variant
-- of 'stopMlTrainedModelDeployment'.
stopMlTrainedModelDeploymentWith ::
  MlTrainedModelId ->
  MlTrainedModelOptions ->
  BHRequest StatusDependant Acknowledged
stopMlTrainedModelDeploymentWith id' opts =
  post @StatusDependant (endpoint `withQueries` mlTrainedModelOptionsParams opts) emptyBody
  where
    endpoint =
      mkEndpoint ["_ml", "trained_models", unMlTrainedModelId id', "deployment", "_stop"]

-- | 'getMlTrainedModelStats' builds the 'BHRequest' for
-- @GET /_ml/trained_models/{model_id}/_stats@
-- (ml-get-trained-models-stats). Pass 'Nothing' for the id to fetch stats
-- for every model. Equivalent to
-- @'getMlTrainedModelStatsWith' mid 'defaultMlTrainedModelOptions'@.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-get-trained-models-stats>.
getMlTrainedModelStats ::
  Maybe MlTrainedModelId ->
  BHRequest StatusDependant MlTrainedModelStatsResponse
getMlTrainedModelStats mid =
  getMlTrainedModelStatsWith mid defaultMlTrainedModelOptions

-- | 'getMlTrainedModelStatsWith' is the fully-parameterised variant of
-- 'getMlTrainedModelStats'.
getMlTrainedModelStatsWith ::
  Maybe MlTrainedModelId ->
  MlTrainedModelOptions ->
  BHRequest StatusDependant MlTrainedModelStatsResponse
getMlTrainedModelStatsWith mid opts =
  get @StatusDependant (endpoint `withQueries` mlTrainedModelOptionsParams opts)
  where
    endpoint =
      mkEndpoint $
        ["_ml", "trained_models"]
          ++ maybe [] (\(MlTrainedModelId x) -> [x]) mid
          ++ ["_stats"]

-- | 'inferMlTrainedModel' builds the 'BHRequest' for
-- @POST /_ml/trained_models/{model_id}/_infer@
-- (ml-infer-trained-model), running inference against a deployed model.
-- The 'MlTrainedModelInferRequest' carries the @docs@ payload as an
-- opaque 'Value'.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-infer-trained-model>.
inferMlTrainedModel ::
  MlTrainedModelId ->
  MlTrainedModelInferRequest ->
  BHRequest StatusDependant MlTrainedModelInferResponse
inferMlTrainedModel id' req =
  post @StatusDependant endpoint (encode req)
  where
    endpoint =
      mkEndpoint ["_ml", "trained_models", unMlTrainedModelId id', "_infer"]

-- =========================================================================
-- ML anomaly jobs (X-Pack)
-- =========================================================================

-- | 'putMlAnomalyJob' builds the 'BHRequest' for
-- @PUT /_ml/anomaly_detectors/{job_id}@ (ml-put-job), creating an anomaly
-- detection job. Returns 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-put-job>.
putMlAnomalyJob ::
  MlJobId ->
  MlAnomalyJob ->
  BHRequest StatusDependant Acknowledged
putMlAnomalyJob id' body =
  put @StatusDependant endpoint (encode body)
  where
    endpoint = mkEndpoint ["_ml", "anomaly_detectors", unMlJobId id']

-- | 'getMlAnomalyJobs' builds the 'BHRequest' for
-- @GET /_ml/anomaly_detectors[/{job_id}]@ (ml-get-job). Pass 'Nothing'
-- to list every job. Equivalent to
-- @'getMlAnomalyJobsWith' mid 'defaultMlAnomalyJobOptions'@.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-get-job>.
getMlAnomalyJobs ::
  Maybe MlJobId ->
  BHRequest StatusDependant MlAnomalyJobsResponse
getMlAnomalyJobs mid = getMlAnomalyJobsWith mid defaultMlAnomalyJobOptions

-- | 'getMlAnomalyJobsWith' is the fully-parameterised variant of
-- 'getMlAnomalyJobs'.
getMlAnomalyJobsWith ::
  Maybe MlJobId ->
  MlAnomalyJobOptions ->
  BHRequest StatusDependant MlAnomalyJobsResponse
getMlAnomalyJobsWith mid opts =
  get @StatusDependant (endpoint `withQueries` mlAnomalyJobOptionsParams opts)
  where
    endpoint =
      mkEndpoint $
        ["_ml", "anomaly_detectors"]
          ++ maybe [] (\(MlJobId x) -> [x]) mid

-- | 'updateMlAnomalyJob' builds the 'BHRequest' for
-- @POST /_ml/anomaly_detectors/{job_id}/_update@ (ml-update-job).
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-update-job>.
updateMlAnomalyJob ::
  MlJobId ->
  MlAnomalyJobUpdate ->
  BHRequest StatusDependant Acknowledged
updateMlAnomalyJob id' body =
  post @StatusDependant endpoint (encode body)
  where
    endpoint =
      mkEndpoint ["_ml", "anomaly_detectors", unMlJobId id', "_update"]

-- | 'deleteMlAnomalyJob' builds the 'BHRequest' for
-- @DELETE /_ml/anomaly_detectors/{job_id}@ (ml-delete-job). Equivalent to
-- @'deleteMlAnomalyJobWith' id 'defaultMlAnomalyJobOptions'@.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-delete-job>.
deleteMlAnomalyJob ::
  MlJobId ->
  BHRequest StatusDependant Acknowledged
deleteMlAnomalyJob id' =
  deleteMlAnomalyJobWith id' defaultMlAnomalyJobOptions

-- | 'deleteMlAnomalyJobWith' is the fully-parameterised variant of
-- 'deleteMlAnomalyJob', forwarding the @force@ query parameter.
deleteMlAnomalyJobWith ::
  MlJobId ->
  MlAnomalyJobOptions ->
  BHRequest StatusDependant Acknowledged
deleteMlAnomalyJobWith id' opts =
  delete (endpoint `withQueries` mlAnomalyJobOptionsParams opts)
  where
    endpoint =
      mkEndpoint ["_ml", "anomaly_detectors", unMlJobId id']

-- | 'openMlAnomalyJob' builds the 'BHRequest' for
-- @POST /_ml/anomaly_detectors/{job_id}/_open@ (ml-open-job). Returns
-- 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-open-job>.
openMlAnomalyJob ::
  MlJobId ->
  BHRequest StatusDependant Acknowledged
openMlAnomalyJob id' =
  post @StatusDependant endpoint emptyBody
  where
    endpoint =
      mkEndpoint ["_ml", "anomaly_detectors", unMlJobId id', "_open"]

-- | 'closeMlAnomalyJob' builds the 'BHRequest' for
-- @POST /_ml/anomaly_detectors/{job_id}/_close@ (ml-close-job). Returns
-- 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-close-job>.
closeMlAnomalyJob ::
  MlJobId ->
  BHRequest StatusDependant Acknowledged
closeMlAnomalyJob id' =
  post @StatusDependant endpoint emptyBody
  where
    endpoint =
      mkEndpoint ["_ml", "anomaly_detectors", unMlJobId id', "_close"]

-- | 'forecastMlAnomalyJob' builds the 'BHRequest' for
-- @POST /_ml/anomaly_detectors/{job_id}/_forecast@ (ml-forecast-job),
-- producing a forecast for a started job. Pass
-- 'defaultMlForecastOptions' for an empty body.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-forecast>.
forecastMlAnomalyJob ::
  MlJobId ->
  MlForecastOptions ->
  BHRequest StatusDependant MlForecastResponse
forecastMlAnomalyJob id' body =
  post @StatusDependant endpoint (encode body)
  where
    endpoint =
      mkEndpoint ["_ml", "anomaly_detectors", unMlJobId id', "_forecast"]

-- | 'flushMlAnomalyJob' builds the 'BHRequest' for
-- @POST /_ml/anomaly_detectors/{job_id}/_flush@ (ml-flush-job),
-- forcing the job to flush its interim results. Pass
-- 'defaultMlFlushOptions' for an empty body.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-flush-job>.
flushMlAnomalyJob ::
  MlJobId ->
  MlFlushOptions ->
  BHRequest StatusDependant MlFlushResponse
flushMlAnomalyJob id' body =
  post @StatusDependant endpoint (encode body)
  where
    endpoint =
      mkEndpoint ["_ml", "anomaly_detectors", unMlJobId id', "_flush"]

-- | 'validateMlAnomalyJob' builds the 'BHRequest' for
-- @POST /_ml/anomaly_detectors/_validate@ (ml-validate-job), validating
-- an anomaly job configuration without creating it. The job body is the
-- first argument.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-validate-job>.
validateMlAnomalyJob ::
  MlAnomalyJob ->
  BHRequest StatusDependant MlValidateResponse
validateMlAnomalyJob body =
  post @StatusDependant endpoint (encode body)
  where
    endpoint = mkEndpoint ["_ml", "anomaly_detectors", "_validate"]

-- | 'getMlAnomalyJobStats' builds the 'BHRequest' for
-- @GET /_ml/anomaly_detectors[/{job_id}]/_stats@ (ml-get-job-stats). Pass
-- 'Nothing' to fetch stats for every job. Equivalent to
-- @'getMlAnomalyJobStatsWith' mid 'defaultMlAnomalyJobOptions'@.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-get-job-stats>.
getMlAnomalyJobStats ::
  Maybe MlJobId ->
  BHRequest StatusDependant MlAnomalyJobStatsResponse
getMlAnomalyJobStats mid =
  getMlAnomalyJobStatsWith mid defaultMlAnomalyJobOptions

-- | 'getMlAnomalyJobStatsWith' is the fully-parameterised variant of
-- 'getMlAnomalyJobStats'.
getMlAnomalyJobStatsWith ::
  Maybe MlJobId ->
  MlAnomalyJobOptions ->
  BHRequest StatusDependant MlAnomalyJobStatsResponse
getMlAnomalyJobStatsWith mid opts =
  get @StatusDependant (endpoint `withQueries` mlAnomalyJobOptionsParams opts)
  where
    endpoint =
      mkEndpoint $
        ["_ml", "anomaly_detectors"]
          ++ maybe [] (\(MlJobId x) -> [x]) mid
          ++ ["_stats"]

-- | 'getMlAnomalyJobResults' builds the 'BHRequest' for the read-only
-- results endpoints
-- @GET /_ml/anomaly_detectors/{job_id}/_results/{buckets,records,categories,influencers,overall_buckets}@
-- (ml-get-buckets, ml-get-records, …). 'MlAnomalyResultType' selects the
-- results kind. Equivalent to
-- @'getMlAnomalyJobResultsWith' id kind 'defaultMlAnomalyJobOptions'@.
getMlAnomalyJobResults ::
  MlJobId ->
  MlAnomalyResultType ->
  BHRequest StatusDependant MlAnomalyJobResults
getMlAnomalyJobResults id' kind =
  getMlAnomalyJobResultsWith id' kind defaultMlAnomalyJobOptions

-- | 'getMlAnomalyJobResultsWith' is the fully-parameterised variant of
-- 'getMlAnomalyJobResults'.
getMlAnomalyJobResultsWith ::
  MlJobId ->
  MlAnomalyResultType ->
  MlAnomalyJobOptions ->
  BHRequest StatusDependant MlAnomalyJobResults
getMlAnomalyJobResultsWith id' kind opts =
  get @StatusDependant (endpoint `withQueries` mlAnomalyJobOptionsParams opts)
  where
    endpoint =
      mkEndpoint
        [ "_ml",
          "anomaly_detectors",
          unMlJobId id',
          "_results",
          mlAnomalyResultTypeSegment kind
        ]

-- | 'getMlModelSnapshots' builds the 'BHRequest' for
-- @GET /_ml/anomaly_detectors/{job_id}/_model_snapshots@
-- (ml-get-model-snapshots). Equivalent to
-- @'getMlModelSnapshotsWith' id 'defaultMlAnomalyJobOptions'@.
getMlModelSnapshots ::
  MlJobId ->
  BHRequest StatusDependant MlModelSnapshotsResponse
getMlModelSnapshots id' =
  getMlModelSnapshotsWith id' defaultMlAnomalyJobOptions

-- | 'getMlModelSnapshotsWith' is the fully-parameterised variant of
-- 'getMlModelSnapshots'.
getMlModelSnapshotsWith ::
  MlJobId ->
  MlAnomalyJobOptions ->
  BHRequest StatusDependant MlModelSnapshotsResponse
getMlModelSnapshotsWith id' opts =
  get @StatusDependant (endpoint `withQueries` mlAnomalyJobOptionsParams opts)
  where
    endpoint =
      mkEndpoint ["_ml", "anomaly_detectors", unMlJobId id', "_model_snapshots"]

-- | 'getMlModelSnapshot' builds the 'BHRequest' for
-- @GET /_ml/anomaly_detectors/{job_id}/_model_snapshots/{snapshot_id}@
-- (ml-get-model-snapshot-info). Equivalent to
-- @'getMlModelSnapshotWith' id snap 'defaultMlAnomalyJobOptions'@.
getMlModelSnapshot ::
  MlJobId ->
  MlModelSnapshotId ->
  BHRequest StatusDependant MlModelSnapshotsResponse
getMlModelSnapshot id' snap =
  getMlModelSnapshotWith id' snap defaultMlAnomalyJobOptions

-- | 'getMlModelSnapshotWith' is the fully-parameterised variant of
-- 'getMlModelSnapshot'.
getMlModelSnapshotWith ::
  MlJobId ->
  MlModelSnapshotId ->
  MlAnomalyJobOptions ->
  BHRequest StatusDependant MlModelSnapshotsResponse
getMlModelSnapshotWith id' snap opts =
  get @StatusDependant (endpoint `withQueries` mlAnomalyJobOptionsParams opts)
  where
    endpoint =
      mkEndpoint
        [ "_ml",
          "anomaly_detectors",
          unMlJobId id',
          "_model_snapshots",
          unMlModelSnapshotId snap
        ]

-- | 'updateMlModelSnapshot' builds the 'BHRequest' for
-- @PUT /_ml/anomaly_detectors/{job_id}/_model_snapshots/{snapshot_id}@
-- (ml-update-model-snapshot), updating snapshot metadata. Returns
-- 'Acknowledged' on success.
updateMlModelSnapshot ::
  MlJobId ->
  MlModelSnapshotId ->
  Value ->
  BHRequest StatusDependant Acknowledged
updateMlModelSnapshot id' snap body =
  put @StatusDependant endpoint (encode body)
  where
    endpoint =
      mkEndpoint
        [ "_ml",
          "anomaly_detectors",
          unMlJobId id',
          "_model_snapshots",
          unMlModelSnapshotId snap
        ]

-- | 'deleteMlModelSnapshot' builds the 'BHRequest' for
-- @DELETE /_ml/anomaly_detectors/{job_id}/_model_snapshots/{snapshot_id}@
-- (ml-delete-model-snapshot). Equivalent to
-- @'deleteMlModelSnapshotWith' id snap 'defaultMlAnomalyJobOptions'@.
deleteMlModelSnapshot ::
  MlJobId ->
  MlModelSnapshotId ->
  BHRequest StatusDependant Acknowledged
deleteMlModelSnapshot id' snap =
  deleteMlModelSnapshotWith id' snap defaultMlAnomalyJobOptions

-- | 'deleteMlModelSnapshotWith' is the fully-parameterised variant of
-- 'deleteMlModelSnapshot'.
deleteMlModelSnapshotWith ::
  MlJobId ->
  MlModelSnapshotId ->
  MlAnomalyJobOptions ->
  BHRequest StatusDependant Acknowledged
deleteMlModelSnapshotWith id' snap opts =
  delete (endpoint `withQueries` mlAnomalyJobOptionsParams opts)
  where
    endpoint =
      mkEndpoint
        [ "_ml",
          "anomaly_detectors",
          unMlJobId id',
          "_model_snapshots",
          unMlModelSnapshotId snap
        ]

-- | 'revertMlModelSnapshot' builds the 'BHRequest' for
-- @POST /_ml/anomaly_detectors/{job_id}/_model_snapshots/{snapshot_id}/_revert@
-- (ml-revert-model-snapshot). The body carries the revert options (e.g.
-- @delete_intervening_results@) as an opaque 'Value'; pass @object []@
-- for an empty body. Equivalent to
-- @'revertMlModelSnapshotWith' id snap (object []) 'defaultMlAnomalyJobOptions'@.
revertMlModelSnapshot ::
  MlJobId ->
  MlModelSnapshotId ->
  Value ->
  BHRequest StatusDependant MlRevertSnapshotResponse
revertMlModelSnapshot id' snap body =
  revertMlModelSnapshotWith id' snap body defaultMlAnomalyJobOptions

-- | 'revertMlModelSnapshotWith' is the fully-parameterised variant of
-- 'revertMlModelSnapshot'.
revertMlModelSnapshotWith ::
  MlJobId ->
  MlModelSnapshotId ->
  Value ->
  MlAnomalyJobOptions ->
  BHRequest StatusDependant MlRevertSnapshotResponse
revertMlModelSnapshotWith id' snap body opts =
  post @StatusDependant (endpoint `withQueries` mlAnomalyJobOptionsParams opts) (encode body)
  where
    endpoint =
      mkEndpoint
        [ "_ml",
          "anomaly_detectors",
          unMlJobId id',
          "_model_snapshots",
          unMlModelSnapshotId snap,
          "_revert"
        ]

-- =========================================================================
-- ML datafeeds (X-Pack)
-- =========================================================================

-- | 'putMlDatafeed' builds the 'BHRequest' for
-- @PUT /_ml/datafeeds/{feed_id}@ (ml-put-datafeed), creating a datafeed.
-- Returns 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-put-datafeed>.
putMlDatafeed ::
  MlDatafeedId ->
  MlDatafeed ->
  BHRequest StatusDependant Acknowledged
putMlDatafeed id' body =
  put @StatusDependant endpoint (encode body)
  where
    endpoint = mkEndpoint ["_ml", "datafeeds", unMlDatafeedId id']

-- | 'getMlDatafeeds' builds the 'BHRequest' for
-- @GET /_ml/datafeeds[/{feed_id}]@ (ml-get-datafeed). Pass 'Nothing' to
-- list every datafeed. Equivalent to
-- @'getMlDatafeedsWith' mid 'defaultMlDatafeedOptions'@.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-get-datafeed>.
getMlDatafeeds ::
  Maybe MlDatafeedId ->
  BHRequest StatusDependant MlDatafeedsResponse
getMlDatafeeds mid = getMlDatafeedsWith mid defaultMlDatafeedOptions

-- | 'getMlDatafeedsWith' is the fully-parameterised variant of
-- 'getMlDatafeeds'.
getMlDatafeedsWith ::
  Maybe MlDatafeedId ->
  MlDatafeedOptions ->
  BHRequest StatusDependant MlDatafeedsResponse
getMlDatafeedsWith mid opts =
  get @StatusDependant (endpoint `withQueries` mlDatafeedOptionsParams opts)
  where
    endpoint =
      mkEndpoint $
        ["_ml", "datafeeds"]
          ++ maybe [] (\(MlDatafeedId x) -> [x]) mid

-- | 'updateMlDatafeed' builds the 'BHRequest' for
-- @POST /_ml/datafeeds/{feed_id}/_update@ (ml-update-datafeed).
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-update-datafeed>.
updateMlDatafeed ::
  MlDatafeedId ->
  MlDatafeedUpdate ->
  BHRequest StatusDependant Acknowledged
updateMlDatafeed id' body =
  post @StatusDependant endpoint (encode body)
  where
    endpoint =
      mkEndpoint ["_ml", "datafeeds", unMlDatafeedId id', "_update"]

-- | 'deleteMlDatafeed' builds the 'BHRequest' for
-- @DELETE /_ml/datafeeds/{feed_id}@ (ml-delete-datafeed). Returns
-- 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-delete-datafeed>.
deleteMlDatafeed ::
  MlDatafeedId ->
  BHRequest StatusDependant Acknowledged
deleteMlDatafeed id' =
  delete endpoint
  where
    endpoint = mkEndpoint ["_ml", "datafeeds", unMlDatafeedId id']

-- | 'startMlDatafeed' builds the 'BHRequest' for
-- @POST /_ml/datafeeds/{feed_id}/_start@ (ml-start-datafeed). The body
-- may carry an optional @start@ \/ @end@ time; pass @object []@ for an
-- empty body. Returns 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-start-datafeed>.
startMlDatafeed ::
  MlDatafeedId ->
  Value ->
  BHRequest StatusDependant Acknowledged
startMlDatafeed id' body =
  post @StatusDependant endpoint (encode body)
  where
    endpoint =
      mkEndpoint ["_ml", "datafeeds", unMlDatafeedId id', "_start"]

-- | 'stopMlDatafeed' builds the 'BHRequest' for
-- @POST /_ml/datafeeds/{feed_id}/_stop@ (ml-stop-datafeed). Returns
-- 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-stop-datafeed>.
stopMlDatafeed ::
  MlDatafeedId ->
  BHRequest StatusDependant Acknowledged
stopMlDatafeed id' =
  post @StatusDependant endpoint emptyBody
  where
    endpoint =
      mkEndpoint ["_ml", "datafeeds", unMlDatafeedId id', "_stop"]

-- | 'previewMlDatafeed' builds the 'BHRequest' for
-- @GET /_ml/datafeeds/{feed_id}/_preview@ (ml-preview-datafeed),
-- returning the documents the datafeed would currently send to its job.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-preview-datafeed>.
previewMlDatafeed ::
  MlDatafeedId ->
  BHRequest StatusDependant MlDatafeedPreviewResponse
previewMlDatafeed id' =
  get @StatusDependant endpoint
  where
    endpoint =
      mkEndpoint ["_ml", "datafeeds", unMlDatafeedId id', "_preview"]

-- =========================================================================
-- ML filters (X-Pack)
-- =========================================================================

-- | 'putMlFilter' builds the 'BHRequest' for
-- @PUT /_ml/filters/{filter_id}@ (ml-put-filter), creating or updating a
-- filter. Returns 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-put-filter>.
putMlFilter ::
  MlFilterId ->
  MlFilter ->
  BHRequest StatusDependant Acknowledged
putMlFilter id' body =
  put @StatusDependant endpoint (encode body)
  where
    endpoint = mkEndpoint ["_ml", "filters", unMlFilterId id']

-- | 'getMlFilters' builds the 'BHRequest' for
-- @GET /_ml/filters[/{filter_id}]@ (ml-get-filter). Pass 'Nothing' to
-- list every filter. Equivalent to
-- @'getMlFiltersWith' mid 'defaultMlDatafeedOptions'@.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-get-filter>.
getMlFilters ::
  Maybe MlFilterId ->
  BHRequest StatusDependant MlFiltersResponse
getMlFilters mid = getMlFiltersWith mid defaultMlDatafeedOptions

-- | 'getMlFiltersWith' is the fully-parameterised variant of
-- 'getMlFilters'.
getMlFiltersWith ::
  Maybe MlFilterId ->
  MlDatafeedOptions ->
  BHRequest StatusDependant MlFiltersResponse
getMlFiltersWith mid opts =
  get @StatusDependant (endpoint `withQueries` mlDatafeedOptionsParams opts)
  where
    endpoint =
      mkEndpoint $
        ["_ml", "filters"]
          ++ maybe [] (\(MlFilterId x) -> [x]) mid

-- | 'deleteMlFilter' builds the 'BHRequest' for
-- @DELETE /_ml/filters/{filter_id}@ (ml-delete-filter). Returns
-- 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-delete-filter>.
deleteMlFilter ::
  MlFilterId ->
  BHRequest StatusDependant Acknowledged
deleteMlFilter id' =
  delete endpoint
  where
    endpoint = mkEndpoint ["_ml", "filters", unMlFilterId id']

-- =========================================================================
-- ML calendars and scheduled events (X-Pack)
-- =========================================================================

-- | 'putMlCalendar' builds the 'BHRequest' for
-- @PUT /_ml/calendars/{calendar_id}@ (ml-put-calendar), creating or
-- updating a calendar. Returns 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-put-calendar>.
putMlCalendar ::
  MlCalendarId ->
  MlCalendar ->
  BHRequest StatusDependant Acknowledged
putMlCalendar id' body =
  put @StatusDependant endpoint (encode body)
  where
    endpoint = mkEndpoint ["_ml", "calendars", unMlCalendarId id']

-- | 'getMlCalendars' builds the 'BHRequest' for
-- @GET /_ml/calendars[/{calendar_id}]@ (ml-get-calendars). Pass
-- 'Nothing' to list every calendar. Equivalent to
-- @'getMlCalendarsWith' mid 'defaultMlDatafeedOptions'@.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-get-calendars>.
getMlCalendars ::
  Maybe MlCalendarId ->
  BHRequest StatusDependant MlCalendarsResponse
getMlCalendars mid = getMlCalendarsWith mid defaultMlDatafeedOptions

-- | 'getMlCalendarsWith' is the fully-parameterised variant of
-- 'getMlCalendars'.
getMlCalendarsWith ::
  Maybe MlCalendarId ->
  MlDatafeedOptions ->
  BHRequest StatusDependant MlCalendarsResponse
getMlCalendarsWith mid opts =
  get @StatusDependant (endpoint `withQueries` mlDatafeedOptionsParams opts)
  where
    endpoint =
      mkEndpoint $
        ["_ml", "calendars"]
          ++ maybe [] (\(MlCalendarId x) -> [x]) mid

-- | 'deleteMlCalendar' builds the 'BHRequest' for
-- @DELETE /_ml/calendars/{calendar_id}@ (ml-delete-calendar). Returns
-- 'Acknowledged' on success.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-delete-calendar>.
deleteMlCalendar ::
  MlCalendarId ->
  BHRequest StatusDependant Acknowledged
deleteMlCalendar id' =
  delete endpoint
  where
    endpoint = mkEndpoint ["_ml", "calendars", unMlCalendarId id']

-- | 'setMlScheduledEvents' builds the 'BHRequest' for
-- @POST /_ml/calendars/{calendar_id}/events@ (ml-post-calendar-events),
-- adding (or replacing) scheduled events on a calendar. The response
-- echoes the stored events.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-post-calendar-event>.
setMlScheduledEvents ::
  MlCalendarId ->
  MlScheduledEvents ->
  BHRequest StatusDependant MlScheduledEventsResponse
setMlScheduledEvents id' body =
  post @StatusDependant endpoint (encode body)
  where
    endpoint =
      mkEndpoint ["_ml", "calendars", unMlCalendarId id', "events"]

-- | 'getMlScheduledEvents' builds the 'BHRequest' for
-- @GET /_ml/calendars/{calendar_id}/events@
-- (ml-get-calendar-events), listing the scheduled events on a calendar.
--
-- For more information see
-- <https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-ml-get-calendar-events>.
getMlScheduledEvents ::
  MlCalendarId ->
  BHRequest StatusDependant MlScheduledEventsResponse
getMlScheduledEvents id' =
  get @StatusDependant endpoint
  where
    endpoint =
      mkEndpoint ["_ml", "calendars", unMlCalendarId id', "events"]