import z from "zod"
import { toIndexingConfigInput, type IndexingConfig } from "@saeeol/indexing/config"
import { IndexingStatus } from "@saeeol/indexing/status"
import type { VectorStoreSearchResult } from "@saeeol/indexing/engine"
import { Instance } from "@/project/instance"
import * as Log from "@saeeol/core/util/log"
import { Event as IndexingEvent } from "./indexing-types"
import { hitFn, cache } from "./indexing-state"

const log = Log.create({ service: "saeeol-indexing" })

export namespace SaeeolIndexing {
  export const Status = IndexingStatus
  export type Status = z.infer<typeof IndexingStatus>

  export function input(config?: IndexingConfig, global?: IndexingConfig) {
    return toIndexingConfigInput({
      ...config,
      enabled: config?.enabled === true || global?.enabled === true,
    })
  }

  export const Event = IndexingEvent

  export async function init() {
    const current = hitFn()
    void current.promise.catch((err) => {
      log.error("failed to initialize indexing", { err })
    })
    await current.ready
  }

  export async function current(): Promise<z.infer<typeof IndexingStatus>> {
    return (await hitFn().ready).current()
  }

  export function ready(): boolean {
    const entry = cache.get(Instance.directory)?.entry
    if (!entry?.manager) return false
    return entry.current().state !== "Disabled"
  }

  export async function available(): Promise<boolean> {
    const entry = await hitFn().ready
    if (!entry.manager) return false
    return entry.current().state !== "Disabled"
  }

  export async function search(query: string, directoryPrefix?: string): Promise<VectorStoreSearchResult[]> {
    const entry = await hitFn().ready
    if (!entry.manager) return []
    return entry.manager.searchIndex(query, directoryPrefix)
  }
}
