import {
  makeAnthropicAdapter,
  type AnthropicCreds,
} from '@platform-modules/ai/anthropic'
import {
  makeOpenAiCompatAdapter,
  type OpenAiCompatCreds,
} from '@platform-modules/ai/openai-compat'
import {
  makeGoogleAdapter,
  type GoogleCreds,
  type GoogleGenAIClient,
} from '@platform-modules/ai/google'
import { AnthropicAdapter } from '../../../../../packages/ai/src/adapters/anthropic'
import { GoogleAdapter } from '../../../../../packages/ai/src/adapters/google'
import { OpenAIAdapter } from '../../../../../packages/ai/src/adapters/openai'
import type {
  AIAdapter,
  AIRequest,
  AIResponse,
} from '../../../../../packages/ai/src/adapter'
import type { AIEnv } from '../../../../../packages/ai/src/adapters/index'
import type { AIRequest as PlatformAIRequest } from '@platform-modules/ai'

type Provider = 'anthropic' | 'openai' | 'google'

type PlatformAiTestOverrides = {
  anthropicFetch?: typeof fetch
  openAiFetch?: typeof fetch
  createGoogleClient?: (apiKey: string) => GoogleGenAIClient
}

function mapRequest(request: AIRequest): PlatformAIRequest {
  return {
    model: request.model,
    messages: request.messages as PlatformAIRequest['messages'],
    ...('maxTokens' in request && request.maxTokens !== undefined ? { maxTokens: request.maxTokens } : {}),
    ...(request.temperature !== undefined ? { temperature: request.temperature } : {}),
  }
}

function mapResponse(response: {
  content: string
  model: string
  provider: string
  usage: {
    promptTokens: number
    completionTokens: number
  }
}): AIResponse {
  return {
    content: response.content,
    inputTokens: response.usage.promptTokens,
    outputTokens: response.usage.completionTokens,
    model: response.model,
    provider: response.provider === 'openai-compat' ? 'openai' : response.provider,
    durationMs: 0,
  }
}

function getStreamAdapter(env: AIEnv, provider: Provider): AIAdapter {
  switch (provider) {
    case 'anthropic':
      return new AnthropicAdapter(env)
    case 'openai':
      return new OpenAIAdapter(env)
    case 'google':
      return new GoogleAdapter(env)
  }
}

function buildPlatformAdapter(
  env: AIEnv,
  provider: Provider,
  overrides?: PlatformAiTestOverrides,
) {
  switch (provider) {
    case 'anthropic':
      return makeAnthropicAdapter({
        apiKey: env.ANTHROPIC_API_KEY,
        ...(overrides?.anthropicFetch ? { fetch: overrides.anthropicFetch } : {}),
      } satisfies AnthropicCreds)
    case 'openai':
      return makeOpenAiCompatAdapter({
        apiKey: env.OPENAI_API_KEY,
        ...(overrides?.openAiFetch ? { fetch: overrides.openAiFetch } : {}),
      } satisfies OpenAiCompatCreds)
    case 'google':
      return makeGoogleAdapter({
        apiKey: env.GOOGLE_AI_API_KEY,
        ...(overrides?.createGoogleClient
          ? { createClient: overrides.createGoogleClient }
          : {}),
      } satisfies GoogleCreds)
  }
}

export function getAiAdapter(
  env: AIEnv,
  provider: Provider,
  overrides?: PlatformAiTestOverrides,
): AIAdapter {
  const platformAdapter = buildPlatformAdapter(env, provider, overrides)
  const streamAdapter = getStreamAdapter(env, provider)

  return {
    provider,
    async call(request: AIRequest): Promise<AIResponse> {
      const response = await platformAdapter.call(mapRequest(request))
      return mapResponse(response)
    },
    stream(request: AIRequest): ReadableStream<string> {
      return streamAdapter.stream(request)
    },
  }
}
