/*
 * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
 */

import { LaunchDarklyCore } from "../core.js";
import { encodeJSON, encodeSimple } from "../lib/encodings.js";
import * as M from "../lib/matchers.js";
import { compactMap } from "../lib/primitives.js";
import { safeParse } from "../lib/schemas.js";
import { RequestOptions } from "../lib/sdks.js";
import { extractSecurity, resolveGlobalSecurity } from "../lib/security.js";
import { pathToFunc } from "../lib/url.js";
import * as components from "../models/components/index.js";
import {
  ConnectionError,
  InvalidRequestError,
  RequestAbortedError,
  RequestTimeoutError,
  UnexpectedClientError,
} from "../models/errors/httpclienterrors.js";
import * as errors from "../models/errors/index.js";
import { LaunchDarklyError } from "../models/errors/launchdarklyerror.js";
import { ResponseValidationError } from "../models/errors/responsevalidationerror.js";
import { SDKValidationError } from "../models/errors/sdkvalidationerror.js";
import * as operations from "../models/operations/index.js";
import { APICall, APIPromise } from "../types/async.js";
import { Result } from "../types/fp.js";

/**
 * Update AI Config targeting
 *
 * @remarks
 * Perform a partial update to an AI Config's targeting. The request body must be a valid semantic patch.
 *
 * ### Using semantic patches on an AI Config
 *
 * To make a semantic patch request, you must append `domain-model=launchdarkly.semanticpatch` to your `Content-Type` header. To learn more, read [Updates using semantic patch](https://launchdarkly.com/docs/api#updates-using-semantic-patch).
 *
 * The body of a semantic patch request for updating an AI Config's targeting takes the following properties:
 *
 * * `comment` (string): (Optional) A description of the update.
 * * `environmentKey` (string): The key of the LaunchDarkly environment.
 * * `instructions` (array): (Required) A list of actions the update should perform. Each action in the list must be an object with a `kind` property that indicates the instruction. If the action requires parameters, you must include those parameters as additional fields in the object. The body of a single semantic patch can contain many different instructions.
 *
 * ### Instructions
 *
 * Semantic patch requests support the following `kind` instructions for updating AI Configs.
 *
 * <details>
 * <summary>Click to expand instructions for <strong>working with targeting and variations</strong> for AI Configs</summary>
 *
 * #### addClauses
 *
 * Adds the given clauses to the rule indicated by `ruleId`.
 *
 * ##### Parameters
 *
 * - `ruleId`: ID of a rule in the AI Config.
 * - `clauses`: Array of clause objects, with `contextKind` (string), `attribute` (string), `op` (string), `negate` (boolean), and `values` (array of strings, numbers, or dates) properties. The `contextKind`, `attribute`, and `values` are case sensitive. The `op` must be lower-case.
 *
 * Here's an example:
 *
 * ```json
 * {
 *   "environmentKey": "environment-key-123abc",
 *   "instructions": [{
 *     "kind": "addClauses",
 *     "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29",
 *     "clauses": [{
 *       "contextKind": "user",
 *       "attribute": "country",
 *       "op": "in",
 *       "negate": false,
 *       "values": ["USA", "Canada"]
 *     }]
 *   }]
 * }
 * ```
 *
 * #### addRule
 *
 * Adds a new targeting rule to the AI Config. The rule may contain `clauses` and serve the variation that `variationId` indicates, or serve a percentage rollout that `rolloutWeights`, `rolloutBucketBy`, and `rolloutContextKind` indicate.
 *
 * If you set `beforeRuleId`, this adds the new rule before the indicated rule. Otherwise, adds the new rule to the end of the list.
 *
 * ##### Parameters
 *
 * - `clauses`: Array of clause objects, with `contextKind` (string), `attribute` (string), `op` (string), `negate` (boolean), and `values` (array of strings, numbers, or dates) properties. The `contextKind`, `attribute`, and `values` are case sensitive. The `op` must be lower-case.
 * - `beforeRuleId`: (Optional) ID of a rule.
 * - Either
 * - `variationId`: ID of a variation.
 *
 * or
 *
 * - `rolloutWeights`: (Optional) Map of `variationId` to weight, in thousandths of a percent (0-100000).
 * - `rolloutBucketBy`: (Optional) Context attribute available in the specified `rolloutContextKind`.
 * - `rolloutContextKind`: (Optional) Context kind, defaults to `user`
 *
 * Here's an example that uses a `variationId`:
 *
 * ```json
 * {
 * "environmentKey": "environment-key-123abc",
 * "instructions": [{
 *   "kind": "addRule",
 *   "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00",
 *   "clauses": [{
 *     "contextKind": "organization",
 *     "attribute": "located_in",
 *     "op": "in",
 *     "negate": false,
 *     "values": ["Sweden", "Norway"]
 *   }]
 * }]
 * }
 * ```
 *
 * Here's an example that uses a percentage rollout:
 *
 * ```json
 * {
 * "environmentKey": "environment-key-123abc",
 * "instructions": [{
 *   "kind": "addRule",
 *   "clauses": [{
 *     "contextKind": "organization",
 *     "attribute": "located_in",
 *     "op": "in",
 *     "negate": false,
 *     "values": ["Sweden", "Norway"]
 *   }],
 *   "rolloutContextKind": "organization",
 *   "rolloutWeights": {
 *     "2f43f67c-3e4e-4945-a18a-26559378ca00": 15000, // serve 15% this variation
 *     "e5830889-1ec5-4b0c-9cc9-c48790090c43": 85000  // serve 85% this variation
 *   }
 * }]
 * }
 * ```
 *
 * #### addTargets
 *
 * Adds context keys to the individual context targets for the context kind that `contextKind` specifies and the variation that `variationId` specifies. Returns an error if this causes the AI Config to target the same context key in multiple variations.
 *
 * ##### Parameters
 *
 * - `values`: List of context keys.
 * - `contextKind`: (Optional) Context kind to target, defaults to `user`
 * - `variationId`: ID of a variation.
 *
 * Here's an example:
 *
 * ```json
 * {
 * "environmentKey": "environment-key-123abc",
 * "instructions": [{
 *   "kind": "addTargets",
 *   "values": ["context-key-123abc", "context-key-456def"],
 *   "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00"
 * }]
 * }
 * ```
 *
 * #### addValuesToClause
 *
 * Adds `values` to the values of the clause that `ruleId` and `clauseId` indicate. Does not update the context kind, attribute, or operator.
 *
 * ##### Parameters
 *
 * - `ruleId`: ID of a rule in the AI Config.
 * - `clauseId`: ID of a clause in that rule.
 * - `values`: Array of strings, case sensitive.
 *
 * Here's an example:
 *
 * ```json
 * {
 * "environmentKey": "environment-key-123abc",
 * "instructions": [{
 *   "kind": "addValuesToClause",
 *   "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29",
 *   "clauseId": "10a58772-3121-400f-846b-b8a04e8944ed",
 *   "values": ["beta_testers"]
 * }]
 * }
 * ```
 *
 * #### clearTargets
 *
 * Removes all individual targets from the variation that `variationId` specifies. This includes both user and non-user targets.
 *
 * ##### Parameters
 *
 * - `variationId`: ID of a variation.
 *
 * Here's an example:
 *
 * ```json
 * {
 * "environmentKey": "environment-key-123abc",
 * "instructions": [ { "kind": "clearTargets", "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" } ]
 * }
 * ```
 *
 * #### removeClauses
 *
 * Removes the clauses specified by `clauseIds` from the rule indicated by `ruleId`.
 *
 * ##### Parameters
 *
 * - `ruleId`: ID of a rule.
 * - `clauseIds`: Array of IDs of clauses in the rule.
 *
 * Here's an example:
 *
 * ```json
 * {
 * "environmentKey": "environment-key-123abc",
 * "instructions": [{
 *   "kind": "removeClauses",
 *   "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29",
 *   "clauseIds": ["10a58772-3121-400f-846b-b8a04e8944ed", "36a461dc-235e-4b08-97b9-73ce9365873e"]
 * }]
 * }
 * ```
 *
 * #### removeRule
 *
 * Removes the targeting rule specified by `ruleId`. Does nothing if the rule does not exist.
 *
 * ##### Parameters
 *
 * - `ruleId`: ID of a rule.
 *
 * Here's an example:
 *
 * ```json
 * {
 * "environmentKey": "environment-key-123abc",
 * "instructions": [ { "kind": "removeRule", "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29" } ]
 * }
 * ```
 *
 * #### removeTargets
 *
 * Removes context keys from the individual context targets for the context kind that `contextKind` specifies and the variation that `variationId` specifies. Does nothing if the flag does not target the context keys.
 *
 * ##### Parameters
 *
 * - `values`: List of context keys.
 * - `contextKind`: (Optional) Context kind to target, defaults to `user`
 * - `variationId`: ID of a variation.
 *
 * Here's an example:
 *
 * ```json
 * {
 * "environmentKey": "environment-key-123abc",
 * "instructions": [{
 *   "kind": "removeTargets",
 *   "values": ["context-key-123abc", "context-key-456def"],
 *   "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00"
 * }]
 * }
 * ```
 *
 * #### removeValuesFromClause
 *
 * Removes `values` from the values of the clause indicated by `ruleId` and `clauseId`. Does not update the context kind, attribute, or operator.
 *
 * ##### Parameters
 *
 * - `ruleId`: ID of a rule.
 * - `clauseId`: ID of a clause in that rule.
 * - `values`: Array of strings, case sensitive.
 *
 * Here's an example:
 *
 * ```json
 * {
 * "environmentKey": "environment-key-123abc",
 * "instructions": [{
 *   "kind": "removeValuesFromClause",
 *   "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29",
 *   "clauseId": "10a58772-3121-400f-846b-b8a04e8944ed",
 *   "values": ["beta_testers"]
 * }]
 * }
 * ```
 *
 * #### reorderRules
 *
 * Rearranges the rules to match the order given in `ruleIds`. Returns an error if `ruleIds` does not match the current set of rules on the AI Config.
 *
 * ##### Parameters
 *
 * - `ruleIds`: Array of IDs of all rules.
 *
 * Here's an example:
 *
 * ```json
 * {
 * "environmentKey": "environment-key-123abc",
 * "instructions": [{
 *   "kind": "reorderRules",
 *   "ruleIds": ["a902ef4a-2faf-4eaf-88e1-ecc356708a29", "63c238d1-835d-435e-8f21-c8d5e40b2a3d"]
 * }]
 * }
 * ```
 *
 * #### replaceRules
 *
 * Removes all targeting rules for the AI Config and replaces them with the list you provide.
 *
 * ##### Parameters
 *
 * - `rules`: A list of rules.
 *
 * Here's an example:
 *
 * ```json
 * {
 * "environmentKey": "environment-key-123abc",
 * "instructions": [
 *   {
 *     "kind": "replaceRules",
 *     "rules": [
 *       {
 *         "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00",
 *         "description": "My new rule",
 *         "clauses": [
 *           {
 *             "contextKind": "user",
 *             "attribute": "segmentMatch",
 *             "op": "segmentMatch",
 *             "values": ["test"]
 *           }
 *         ]
 *       }
 *     ]
 *   }
 * ]
 * }
 * ```
 *
 * #### replaceTargets
 *
 * Removes all existing targeting and replaces it with the list of targets you provide.
 *
 * ##### Parameters
 *
 * - `targets`: A list of context targeting. Each item in the list includes an optional `contextKind` that defaults to `user`, a required `variationId`, and a required list of `values`.
 *
 * Here's an example:
 *
 * ```json
 * {
 * "environmentKey": "environment-key-123abc",
 * "instructions": [
 *   {
 *     "kind": "replaceTargets",
 *     "targets": [
 *       {
 *         "contextKind": "user",
 *         "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00",
 *         "values": ["user-key-123abc"]
 *       },
 *       {
 *         "contextKind": "device",
 *         "variationId": "e5830889-1ec5-4b0c-9cc9-c48790090c43",
 *         "values": ["device-key-456def"]
 *       }
 *     ]
 *   }
 * ]
 * }
 * ```
 *
 * #### updateClause
 *
 * Replaces the clause indicated by `ruleId` and `clauseId` with `clause`.
 *
 * ##### Parameters
 *
 * - `ruleId`: ID of a rule.
 * - `clauseId`: ID of a clause in that rule.
 * - `clause`: New `clause` object, with `contextKind` (string), `attribute` (string), `op` (string), `negate` (boolean), and `values` (array of strings, numbers, or dates) properties. The `contextKind`, `attribute`, and `values` are case sensitive. The `op` must be lower-case.
 *
 * Here's an example:
 *
 * ```json
 * {
 * "environmentKey": "environment-key-123abc",
 * "instructions": [{
 *   "kind": "updateClause",
 *   "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29",
 *   "clauseId": "10c7462a-2062-45ba-a8bb-dfb3de0f8af5",
 *   "clause": {
 *     "contextKind": "user",
 *     "attribute": "country",
 *     "op": "in",
 *     "negate": false,
 *     "values": ["Mexico", "Canada"]
 *   }
 * }]
 * }
 * ```
 *
 * #### updateDefaultVariation
 *
 * Updates the default on or off variation of the AI Config.
 *
 * ##### Parameters
 *
 * - `onVariationValue`: (Optional) The value of the variation of the new on variation.
 * - `offVariationValue`: (Optional) The value of the variation of the new off variation
 *
 * Here's an example:
 *
 * ```json
 * {
 * "instructions": [ { "kind": "updateDefaultVariation", "OnVariationValue": true, "OffVariationValue": false } ]
 * }
 * ```
 *
 * #### updateFallthroughVariationOrRollout
 *
 * Updates the default or "fallthrough" rule for the AI Config, which the AI Config serves when a context matches none of the targeting rules. The rule can serve either the variation that `variationId` indicates, or a percentage rollout that `rolloutWeights` and `rolloutBucketBy` indicate.
 *
 * ##### Parameters
 *
 * - `variationId`: ID of a variation.
 *
 * or
 *
 * - `rolloutWeights`: Map of `variationId` to weight, in thousandths of a percent (0-100000).
 * - `rolloutBucketBy`: (Optional) Context attribute available in the specified `rolloutContextKind`.
 * - `rolloutContextKind`: (Optional) Context kind, defaults to `user`
 *
 * Here's an example that uses a `variationId`:
 *
 * ```json
 * {
 * "environmentKey": "environment-key-123abc",
 * "instructions": [{
 *   "kind": "updateFallthroughVariationOrRollout",
 *   "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00"
 * }]
 * }
 * ```
 *
 * Here's an example that uses a percentage rollout:
 *
 * ```json
 * {
 * "environmentKey": "environment-key-123abc",
 * "instructions": [{
 *   "kind": "updateFallthroughVariationOrRollout",
 *   "rolloutContextKind": "user",
 *   "rolloutWeights": {
 *     "2f43f67c-3e4e-4945-a18a-26559378ca00": 15000, // serve 15% this variation
 *     "e5830889-1ec5-4b0c-9cc9-c48790090c43": 85000  // serve 85% this variation
 *   }
 * }]
 * }
 * ```
 *
 * #### updateOffVariation
 *
 * Updates the default off variation to `variationId`. The AI Config serves the default off variation when the AI Config's targeting is **Off**.
 *
 * ##### Parameters
 *
 * - `variationId`: ID of a variation.
 *
 * Here's an example:
 *
 * ```json
 * {
 * "environmentKey": "environment-key-123abc",
 * "instructions": [ { "kind": "updateOffVariation", "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00" } ]
 * }
 * ```
 *
 * #### updateRuleDescription
 *
 * Updates the description of the targeting rule.
 *
 * ##### Parameters
 *
 * - `description`: The new human-readable description for this rule.
 * - `ruleId`: The ID of the rule. You can retrieve this by making a GET request for the AI Config.
 *
 * Here's an example:
 *
 * ```json
 * {
 * "environmentKey": "environment-key-123abc",
 * "instructions": [{
 *   "kind": "updateRuleDescription",
 *   "description": "New rule description",
 *   "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29"
 * }]
 * }
 * ```
 *
 * #### updateRuleTrackEvents
 *
 * Updates whether or not LaunchDarkly tracks events for the AI Config associated with this rule.
 *
 * ##### Parameters
 *
 * - `ruleId`: The ID of the rule. You can retrieve this by making a GET request for the AI Config.
 * - `trackEvents`: Whether or not events are tracked.
 *
 * Here's an example:
 *
 * ```json
 * {
 * "environmentKey": "environment-key-123abc",
 * "instructions": [{
 *   "kind": "updateRuleTrackEvents",
 *   "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29",
 *   "trackEvents": true
 * }]
 * }
 * ```
 *
 * #### updateRuleVariationOrRollout
 *
 * Updates what `ruleId` serves when its clauses evaluate to true. The rule can serve either the variation that `variationId` indicates, or a percent rollout that `rolloutWeights` and `rolloutBucketBy` indicate.
 *
 * ##### Parameters
 *
 * - `ruleId`: ID of a rule.
 * - `variationId`: ID of a variation.
 *
 * or
 *
 * - `rolloutWeights`: Map of `variationId` to weight, in thousandths of a percent (0-100000).
 * - `rolloutBucketBy`: (Optional) Context attribute available in the specified `rolloutContextKind`.
 * - `rolloutContextKind`: (Optional) Context kind, defaults to `user`
 *
 * Here's an example:
 *
 * ```json
 * {
 * "environmentKey": "environment-key-123abc",
 * "instructions": [{
 *   "kind": "updateRuleVariationOrRollout",
 *   "ruleId": "a902ef4a-2faf-4eaf-88e1-ecc356708a29",
 *   "variationId": "2f43f67c-3e4e-4945-a18a-26559378ca00"
 * }]
 * }
 * ```
 *
 * #### updateTrackEvents
 *
 * Updates whether or not LaunchDarkly tracks events for the AI Config, for all rules.
 *
 * ##### Parameters
 *
 * - `trackEvents`: Whether or not events are tracked.
 *
 * Here's an example:
 *
 * ```json
 * {
 * "environmentKey": "environment-key-123abc",
 * "instructions": [ { "kind": "updateTrackEvents", "trackEvents": true } ]
 * }
 * ```
 *
 * #### updateTrackEventsFallthrough
 *
 * Updates whether or not LaunchDarkly tracks events for the AI Config, for the default rule.
 *
 * ##### Parameters
 *
 * - `trackEvents`: Whether or not events are tracked.
 *
 * Here's an example:
 *
 * ```json
 * {
 * "environmentKey": "environment-key-123abc",
 * "instructions": [ { "kind": "updateTrackEventsFallthrough", "trackEvents": true } ]
 * }
 * ```
 * </details>
 */
