import { JSONValue } from '../../json-value/json-value';
import { SharedV3ProviderOptions } from '../../shared/v3/shared-v3-provider-options';
import { LanguageModelV3DataContent } from './language-model-v3-data-content';

/**
 * A prompt is a list of messages.
 *
 * Note: Not all models and prompt formats support multi-modal inputs and
 * tool calls. The validation happens at runtime.
 *
 * Note: This is not a user-facing prompt. The AI SDK methods will map the
 * user-facing prompt types such as chat or instruction prompts to this format.
 */
export type LanguageModelV3Prompt = Array<LanguageModelV3Message>;

export type LanguageModelV3Message =
  // Note: there could be additional parts for each role in the future,
  // e.g. when the assistant can return images or the user can share files
  // such as PDFs.
  (
    | {
        role: 'system';
        content: string;
      }
    | {
        role: 'user';
        content: Array<LanguageModelV3TextPart | LanguageModelV3FilePart>;
      }
    | {
        role: 'assistant';
        content: Array<
          | LanguageModelV3TextPart
          | LanguageModelV3FilePart
          | LanguageModelV3ReasoningPart
          | LanguageModelV3ToolCallPart
          | LanguageModelV3ToolResultPart
        >;
      }
    | {
        role: 'tool';
        content: Array<
          | LanguageModelV3ToolResultPart
          | LanguageModelV3ToolApprovalResponsePart
        >;
      }
  ) & {
    /**
     * Additional provider-specific options. They are passed through
     * to the provider from the AI SDK and enable provider-specific
     * functionality that can be fully encapsulated in the provider.
     */
    providerOptions?: SharedV3ProviderOptions;
  };

/**
 * Text content part of a prompt. It contains a string of text.
 */
export interface LanguageModelV3TextPart {
  type: 'text';

  /**
   * The text content.
   */
  text: string;

  /**
   * Additional provider-specific options. They are passed through
   * to the provider from the AI SDK and enable provider-specific
   * functionality that can be fully encapsulated in the provider.
   */
  providerOptions?: SharedV3ProviderOptions;
}

/**
 * Reasoning content part of a prompt. It contains a string of reasoning text.
 */
export interface LanguageModelV3ReasoningPart {
  type: 'reasoning';

  /**
   * The reasoning text.
   */
  text: string;

  /**
   * Additional provider-specific options. They are passed through
   * to the provider from the AI SDK and enable provider-specific
   * functionality that can be fully encapsulated in the provider.
   */
  providerOptions?: SharedV3ProviderOptions;
}

/**
 * File content part of a prompt. It contains a file.
 */
export interface LanguageModelV3FilePart {
  type: 'file';

  /**
   * Optional filename of the file.
   */
  filename?: string;

  /**
   * File data. Can be a Uint8Array, base64 encoded data as a string or a URL.
   */
  data: LanguageModelV3DataContent;

  /**
   * IANA media type of the file.
   *
   * Can support wildcards, e.g. `image/*` (in which case the provider needs to take appropriate action).
   *
   * @see https://www.iana.org/assignments/media-types/media-types.xhtml
   */
  mediaType: string;

  /**
   * Additional provider-specific options. They are passed through
   * to the provider from the AI SDK and enable provider-specific
   * functionality that can be fully encapsulated in the provider.
   */
  providerOptions?: SharedV3ProviderOptions;
}

/**
 * Tool call content part of a prompt. It contains a tool call (usually generated by the AI model).
 */
export interface LanguageModelV3ToolCallPart {
  type: 'tool-call';

  /**
   * ID of the tool call. This ID is used to match the tool call with the tool result.
   */
  toolCallId: string;

  /**
   * Name of the tool that is being called.
   */
  toolName: string;

  /**
   * Arguments of the tool call. This is a JSON-serializable object that matches the tool's input schema.
   */
  input: unknown;

  /**
   * Whether the tool call will be executed by the provider.
   * If this flag is not set or is false, the tool call will be executed by the client.
   */
  providerExecuted?: boolean;

  /**
   * Additional provider-specific options. They are passed through
   * to the provider from the AI SDK and enable provider-specific
   * functionality that can be fully encapsulated in the provider.
   */
  providerOptions?: SharedV3ProviderOptions;
}

/**
 * Tool result content part of a prompt. It contains the result of the tool call with the matching ID.
 */
export interface LanguageModelV3ToolResultPart {
  type: 'tool-result';

  /**
   * ID of the tool call that this result is associated with.
   */
  toolCallId: string;

  /**
   * Name of the tool that generated this result.
   */
  toolName: string;

  /**
   * Result of the tool call.
   */
  output: LanguageModelV3ToolResultOutput;

