export type EnvironmentVariables = Partial<Record<string, string | undefined>>

export type AiRuntimeConfig =
  | {
      provider: 'mock'
      mode: 'mock'
      model: string
      chatModel?: string
      embeddingModel?: string
    }
  | {
      provider: 'qiniu' | 'deepseek' | 'openai-compatible'
      mode: 'openai-compatible'
      apiKey: string
      baseUrl: string
      embeddingApiKey?: string
      embeddingBaseUrl?: string
      model: string
      chatModel?: string
      embeddingModel?: string
      maxTokens?: number
      providerLabel: string
      reasoningEffort?: 'low' | 'medium' | 'high'
      thinkingEnabled?: boolean
    }

function readRequiredValue(
  env: EnvironmentVariables,
  key: string,
  errorMessage: string,
): string {
  const value = env[key]?.trim()

  if (!value) {
    throw new Error(errorMessage)
  }

  return value
}

function readRequiredSecret(
  env: EnvironmentVariables,
  key: string,
  errorMessage: string,
): string {
  const value = readRequiredValue(env, key, errorMessage)

  if (value === 'replace-with-your-own-key') {
    throw new Error(
      `${key} is still a placeholder; set a real API key or use AI_PROVIDER=mock`,
    )
  }

  return value
}

function readOptionalSecret(
  env: EnvironmentVariables,
  key: string,
): string | undefined {
  const value = readOptionalValue(env, key)

  if (!value) {
    return undefined
  }

  if (value === 'replace-with-your-own-key') {
    throw new Error(
      `${key} is still a placeholder; set a real API key or remove this override`,
    )
  }

  return value
}

function readOptionalValue(env: EnvironmentVariables, key: string): string | undefined {
  const value = env[key]?.trim()

  return value ? value : undefined
}

function normalizeBaseUrl(value: string | undefined): string | undefined {
  return value?.trim().replace(/\/$/, '')
}

function isSameBaseUrl(
  left: string | undefined,
  right: string | undefined,
): boolean {
  return Boolean(left && right && normalizeBaseUrl(left) === normalizeBaseUrl(right))
}

function isDashScopeCompatibleBaseUrl(value: string | undefined): boolean {
  return normalizeBaseUrl(value)?.includes('dashscope.aliyuncs.com/compatible-mode') ?? false
}

function readOptionalBoolean(
  env: EnvironmentVariables,
  key: string,
): boolean | undefined {
  const value = readOptionalValue(env, key)?.toLowerCase()

  if (!value) {
    return undefined
  }

  return ['1', 'true', 'yes', 'on'].includes(value)
}

function readOptionalPositiveInteger(
  env: EnvironmentVariables,
  key: string,
): number | undefined {
  const value = readOptionalValue(env, key)

  if (!value) {
    return undefined
  }

  const parsedValue = Number.parseInt(value, 10)

  return Number.isInteger(parsedValue) && parsedValue > 0 ? parsedValue : undefined
}

function readOptionalReasoningEffort(
  env: EnvironmentVariables,
  key: string,
): 'low' | 'medium' | 'high' | undefined {
  const value = readOptionalValue(env, key)?.toLowerCase()

  return value === 'low' || value === 'medium' || value === 'high' ? value : undefined
}

function resolveSharedEmbeddingOverride(env: EnvironmentVariables): {
  embeddingApiKey?: string
  embeddingBaseUrl?: string
  embeddingModel?: string
} {
  const embeddingBaseUrl =
    readOptionalValue(env, 'EMBEDDINGS_BASE_URL') ??
    readOptionalValue(env, 'EMBEDDINGS_URL')
  const embeddingApiKey =
    readOptionalSecret(env, 'EMBEDDINGS_API_KEY') ??
    readOptionalSecret(env, 'DASHSCOPE_API_KEY') ??
    readOptionalSecret(env, 'QWEN_API_KEY') ??
    resolveOpenAiCompatibleEmbeddingAlias(env, embeddingBaseUrl)
  const embeddingModel =
    readOptionalValue(env, 'EMBEDDINGS_MODEL_NAME') ??
    readOptionalValue(env, 'EMBEDDINGS_MODEL')

  return {
    embeddingApiKey,
    embeddingBaseUrl,
    embeddingModel,
  }
}

function resolveOpenAiCompatibleEmbeddingAlias(
  env: EnvironmentVariables,
  embeddingBaseUrl: string | undefined,
): string | undefined {
  const openAiCompatibleBaseUrl =
    readOptionalValue(env, 'OPENAI_COMPATIBLE_BASE_URL') ??
    readOptionalValue(env, 'OPENAI_BASE_URL')
  const openAiCompatibleApiKey =
    readOptionalSecret(env, 'OPENAI_COMPATIBLE_API_KEY') ??
    readOptionalSecret(env, 'OPENAI_API_KEY')

  if (!openAiCompatibleApiKey || !openAiCompatibleBaseUrl) {
    return undefined
  }

  if (
    isSameBaseUrl(openAiCompatibleBaseUrl, embeddingBaseUrl) ||
    (!embeddingBaseUrl && isDashScopeCompatibleBaseUrl(openAiCompatibleBaseUrl))
  ) {
    return openAiCompatibleApiKey
  }

  return undefined
}

function resolveDefaultDeepseekEmbeddingOverride(
  sharedEmbeddingOverride: {
    embeddingApiKey?: string
    embeddingBaseUrl?: string
    embeddingModel?: string
  },
): {
  embeddingApiKey?: string
  embeddingBaseUrl: string
  embeddingModel: string
} {
  return {
    embeddingApiKey: sharedEmbeddingOverride.embeddingApiKey,
    embeddingBaseUrl:
      sharedEmbeddingOverride.embeddingBaseUrl ??
      'https://dashscope.aliyuncs.com/compatible-mode/v1',
    embeddingModel: sharedEmbeddingOverride.embeddingModel ?? 'text-embedding-v3',
  }
}

