/** Knowledge Base API client */

import { BaseApiClient } from './base'

const API_BASE = '/api/v1/kb-management'

export interface IKbSource {
  id: string
  name: string
  type: 'local' | 'feishu' | 'confluence' | 'http'
  status: string
  document_count: number
  last_synced: string | null
  config?: Record<string, unknown>
  /** Department binding for ACL (U4). Absent = global source. */
  department_id?: string | null
}

/** Document processing status flow: pending → parsing → segmenting → vectorizing → indexed | failed. */
export type DocumentStatus =
  | 'pending'
  | 'parsing'
  | 'segmenting'
  | 'vectorizing'
  | 'indexed'
  | 'failed'

export interface IPreviewChunk {
  index: number
  content: string
  metadata?: Record<string, unknown>
}

export interface IUploadedDocument {
  document_id: string
  filename: string
  source_id: string
  chunks: number
  status: string
  created_at: string
  /** Present when status === 'failed'. */
  error_message?: string
  /** Total chunk count (upload response includes this; list may omit). */
  total_chunks?: number
  /** Chunk preview returned by the upload endpoint. */
  chunks_preview?: IPreviewChunk[]
}

export interface IPreviewResult {
  document_id: string
  chunks: IPreviewChunk[]
  total_chunks: number
}

/** Retrieval query mode — mirrors backend ``QueryMode`` enum. */
export type QueryMode = 'embedding' | 'keywords' | 'blend'

/** Hit-processing strategy — mirrors backend constants. */
export type HitProcessing = 'model_opt' | 'direct'

/** Rerank provider options. */
export type RerankProvider = 'cohere' | 'bge' | 'none'

export interface IKBSettings {
  kb_id: string
  owner: string | null
  default_query_mode: QueryMode
  default_hit_processing: HitProcessing
  caching_disabled: boolean
  rerank_enabled: boolean
  rerank_provider: RerankProvider
  rerank_api_key: string | null
  rerank_base_url: string | null
  data_export_warning: boolean
}

export interface IKBSettingsUpdate {
  default_query_mode?: QueryMode
  default_hit_processing?: HitProcessing
  caching_disabled?: boolean
  rerank_enabled?: boolean
  rerank_provider?: RerankProvider
  rerank_api_key?: string | null
  rerank_base_url?: string | null
}

export interface IAddSourceRequest {
  name: string
  type: 'local' | 'feishu' | 'confluence' | 'http'
  config: Record<string, unknown>
}

export interface ISearchResult {
  content: string
  source: string
  score: number
  metadata: Record<string, unknown>
}

export interface ISourceHealth {
  source_id: string
  status: string
  message: string
}

class KbApiClient extends BaseApiClient {
  constructor(baseUrl: string = API_BASE) {
    super(baseUrl)
  }

  /** List all knowledge sources */
  async listSources(): Promise<{ sources: IKbSource[] }> {
    return this.request<{ sources: IKbSource[] }>('/sources')
  }

  /** Add a knowledge source */
  async addSource(data: IAddSourceRequest): Promise<IKbSource> {
    return this.request<IKbSource>('/sources', {
      method: 'POST',
      body: JSON.stringify(data),
    })
  }

  /** Remove a knowledge source */
  async removeSource(sourceId: string): Promise<{ status: string }> {
    return this.request<{ status: string }>(`/sources/${sourceId}`, {
      method: 'DELETE',
    })
  }

  /** Upload a document */
  async uploadDocument(file: File, sourceId?: string): Promise<IUploadedDocument> {
    const formData = new FormData()
    formData.append('file', file)
    if (sourceId) {
      formData.append('source_id', sourceId)
    }
    return this.request<IUploadedDocument>('/documents/upload', {
      method: 'POST',
      body: formData,
    })
  }

