import axios from 'axios'
import md5 from 'blueimp-md5'
import { fetchEventSource, FetchEventSourceInit } from '@fortaine/fetch-event-source'
import { AIData, AIMessage, InitOptions } from './types'
import { extractJSON } from '@/utils/helper'

export async function fetchAIEventSource(url: string, options: FetchEventSourceInit) {
  await fetchEventSource(url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    async onopen(response) {
      if (response.ok) return
      else throw response
    },
    ...options,
  })
}

function getCommonResponseMessage(res: any) {
  if (res.data === '[DONE]') return
  try {
    const message = JSON.parse(res.data)
    if (message.choices && message.choices.length > 0) {
      const content = message.choices[0].delta?.content || ''
      return { id: message.id, role: 'assistant', content, json: extractJSON(content) } as AIMessage
    }
  } catch (error) {
    console.error(error)
  }
}

// https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Fm2vrveyu
export async function yiyan(data: AIData, options: InitOptions): Promise<void> {
  const getYiyanAccessToken = async () => {
    const AK = 'wY7bvMpkWeZbDVq9w3EDvpjU'
    const SK = 'XJwpiJWxs5HXkOtbo6tQrvYPZFJAWdAy'
    const resp = await axios.post(
      `/api/qianfan/oauth/2.0/token?grant_type=client_credentials&client_id=${AK}&client_secret=${SK}`
    )
    return resp.data.access_token
  }
  const accessToken = await getYiyanAccessToken()
  const params = { stream: true, ...data }
  await fetchAIEventSource(
    `/api/qianfan/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant?access_token=${accessToken}`,
    {
      ...options,
      body: JSON.stringify(params),
      onmessage(res) {
        try {
          const message = JSON.parse(res.data)
          if (options.onMessage) options.onMessage({ id: message.id, content: message.result || '' } as any)
        } catch (error) {
          console.error(error)
        }
      },
    }
  )
}

// https://api-docs.deepseek.com/zh-cn/api/create-chat-completion
export async function deepseek(data: AIData, options: InitOptions): Promise<void> {
  const apiKey = 'sk-f1a6f0a7013241de8393cb2cb108e777'
  const params = { model: 'deepseek-reasoner', stream: true, ...data }
  await fetchAIEventSource('/api/deepseek/chat/completions', {
    ...options,
    headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${apiKey}` },
    body: JSON.stringify(params),
    onmessage(res) {
      const message = getCommonResponseMessage(res)
      if (message) options.onMessage?.(message)
    },
  })
}

// https://docs.siliconflow.cn/cn/api-reference/chat-completions/chat-completions
export async function siliconflow(data: AIData, options: InitOptions): Promise<void> {
  const apiKey = 'sk-bivnwauskdbvpspvmdorrgkrpwlyfxbfcezqsfsevowzubdj'
  const params = { model: 'deepseek-ai/DeepSeek-R1', stream: true, ...data }
  await fetchAIEventSource('/api/siliconflow/v1/chat/completions', {
    ...options,
    headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${apiKey}` },
    body: JSON.stringify(params),
    onmessage(res) {
      const message = getCommonResponseMessage(res)
      if (message) options.onMessage?.(message)
    },
  })
}

// https://help.aliyun.com/zh/model-studio/developer-reference/use-qwen-by-calling-api
export async function qwen(data: AIData, options: InitOptions): Promise<void> {
  const apiKey = 'sk-afd0fcdb53bf4058b2068b8548820150'
  const params = { model: 'qwen-max-latest', stream: true, ...data }
  await fetchAIEventSource('/api/qwen/compatible-mode/v1/chat/completions', {
    ...options,
    headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${apiKey}` },
    body: JSON.stringify(params),
    onmessage(res) {
      const message = getCommonResponseMessage(res)
      if (message) options.onMessage?.(message)
    },
  })
}

export async function tiangong(data: AIData, options: InitOptions): Promise<void> {
  const appKey = 'a8701b73637562d33a53c668a90ee3be'
  const appSecret = 'e191593f486bb88a39c634f46926762dddc97b9082e192af'
  const timestamp = Math.floor(Date.now() / 1000).toString()
  const sign = md5(`${appKey}${appSecret}${timestamp}`)

  await fetchAIEventSource('/api/tiangong/sky-saas-writing/api/v1/chat', {
    ...options,
    headers: {
      'Content-Type': 'application/json',
      app_key: appKey,
      sign,
      timestamp,
      stream: 'true',
    },
    body: JSON.stringify({ chat_history: data.messages, stream_resp_type: 'delta' }),
    onmessage(res) {
      if (res.data === '[DONE]') return
      try {
        const message = JSON.parse(res.data)
        if (message.type !== 1) return
        const messageId = message.conversation_id
        const messageContent = message?.arguments?.[0]?.messages?.[0]?.text || ''
        if (options.onMessage) options.onMessage({ id: messageId, content: messageContent } as any)
      } catch (error) {
        console.error(error)
      }
    },
  })
}

export async function openAIStream(data: AIData, options: InitOptions): Promise<void> {
  const params = { model: 'qwen-max-latest', stream: true, ...data }
  await fetchEventSource('/api/openai/chat/create', {
    ...options,
    method: 'POST',
    headers: { 'Content-Type': 'application/json', Authorization: 'ezijing@20250331' },
    body: JSON.stringify(params),
    async onopen(response) {
      if (response.ok) return
      else throw response
    },
    onmessage(res) {
      const message = getCommonResponseMessage(res)
      if (message) options.onMessage?.(message)
    },
  })
}

export async function openAI(data: AIData, options: InitOptions): Promise<void> {
  try {
    const response = await axios.post('/api/openai/chat/create', data, {
      headers: { 'Content-Type': 'application/json', Authorization: 'ezijing@20250331' },
    })
    const content = response.data.choices[0]?.message?.content || ''
    const message: AIMessage = {
      id: response.data.id,
      role: 'assistant',
      content,
      json: extractJSON(content),
    }
    options.onMessage?.(message)
    options.onclose?.()
  } catch (error) {
    console.error(error)
    options.onerror?.(error)
  }
}

const aiService = {
  async post(data: AIData, options: InitOptions): Promise<void> {
    const messages: AIMessage[] = []
    const dataset = localStorage.getItem('dataset')
    if (dataset) {
      const datasetInfo = JSON.parse(dataset)
      messages.push({
        role: 'system',
        content: `这是一个数据集：${JSON.stringify(datasetInfo)}`,
      })
    }
    data.messages = [...messages, ...data.messages]
    openAI(data, options)
  },
}

export default aiService