export function resolveAiRuntimeConfig(env: EnvironmentVariables): AiRuntimeConfig {
  const provider = env.AI_PROVIDER?.trim().toLowerCase()
  const sharedEmbeddingOverride = resolveSharedEmbeddingOverride(env)

  if (!provider || provider === 'mock') {
    return {
      provider: 'mock',
      mode: 'mock',
      model: 'mock-resume-advisor',
      chatModel: 'mock-resume-advisor',
      embeddingModel: 'mock-resume-advisor-embedding',
    }
  }

  if (provider === 'qiniu') {
    const chatModel =
      readOptionalValue(env, 'QINIU_AI_CHAT_MODEL') ??
      readOptionalValue(env, 'QINIU_AI_MODEL_NAME') ??
      readOptionalValue(env, 'QINIU_AI_MODEL') ??
      'deepseek-v3'
    const embeddingModel =
      sharedEmbeddingOverride.embeddingModel ??
      readOptionalValue(env, 'QINIU_AI_EMBEDDING_MODEL') ??
      chatModel

    return {
      provider: 'qiniu',
      mode: 'openai-compatible',
      apiKey: readRequiredSecret(env, 'QINIU_AI_API_KEY', 'QINIU_AI_API_KEY is required'),
      baseUrl: env.QINIU_AI_BASE_URL?.trim() || 'https://api.qnaigc.com/v1',
      ...(sharedEmbeddingOverride.embeddingApiKey
        ? { embeddingApiKey: sharedEmbeddingOverride.embeddingApiKey }
        : {}),
      ...(sharedEmbeddingOverride.embeddingBaseUrl
        ? { embeddingBaseUrl: sharedEmbeddingOverride.embeddingBaseUrl }
        : {}),
      model: chatModel,
      chatModel,
      embeddingModel,
      providerLabel: 'Qiniu AI',
    }
  }

  if (provider === 'deepseek') {
    const deepseekEmbeddingOverride = resolveDefaultDeepseekEmbeddingOverride(
      sharedEmbeddingOverride,
    )
    const chatModel =
      readOptionalValue(env, 'DEEPSEEK_CHAT_MODEL') ??
      readOptionalValue(env, 'DEEPSEEK_MODEL_NAME') ??
      readOptionalValue(env, 'DEEPSEEK_MODEL') ??
      readOptionalValue(env, 'MODEL_NAME') ??
      'deepseek-v4-flash'

    return {
      provider: 'deepseek',
      mode: 'openai-compatible',
      apiKey: readRequiredSecret(
        env,
        'DEEPSEEK_API_KEY',
        'DEEPSEEK_API_KEY is required',
      ),
      baseUrl:
        readOptionalValue(env, 'DEEPSEEK_BASE_URL') ??
        readOptionalValue(env, 'OPENAI_BASE_URL') ??
        'https://api.deepseek.com',
      embeddingApiKey: deepseekEmbeddingOverride.embeddingApiKey,
      embeddingBaseUrl: deepseekEmbeddingOverride.embeddingBaseUrl,
      maxTokens: readOptionalPositiveInteger(env, 'DEEPSEEK_MAX_TOKENS'),
      model: chatModel,
      chatModel,
      embeddingModel:
        readOptionalValue(env, 'DEEPSEEK_EMBEDDING_MODEL') ??
        deepseekEmbeddingOverride.embeddingModel,
      providerLabel: 'DeepSeek',
      reasoningEffort: readOptionalReasoningEffort(env, 'DEEPSEEK_REASONING_EFFORT'),
      thinkingEnabled: readOptionalBoolean(env, 'DEEPSEEK_THINKING_ENABLED'),
    }
  }

  if (provider === 'openai-compatible') {
    const chatModel =
      readOptionalValue(env, 'OPENAI_COMPATIBLE_CHAT_MODEL') ??
      readOptionalValue(env, 'MODEL_NAME') ??
      readRequiredValue(
        env,
        'OPENAI_COMPATIBLE_MODEL',
        'OPENAI_COMPATIBLE_MODEL is required',
      )
    const embeddingModel =
      sharedEmbeddingOverride.embeddingModel ??
      readOptionalValue(env, 'OPENAI_COMPATIBLE_EMBEDDING_MODEL') ??
      chatModel

    return {
      provider: 'openai-compatible',
      mode: 'openai-compatible',
      apiKey:
        readOptionalSecret(env, 'OPENAI_COMPATIBLE_API_KEY') ??
        readRequiredSecret(
          env,
          'OPENAI_API_KEY',
          'OPENAI_COMPATIBLE_API_KEY or OPENAI_API_KEY is required',
        ),
      baseUrl:
        readOptionalValue(env, 'OPENAI_COMPATIBLE_BASE_URL') ??
        readRequiredValue(
          env,
          'OPENAI_BASE_URL',
          'OPENAI_COMPATIBLE_BASE_URL or OPENAI_BASE_URL is required',
        ),
      ...(sharedEmbeddingOverride.embeddingApiKey
        ? { embeddingApiKey: sharedEmbeddingOverride.embeddingApiKey }
        : {}),
      ...(sharedEmbeddingOverride.embeddingBaseUrl
        ? { embeddingBaseUrl: sharedEmbeddingOverride.embeddingBaseUrl }
        : {}),
      model: chatModel,
      chatModel,
      embeddingModel,
      providerLabel: 'OpenAI Compatible',
    }
  }

  throw new Error(`Unsupported AI_PROVIDER: ${provider}`)
}
