import api from './index'

export interface ChatProgressEvent {
  stage: 'thinking' | 'planning' | 'tool' | 'responding'
  label: string
  agent?: string | null
  tool_name?: string | null
  step?: string | null
  steps?: string[]
}

export interface ChatStreamChunkEvent {
  content: string
}

export interface ChatStreamMetadataEvent {
  conversation_id: string
  message_id: string
}

export interface ChatStreamHandlers {
  onMetadata?: (payload: ChatStreamMetadataEvent) => void
  onProgress?: (payload: ChatProgressEvent) => void
  onChunk?: (payload: ChatStreamChunkEvent) => void
  onError?: (message: string) => void
}

export interface MessageAttachment {
  id: string
  name: string
  type: string
  size: number
}

export interface Message {
  id: string
  role: 'user' | 'assistant'
  content: string
  model?: string
  tokens_used?: number
  created_at: string
  attachments?: MessageAttachment[]
}

export interface Conversation {
  id: string
  title?: string
  message_count: number
  created_at: string
  updated_at: string
}

function parseSseBlocks(buffer: string) {
  const chunks = buffer.split('\n\n')
  const rest = chunks.pop() ?? ''
  const events = chunks
    .map((block) => {
      const lines = block.split('\n')
      const event = lines.find((line) => line.startsWith('event:'))?.slice(6).trim() || 'message'
      const data = lines
        .filter((line) => line.startsWith('data:'))
        .map((line) => line.slice(5).trim())
        .join('\n')
      return { event, data }
    })
    .filter((item) => item.data)
  return { events, rest }
}

export const conversationApi = {
  list() {
    return api.get<Conversation[]>('/api/conversations')
  },

  create(title?: string) {
    return api.post<Conversation>('/api/conversations', { title })
  },

  getMessages(conversationId: string) {
    return api.get<Message[]>(`/api/conversations/${conversationId}/messages`)
  },

  delete(conversationId: string) {
    return api.delete(`/api/conversations/${conversationId}`)
  },

  chat(message: string, conversationId?: string, fileIds: string[] = [], modelName?: string) {
    return api.post('/api/conversations/chat', {
      message,
      conversation_id: conversationId,
      file_ids: fileIds,
      model_name: modelName,
    })
  },

  async chatStream(
    message: string,
    conversationId?: string,
    fileIds: string[] = [],
    modelName?: string,
    handlers: ChatStreamHandlers = {},
  ) {
    const token = localStorage.getItem('access_token')
    const response = await fetch(`${import.meta.env.VITE_API_URL}/api/conversations/chat/stream`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        ...(token ? { Authorization: `Bearer ${token}` } : {}),
      },
      body: JSON.stringify({
        message,
        conversation_id: conversationId,
        file_ids: fileIds,
        model_name: modelName,
      }),
    })

    if (!response.ok || !response.body) {
      let messageText = '连接失败。请检查服务状态。'
      try {
        const payload = await response.json()
        messageText = payload?.detail || payload?.error || messageText
      } catch {
        // ignore parse error
      }
      throw new Error(messageText)
    }

    const reader = response.body.getReader()
    const decoder = new TextDecoder('utf-8')
    let buffer = ''

    while (true) {
      const { done, value } = await reader.read()
      if (done) break
      buffer += decoder.decode(value, { stream: true })
      const { events, rest } = parseSseBlocks(buffer)
      buffer = rest

      for (const item of events) {
        const payload = JSON.parse(item.data)
        if (item.event === 'metadata') {
          handlers.onMetadata?.(payload)
        } else if (item.event === 'progress') {
          handlers.onProgress?.(payload)
        } else if (item.event === 'chunk') {
          handlers.onChunk?.(payload)
        } else if (item.event === 'error') {
          handlers.onError?.(payload.error || '连接失败。请检查服务状态。')
        }
      }
    }
  },
}
