/**
 * 自定义 Provider 模型发现 Adapter。
 *
 * 按 OpenAI-compatible /v1/models 发现。
 * - 无 baseUrl：回退到配置的 modelName（静态单模型）。
 * - 无 apiKey（getSeedModels）：不 throw，失败返回 modelName 或 []。
 * - 有 apiKey 的刷新路径：远程失败 throw，避免覆盖已有 DB 列表。
 */

import type { ModelRecord, ProviderAdapter, ProviderCredential, ConnectionTestResult, ModelCapabilities } from '../types'
import { buildGenericRecord, fetchWithTimeout, bearerHeaders, normalizeBaseUrl, parseOpenAIModelsResponse } from './common'

const defaultCapabilities = (): ModelCapabilities => ({
  contextWindow: 128_000,
  maxOutputTokens: 4096,
  supportsVision: false,
  supportsThinking: false,
  supportsAdaptiveThinking: false,
  supportsEffort: false,
})

export class CustomAdapter implements ProviderAdapter {
  readonly providerId = 'custom'
  readonly defaultBaseUrl = ''
  readonly authType = 'auth_token' as const

  async listModels(credential: ProviderCredential): Promise<ModelRecord[]> {
    if (!credential.baseUrl) {
      return credential.modelName
        ? [this.recordFor(credential.modelName, credential.providerId)]
        : []
    }

    // seed / 预览路径：永不 throw，以免拖垮 getAvailableModels
    if (!credential.apiKey) {
      if (credential.modelName) {
        return [this.recordFor(credential.modelName, credential.providerId)]
      }
      try {
        return await this.fetchRemoteModels(credential)
      } catch {
        return []
      }
    }

    // 刷新路径：失败必须 throw，registry 才不会误覆盖 DB
    const models = await this.fetchRemoteModels(credential)
    if (models.length === 0) {
      if (credential.modelName) {
        return [this.recordFor(credential.modelName, credential.providerId)]
      }
      throw new Error('Custom provider returned an empty model list')
    }
    return models
  }

  private async fetchRemoteModels(credential: ProviderCredential): Promise<ModelRecord[]> {
    const baseUrl = normalizeBaseUrl(credential.baseUrl)
    const url = baseUrl.includes('/v1') ? `${baseUrl}/models` : `${baseUrl}/v1/models`
    const res = await fetchWithTimeout(url, {
      headers: credential.apiKey ? bearerHeaders(credential) : {},
    })
    if (!res.ok) {
      throw new Error(`Failed to list custom provider models: HTTP ${res.status}`)
    }
    const json = await res.json()
    return parseOpenAIModelsResponse(
      json as { data?: Array<{ id: string }> },
      credential.providerId,
      credential.providerId,
      defaultCapabilities,
    )
  }

  async testConnection(credential: ProviderCredential): Promise<ConnectionTestResult> {
    if (!credential.baseUrl) return { ok: false, error: 'Base URL is not configured' }
    const baseUrl = normalizeBaseUrl(credential.baseUrl)
    const url = baseUrl.includes('/v1') ? `${baseUrl}/models` : `${baseUrl}/v1/models`
    try {
      const res = await fetchWithTimeout(url, {
        headers: credential.apiKey ? bearerHeaders(credential) : {},
      })
      if (res.ok) return { ok: true }
      const data = await res.json().catch(() => ({})) as { error?: { message?: string } }
      return { ok: false, error: data.error?.message || `HTTP ${res.status}` }
    } catch (err) {
      return { ok: false, error: err instanceof Error ? err.message : 'Connection failed' }
    }
  }

  private recordFor(modelName: string, providerId: string): ModelRecord {
    return buildGenericRecord(modelName, `${modelName} (${providerId})`, providerId, providerId, defaultCapabilities())
  }
}