  /**
   * Additional provider-specific options. They are passed through
   * to the provider from the AI SDK and enable provider-specific
   * functionality that can be fully encapsulated in the provider.
   */
  providerOptions?: SharedV3ProviderOptions;
}

/**
 * Tool approval response content part of a prompt. It contains the user's
 * decision to approve or deny a provider-executed tool call.
 */
export interface LanguageModelV3ToolApprovalResponsePart {
  type: 'tool-approval-response';

  /**
   * ID of the approval request that this response refers to.
   */
  approvalId: string;

  /**
   * Whether the approval was granted (true) or denied (false).
   */
  approved: boolean;

  /**
   * Optional reason for approval or denial.
   */
  reason?: string;

  /**
   * Additional provider-specific options. They are passed through
   * to the provider from the AI SDK and enable provider-specific
   * functionality that can be fully encapsulated in the provider.
   */
  providerOptions?: SharedV3ProviderOptions;
}

/**
 * Result of a tool call.
 */
export type LanguageModelV3ToolResultOutput =
  | {
      /**
       * Text tool output that should be directly sent to the API.
       */
      type: 'text';
      value: string;

      /**
       * Provider-specific options.
       */
      providerOptions?: SharedV3ProviderOptions;
    }
  | {
      type: 'json';
      value: JSONValue;

      /**
       * Provider-specific options.
       */
      providerOptions?: SharedV3ProviderOptions;
    }
  | {
      /**
       * Type when the user has denied the execution of the tool call.
       */
      type: 'execution-denied';

      /**
       * Optional reason for the execution denial.
       */
      reason?: string;

      /**
       * Provider-specific options.
       */
      providerOptions?: SharedV3ProviderOptions;
    }
  | {
      type: 'error-text';
      value: string;

      /**
       * Provider-specific options.
       */
      providerOptions?: SharedV3ProviderOptions;
    }
  | {
      type: 'error-json';
      value: JSONValue;

      /**
       * Provider-specific options.
       */
      providerOptions?: SharedV3ProviderOptions;
    }
  | {
      type: 'content';
      value: Array<
        | {
            type: 'text';

            /**
             * Text content.
             */
            text: string;

            /**
             * Provider-specific options.
             */
            providerOptions?: SharedV3ProviderOptions;
          }
        | {
            type: 'file-data';

            /**
             * Base-64 encoded media data.
             */
            data: string;

            /**
             * IANA media type.
             * @see https://www.iana.org/assignments/media-types/media-types.xhtml
             */
            mediaType: string;

            /**
             * Optional filename of the file.
             */
            filename?: string;

            /**
             * Provider-specific options.
             */
            providerOptions?: SharedV3ProviderOptions;
          }
        | {
            type: 'file-url';

            /**
             * URL of the file.
             */
            url: string;

            /**
             * Provider-specific options.
             */
            providerOptions?: SharedV3ProviderOptions;
          }
        | {
            type: 'file-id';

            /**
             * ID of the file.
             *
             * If you use multiple providers, you need to
             * specify the provider specific ids using
             * the Record option. The key is the provider
             * name, e.g. 'openai' or 'anthropic'.
             */
            fileId: string | Record<string, string>;

            /**
             * Provider-specific options.
             */
            providerOptions?: SharedV3ProviderOptions;
          }
        | {
            /**
             * Images that are referenced using base64 encoded data.
             */
            type: 'image-data';

            /**
             * Base-64 encoded image data.
             */
            data: string;

            /**
             * IANA media type.
             * @see https://www.iana.org/assignments/media-types/media-types.xhtml
             */
            mediaType: string;

            /**
             * Provider-specific options.
             */
            providerOptions?: SharedV3ProviderOptions;
          }
        | {
            /**
             * Images that are referenced using a URL.
             */
            type: 'image-url';

            /**
             * URL of the image.
             */
            url: string;

            /**
             * Provider-specific options.
             */
            providerOptions?: SharedV3ProviderOptions;
          }
        | {
            /**
             * Images that are referenced using a provider file id.
             */
            type: 'image-file-id';

            /**
             * Image that is referenced using a provider file id.
             *
             * If you use multiple providers, you need to
             * specify the provider specific ids using
             * the Record option. The key is the provider
             * name, e.g. 'openai' or 'anthropic'.
             */
            fileId: string | Record<string, string>;

            /**
             * Provider-specific options.
             */
            providerOptions?: SharedV3ProviderOptions;
          }
        | {
            /**
             * Custom content part. This can be used to implement
             * provider-specific content parts.
             */
            type: 'custom';

            /**
             * Provider-specific options.
             */
            providerOptions?: SharedV3ProviderOptions;
          }
      >;
    };
