import type {
  ListModelsRequest,
  ModelConfig,
  ModelListResponse,
  TestModelConnectionResponse
} from '../types/model'

const DEFAULT_TEST_PROMPT = '请回复“连接成功”。'

function normalizeBaseUrl(baseUrl: string): string {
  const normalizedBaseUrl = baseUrl.trim().replace(/\/+$/, '')

  if (normalizedBaseUrl.endsWith('/chat/completions')) {
    return normalizedBaseUrl.slice(0, -'/chat/completions'.length)
  }

  if (normalizedBaseUrl.endsWith('/models')) {
    return normalizedBaseUrl.slice(0, -'/models'.length)
  }

  return normalizedBaseUrl
}

function getModelsUrl(baseUrl: string): string {
  return `${normalizeBaseUrl(baseUrl)}/models`
}

export function getChatCompletionsUrl(baseUrl: string): string {
  const normalizedBaseUrl = normalizeBaseUrl(baseUrl)

  if (/\/v\d+$/i.test(normalizedBaseUrl)) {
    return `${normalizedBaseUrl}/chat/completions`
  }

  return `${normalizedBaseUrl}/v1/chat/completions`
}

function maskApiKey(apiKey: string): string {
  const trimmedKey = apiKey.trim()

  if (trimmedKey.length <= 8) {
    return `${trimmedKey.slice(0, 2)}***`
  }

  return `${trimmedKey.slice(0, 6)}...${trimmedKey.slice(-4)}`
}

function truncatePrompt(prompt: string, maxLength = 240): string {
  const normalizedPrompt = prompt.replace(/\s+/g, ' ').trim()

  if (normalizedPrompt.length <= maxLength) {
    return normalizedPrompt
  }

  return `${normalizedPrompt.slice(0, maxLength)}...`
}

export function logLargeModelRequest({
  label,
  url,
  apiKey,
  model,
  prompt
}: {
  label: string
  url: string
  apiKey: string
  model: string
  prompt: string
}): void {
  console.info(`[大模型请求] ${label}`, {
    requestUrl: url,
    apiKey: maskApiKey(apiKey),
    modelId: model,
    prompt: truncatePrompt(prompt)
  })
}

export async function listModels(payload: ListModelsRequest): Promise<ModelListResponse> {
  if (!payload.baseUrl.trim()) {
    return { ok: false, message: '请先填写接口地址' }
  }

  if (!payload.apiKey.trim()) {
    return { ok: false, message: '请先填写 API Key' }
  }

  console.info('[大模型请求] 获取模型列表', {
    requestUrl: getModelsUrl(payload.baseUrl),
    apiKey: maskApiKey(payload.apiKey)
  })

  try {
    const response = await fetch(getModelsUrl(payload.baseUrl), {
      headers: {
        Authorization: `Bearer ${payload.apiKey}`,
        'Content-Type': 'application/json'
      }
    })

    if (!response.ok) {
      return { ok: false, message: `获取模型列表失败：HTTP ${response.status}` }
    }

    const data = (await response.json()) as { data?: Array<{ id?: unknown }> }
    const models = Array.from(
      new Set(
        (data.data ?? [])
          .map((model) => model.id)
          .filter((id): id is string => typeof id === 'string')
      )
    ).sort((a, b) => a.localeCompare(b))

    if (models.length === 0) {
      return { ok: false, message: '接口返回成功，但没有找到可用模型' }
    }

    return { ok: true, models }
  } catch (error) {
    return {
      ok: false,
      message: error instanceof Error ? error.message : '获取模型列表失败'
    }
  }
}

export async function testModelConnection(
  modelConfig: ModelConfig
): Promise<TestModelConnectionResponse> {
  if (!modelConfig.baseUrl.trim()) {
    return { ok: false, message: '请先填写接口地址' }
  }

  if (!modelConfig.apiKey.trim()) {
    return { ok: false, message: '请先填写 API Key' }
  }

  if (!modelConfig.model.trim()) {
    return { ok: false, message: '请先填写模型名称' }
  }

  const requestUrl = getChatCompletionsUrl(modelConfig.baseUrl)

  logLargeModelRequest({
    label: '测试连接',
    url: requestUrl,
    apiKey: modelConfig.apiKey,
    model: modelConfig.model,
    prompt: DEFAULT_TEST_PROMPT
  })

  try {
    const response = await fetch(requestUrl, {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${modelConfig.apiKey}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        model: modelConfig.model,
        temperature: 0,
        max_tokens: 16,
        messages: [
          {
            role: 'user',
            content: DEFAULT_TEST_PROMPT
          }
        ]
      })
    })

    if (!response.ok) {
      const message = await response.text().catch(() => '')
      return {
        ok: false,
        message: `测试连接失败：HTTP ${response.status}${message ? `，${message.slice(0, 160)}` : ''}`
      }
    }

    return { ok: true, message: '测试连接成功' }
  } catch (error) {
    return {
      ok: false,
      message: error instanceof Error ? error.message : '测试连接失败'
    }
  }
}
