import apiClient from './client'
import type {
  AppConfig,
  SemanticModel,
  SemanticModelVersion,
  VersionCreate,
  VersionUpdate,
  SemanticModelSpec,
  PlaygroundFullRequest,
  PlaygroundFullResponse,
  DSSDataset,
  DSSDatasetSchema,
  DSSLLM,
  AutogenGenerateRequest,
  AutogenModelResponse,
  GlossaryTerm,
  GlossaryExtractionRequest,
  GlossaryExtractionResponse,
  BindingSuggestion,
  IndexingStatus,
} from '@/types'

// =============================================================================
// Config
// =============================================================================

export const configApi = {
  async get(): Promise<AppConfig> {
    const response = await apiClient.get('/config')
    return response.data
  },
}

// =============================================================================
// Semantic Models
// =============================================================================

export const semanticModelsApi = {
  async get(id: string, options?: { includeSpec?: boolean }): Promise<SemanticModel> {
    const params = options?.includeSpec ? { include_spec: 'true' } : undefined
    const response = await apiClient.get(`/semantic-models/${id}`, { params })
    return response.data
  },

  async setActiveVersion(id: string, versionId: string): Promise<SemanticModel> {
    const response = await apiClient.put(`/semantic-models/${id}/active`, {
      versionId: versionId,
    })
    return response.data
  },
}

// =============================================================================
// Versions
// =============================================================================

export const versionsApi = {
  async list(modelId: string): Promise<SemanticModelVersion[]> {
    const response = await apiClient.get(`/semantic-models/${modelId}/versions`)
    return response.data
  },

  async get(
    modelId: string,
    versionId: string,
    options?: { includeSpec?: boolean }
  ): Promise<SemanticModelVersion> {
    const params = options?.includeSpec === false ? undefined : { include_spec: 'true' }
    const response = await apiClient.get(
      `/semantic-models/${modelId}/versions/${versionId}`,
      { params }
    )
    return response.data
  },

  async create(modelId: string, data?: VersionCreate): Promise<SemanticModelVersion> {
    const payload: Record<string, unknown> = data?.version ? { ...data.version } : {}
    if (data?.fromVersion) {
      payload.fromVersion = data.fromVersion
    }
    const response = await apiClient.post(`/semantic-models/${modelId}/versions`, payload)
    return response.data
  },

  async update(
    modelId: string,
    versionId: string,
    data: VersionUpdate
  ): Promise<SemanticModelVersion> {
    const response = await apiClient.put(
      `/semantic-models/${modelId}/versions/${versionId}`,
      data.version
    )
    return response.data
  },

  async delete(modelId: string, versionId: string): Promise<void> {
    await apiClient.delete(`/semantic-models/${modelId}/versions/${versionId}`)
  },
}

// =============================================================================
// Playground
// =============================================================================

export const playgroundApi = {
  async execute(data: PlaygroundFullRequest): Promise<PlaygroundFullResponse> {
    const response = await apiClient.post('/playground/execute', data)
    return response.data
  },
}

// =============================================================================
// DSS Resources
// =============================================================================

export interface DSSProject {
  key: string
  name: string
}

export interface SQLAggregation {
  name: string
  syntax: string
  description: string
}

