import type { JSONObject, JSONValue, LanguageModelV3, LanguageModelV3Prompt } from '@ai-sdk/provider';
import type { ISmartAiCacheOptions } from './smartai.cache.js';

export type TProvider =
  | 'anthropic'
  | 'openai'
  | 'google'
  | 'groq'
  | 'mistral'
  | 'xai'
  | 'perplexity'
  | 'ollama';

export type TOpenAiReasoningEffort = 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';

export type TOpenAiTextVerbosity = 'low' | 'medium' | 'high';

export interface IOpenAiChatGptTokenInfo {
  email?: string;
  chatgptPlanType?: string;
  chatgptUserId?: string;
  chatgptAccountId?: string;
  chatgptAccountIsFedramp: boolean;
  expiresAt?: string;
  rawJwt: string;
}

export interface IOpenAiChatGptAuthCredentials {
  accessToken: string;
  refreshToken?: string;
  idToken?: string;
  accountId?: string;
  tokenInfo?: IOpenAiChatGptTokenInfo;
  baseUrl?: string;
  originator?: string;
}

export interface IOpenAiChatGptTokenData extends IOpenAiChatGptAuthCredentials {
  refreshToken: string;
  tokenInfo: IOpenAiChatGptTokenInfo;
}

export interface IOpenAiChatGptDeviceCode {
  verificationUrl: string;
  userCode: string;
  deviceAuthId: string;
  intervalSeconds: number;
}

export interface IOpenAiChatGptAuthOptions {
  issuer?: string;
  clientId?: string;
  fetch?: typeof fetch;
}

export interface IOpenAiChatGptDeviceCodePollOptions extends IOpenAiChatGptAuthOptions {
  timeoutMs?: number;
  sleep?: (ms: number) => Promise<void>;
}

export interface IOpenAiChatGptCompleteDeviceCodeOptions extends IOpenAiChatGptDeviceCodePollOptions {
  forcedChatGptWorkspaceId?: string;
}

export interface IOpenAiProviderOptions extends JSONObject {
  conversation?: string | null;
  include?: string[] | null;
  instructions?: string | null;
  logitBias?: Record<string, number>;
  logprobs?: boolean | number | null;
  maxCompletionTokens?: number;
  maxToolCalls?: number | null;
  metadata?: JSONObject | null;
  parallelToolCalls?: boolean | null;
  previousResponseId?: string | null;
  prediction?: JSONObject;
  promptCacheKey?: string | null;
  promptCacheRetention?: 'in_memory' | '24h' | null;
  reasoningEffort?: TOpenAiReasoningEffort | null;
  reasoningSummary?: string | null;
  safetyIdentifier?: string | null;
  serviceTier?: 'auto' | 'flex' | 'priority' | 'default' | null;
  store?: boolean | null;
  strictJsonSchema?: boolean | null;
  systemMessageMode?: 'remove' | 'system' | 'developer';
  textVerbosity?: TOpenAiTextVerbosity | null;
  truncation?: 'auto' | 'disabled' | null;
  user?: string | null;
  forceReasoning?: boolean;
  [key: string]: JSONValue | undefined;
}

export type TSmartAiProviderOptions = Record<string, JSONObject> & {
  openai?: IOpenAiProviderOptions;
};

export interface ISmartAiModelSetup {
  model: LanguageModelV3;
  providerOptions?: TSmartAiProviderOptions;
}

export interface ISmartAiOptions {
  provider: TProvider;
  model: string;
  apiKey?: string;
  /**
   * OpenAI ChatGPT/Codex subscription credentials from the device-code auth flow.
   * Only used when provider === 'openai'.
   */
  openAiChatGptAuth?: IOpenAiChatGptAuthCredentials;
  /**
   * Provider-specific AI SDK generation options.
   * Pass this to generateText()/streamText() alongside the model.
   */
  providerOptions?: TSmartAiProviderOptions;
  /** For Ollama: base URL of the local server. Default: http://localhost:11434 */
  baseUrl?: string;
  /**
   * Ollama-specific model runtime options.
   * Only used when provider === 'ollama'.
   */
  ollamaOptions?: IOllamaModelOptions;
  /**
   * Enable Anthropic prompt caching on system + recent messages.
   * Only used when provider === 'anthropic'. Default: true.
   */
  promptCaching?: boolean | ISmartAiCacheOptions;
}

/**
 * Ollama model runtime options passed in the request body `options` field.
 * @see https://github.com/ollama/ollama/blob/main/docs/modelfile.md
 */
export interface IOllamaModelOptions {
  /** Context window size. Default: 2048. */
  num_ctx?: number;
  /** 0 = deterministic. Default: 0.8. For Qwen models use 0.55. */
  temperature?: number;
  top_k?: number;
  top_p?: number;
  repeat_penalty?: number;
  num_predict?: number;
  stop?: string[];
  seed?: number;
  /**
   * Enable thinking/reasoning mode (Qwen3, QwQ, DeepSeek-R1 etc.).
   * The custom Ollama provider handles this directly.
   */
  think?: boolean;
}

export type { LanguageModelV3, LanguageModelV3Prompt };