  /** Search/retrieve from knowledge base */
  async searchKnowledge(
    query: string,
    sources?: string[],
    topK: number = 5,
    strategy: string = 'vector'
  ): Promise<{ results: ISearchResult[]; message?: string }> {
    return this.request<{ results: ISearchResult[]; message?: string }>('/search', {
      method: 'POST',
      body: JSON.stringify({ query, source_ids: sources, top_k: topK, strategy }),
    })
  }

  /** Check source health */
  async checkSourceHealth(sourceId: string): Promise<ISourceHealth> {
    return this.request<ISourceHealth>(`/sources/${sourceId}/health`)
  }

  /** List all documents, optionally filtered by source */
  async listDocuments(sourceId?: string): Promise<{ documents: IUploadedDocument[] }> {
    const query = sourceId ? `?source_id=${sourceId}` : ''
    return this.request<{ documents: IUploadedDocument[] }>(`/documents${query}`)
  }

  /** Delete a document */
  async deleteDocument(documentId: string): Promise<{ status: string }> {
    return this.request<{ status: string }>(`/documents/${documentId}`, {
      method: 'DELETE',
    })
  }

  /** Trigger source sync */
  async syncSource(sourceId: string): Promise<{ status: string; source_id: string }> {
    return this.request<{ status: string; source_id: string }>(`/sources/${sourceId}/sync`, {
      method: 'POST',
    })
  }

  /** Update source config */
  async updateSource(sourceId: string, data: Partial<IAddSourceRequest>): Promise<IKbSource> {
    return this.request<IKbSource>(`/sources/${sourceId}`, {
      method: 'PUT',
      body: JSON.stringify(data),
    })
  }

  /** Preview document segmentation without persisting (U3). */
  async previewDocument(
    file: File,
    chunkSize: number = 512,
    chunkOverlap: number = 50,
  ): Promise<IPreviewResult> {
    const formData = new FormData()
    formData.append('file', file)
    const query = `?chunk_size=${chunkSize}&chunk_overlap=${chunkOverlap}`
    return this.request<IPreviewResult>(`/documents/preview${query}`, {
      method: 'POST',
      body: formData,
    })
  }

  /** Trigger vectorization for a document (retry path for failed docs). */
  async vectorizeDocument(documentId: string): Promise<{ status: string }> {
    return this.request<{ status: string }>(`/documents/${documentId}/vectorize`, {
      method: 'POST',
    })
  }

  /** Get KB-level settings (query mode / hit processing / caching / rerank). */
  async getKbSettings(kbId: string): Promise<IKBSettings> {
    return this.request<IKBSettings>(`/kbs/${kbId}/settings`)
  }

  /** Update KB-level settings (owner only). */
  async updateKbSettings(kbId: string, update: IKBSettingsUpdate): Promise<IKBSettings> {
    return this.request<IKBSettings>(`/kbs/${kbId}/settings`, {
      method: 'PUT',
      body: JSON.stringify(update),
    })
  }
}

export const kbApi = new KbApiClient()

// Backward-compatible standalone function exports
export const listSources = kbApi.listSources.bind(kbApi)
export const addSource = kbApi.addSource.bind(kbApi)
export const removeSource = kbApi.removeSource.bind(kbApi)
export const uploadDocument = kbApi.uploadDocument.bind(kbApi)
export const searchKnowledge = kbApi.searchKnowledge.bind(kbApi)
export const checkSourceHealth = kbApi.checkSourceHealth.bind(kbApi)
export const listDocuments = kbApi.listDocuments.bind(kbApi)
export const deleteDocument = kbApi.deleteDocument.bind(kbApi)
export const syncSource = kbApi.syncSource.bind(kbApi)
export const updateSource = kbApi.updateSource.bind(kbApi)
export const previewDocument = kbApi.previewDocument.bind(kbApi)
export const vectorizeDocument = kbApi.vectorizeDocument.bind(kbApi)
export const getKbSettings = kbApi.getKbSettings.bind(kbApi)
export const updateKbSettings = kbApi.updateKbSettings.bind(kbApi)