export const dssResourcesApi = {
  async listProjects(): Promise<DSSProject[]> {
    const response = await apiClient.get('/dss/projects')
    return response.data
  },

  async listDatasets(projectKey: string): Promise<DSSDataset[]> {
    const response = await apiClient.get(`/dss/datasets/${projectKey}/list`)
    return response.data
  },

  async getDatasetSchema(projectKey: string, datasetName: string): Promise<DSSDatasetSchema> {
    const response = await apiClient.get(`/dss/datasets/${projectKey}/${datasetName}/schema`)
    return response.data
  },

  
  async listLlms(purpose?: 'TEXT_EMBEDDING_EXTRACTION' | 'GENERIC_COMPLETION'): Promise<DSSLLM[]> {
    const params = purpose ? { purpose } : undefined
    const response = await apiClient.get('/dss/llms', { params })
    return response.data
  },


  async listAggregations(dialect?: string): Promise<SQLAggregation[]> {
    const url = dialect ? `/dss/aggregations/${dialect}` : '/dss/aggregations'
    const response = await apiClient.get(url)
    // Handle both formats (with or without dialect)
    return Array.isArray(response.data) ? response.data : response.data.standard
  },

  async fetchColumnValues(params: {
    semantic_model_id: string
    version_id: string
    entity: string
    attribute: string
    limit?: number
  }): Promise<{ values: string[]; truncated: boolean }> {
    const response = await apiClient.post('/dss/column-values', params)
    return response.data
  },
}

// =============================================================================
// Data Sources & Indexing
// =============================================================================

export const indexingApi = {
  async startIndexing(
    modelId: string,
    versionId: string,
    options?: { embedding_llm_id?: string | null }
  ): Promise<{ jobId: string | null }> {
    const payload: Record<string, unknown> = {}
    if (options?.embedding_llm_id) {
      payload.embedding_llm_id = options.embedding_llm_id
    }
    const response = await apiClient.post(
      `/semantic-models/${modelId}/versions/${versionId}/indexing/start`,
      payload
    )
    return response.data
  },
  async getIndexingStatus(
    modelId: string,
    versionId: string,
    jobId: string
  ): Promise<IndexingStatus> {
    const response = await apiClient.get(
      `/semantic-models/${modelId}/versions/${versionId}/indexing/status/${jobId}`
    )
    return response.data
  },
  async refreshIndices(
    modelId: string,
    versionId: string,
    options?: { embedding_llm_id?: string | null }
  ): Promise<{ results: Record<string, boolean>; lastIndexedAt?: string }> {
    const payload: Record<string, unknown> = {}
    if (options?.embedding_llm_id) {
      payload.embedding_llm_id = options.embedding_llm_id
    }
    const response = await apiClient.post(
      `/semantic-models/${modelId}/versions/${versionId}/indexing/rebuild-indices`,
      payload
    )
    return response.data
  },
}

// =============================================================================
// Auto-Generation
// =============================================================================

export const autogenApi = {
  /**
   * Generate a complete semantic model from a dataset.
   *
   * Synchronous endpoint that runs the full generation pipeline:
   * - Loads schema and profiles columns
   * - Proposes entity groups
   * - Generates entities with attributes, metrics, filters
   * - Suggests relationships
   * - Validates the model
   *
   * Returns when generation is complete (or failed).
   */
  async generateModel(request: AutogenGenerateRequest): Promise<AutogenModelResponse> {
    const response = await apiClient.post('/autogen/model/generate', request)
    return response.data
  },
}

// =============================================================================
// Glossary
// =============================================================================

export const glossaryApi = {
  /** Extract glossary terms from an uploaded file */
  async extractFromFile(
    file: File,
    request?: GlossaryExtractionRequest
  ): Promise<GlossaryExtractionResponse> {
    const formData = new FormData()
    formData.append('file', file)
    if (request) {
      formData.append('payload', JSON.stringify(request))
    }
    const response = await apiClient.post('/glossary/extract', formData, {
      headers: { 'Content-Type': 'multipart/form-data' },
    })
    return response.data
  },

  /** Get LLM-suggested bindings for glossary terms */
  async suggestBindings(
    modelId: string,
    versionId: string,
    options?: { spec?: SemanticModelSpec; terms?: GlossaryTerm[]; llm_id?: string }
  ): Promise<BindingSuggestion[]> {
    const response = await apiClient.post(
      `/semantic-models/${modelId}/versions/${versionId}/glossary/map`,
      options || {}
    )
    return response.data
  },
}

export { default as apiClient } from './client'