export function aiConfigsUpdateTargeting(
  client: LaunchDarklyCore,
  request: operations.PatchAIConfigTargetingRequest,
  options?: RequestOptions,
): APIPromise<
  Result<
    components.AIConfigTargeting,
    | errors.ErrorT
    | LaunchDarklyError
    | ResponseValidationError
    | ConnectionError
    | RequestAbortedError
    | RequestTimeoutError
    | InvalidRequestError
    | UnexpectedClientError
    | SDKValidationError
  >
> {
  return new APIPromise($do(
    client,
    request,
    options,
  ));
}

async function $do(
  client: LaunchDarklyCore,
  request: operations.PatchAIConfigTargetingRequest,
  options?: RequestOptions,
): Promise<
  [
    Result<
      components.AIConfigTargeting,
      | errors.ErrorT
      | LaunchDarklyError
      | ResponseValidationError
      | ConnectionError
      | RequestAbortedError
      | RequestTimeoutError
      | InvalidRequestError
      | UnexpectedClientError
      | SDKValidationError
    >,
    APICall,
  ]
> {
  const parsed = safeParse(
    request,
    (value) =>
      operations.PatchAIConfigTargetingRequest$outboundSchema.parse(value),
    "Input validation failed",
  );
  if (!parsed.ok) {
    return [parsed, { status: "invalid" }];
  }
  const payload = parsed.value;
  const body = encodeJSON("body", payload.AIConfigTargetingPatch, {
    explode: true,
  });

  const pathParams = {
    configKey: encodeSimple("configKey", payload.configKey, {
      explode: false,
      charEncoding: "percent",
    }),
    projectKey: encodeSimple("projectKey", payload.projectKey, {
      explode: false,
      charEncoding: "percent",
    }),
  };

  const path = pathToFunc(
    "/api/v2/projects/{projectKey}/ai-configs/{configKey}/targeting",
  )(pathParams);

  const headers = new Headers(compactMap({
    "Content-Type": "application/json",
    Accept: "application/json",
  }));

  const secConfig = await extractSecurity(client._options.apiKey);
  const securityInput = secConfig == null ? {} : { apiKey: secConfig };
  const requestSecurity = resolveGlobalSecurity(securityInput);

  const context = {
    options: client._options,
    baseURL: options?.serverURL ?? client._baseURL ?? "",
    operationID: "patchAIConfigTargeting",
    oAuth2Scopes: null,

    resolvedSecurity: requestSecurity,

    securitySource: client._options.apiKey,
    retryConfig: options?.retries
      || client._options.retryConfig
      || { strategy: "none" },
    retryCodes: options?.retryCodes || ["429", "500", "502", "503", "504"],
  };

  const requestRes = client._createRequest(context, {
    security: requestSecurity,
    method: "PATCH",
    baseURL: options?.serverURL,
    path: path,
    headers: headers,
    body: body,
    userAgent: client._options.userAgent,
    timeoutMs: options?.timeoutMs || client._options.timeoutMs || -1,
  }, options);
  if (!requestRes.ok) {
    return [requestRes, { status: "invalid" }];
  }
  const req = requestRes.value;

  const doResult = await client._do(req, {
    context,
    errorCodes: ["400", "403", "404", "4XX", "500", "5XX"],
    retryConfig: context.retryConfig,
    retryCodes: context.retryCodes,
  });
  if (!doResult.ok) {
    return [doResult, { status: "request-error", request: req }];
  }
  const response = doResult.value;

  const responseFields = {
    HttpMeta: { Response: response, Request: req },
  };

  const [result] = await M.match<
    components.AIConfigTargeting,
    | errors.ErrorT
    | LaunchDarklyError
    | ResponseValidationError
    | ConnectionError
    | RequestAbortedError
    | RequestTimeoutError
    | InvalidRequestError
    | UnexpectedClientError
    | SDKValidationError
  >(
    M.json(200, components.AIConfigTargeting$inboundSchema),
    M.jsonErr([400, 403, 404], errors.ErrorT$inboundSchema),
    M.jsonErr(500, errors.ErrorT$inboundSchema),
    M.fail("4XX"),
    M.fail("5XX"),
  )(response, req, { extraFields: responseFields });
  if (!result.ok) {
    return [result, { status: "complete", request: req, response }];
  }

  return [result, { status: "complete", request: req, response }];
}
