import { useDialog } from "@tui/ui/dialog"
import { DialogSelect, type DialogSelectOption } from "@tui/ui/dialog-select"
import { DialogPrompt } from "@tui/ui/dialog-prompt"
import { useSync } from "@tui/context/sync"
import { useToast } from "@tui/ui/toast"
import { createResource } from "solid-js"
import type { Config } from "@saeeol/sdk/v2"
import {
  type SubDialogProps,
  PROVIDER_LABELS,
  VECTOR_STORE_LABELS,
  TUNING_PARAMS,
  defaultIndexing,
  globalIndexing,
  getIndexing,
  hasSaeeolAuth,
  providerSettingsDescription,
  saveIndexing,
  saveGlobalIndexing,
  saveProjectIndexing,
  normalizeSaeeolEmbeddingModelId,
} from "./dialog-indexing-helpers"
import { ProviderSelect, showProviderSettings } from "./dialog-provider-settings"
import { VectorStoreSelect } from "./dialog-vector-store"
import { TuningMenu } from "./dialog-tuning"

export function DialogIndexing(props: SubDialogProps) {
  const dialog = useDialog()
  const sync = useSync()
  const sdk = props.useSDK()
  const toast = useToast()
  const [global] = createResource(async () => (await sdk.client.global.config.get({})).data as Config | undefined)
  const globalCfg = () => globalIndexing(global())
  const indexing = defaultIndexing(sync, globalCfg())

  const goBack = () => dialog.replace(() => <DialogIndexing useSDK={props.useSDK} />)

  const providerLabel = indexing.provider ? PROVIDER_LABELS[indexing.provider] : "not set"
  const storeLabel = indexing.vectorStore
    ? (VECTOR_STORE_LABELS[indexing.vectorStore] ?? indexing.vectorStore)
    : "Qdrant (default)"
  const tuningCount = TUNING_PARAMS.filter((p) => indexing[p.key] !== undefined).length
  const tuningDesc = tuningCount > 0 ? `${tuningCount} customized` : "defaults"

  const options: DialogSelectOption<string>[] = [
    {
      value: "globalToggle",
      title: "Indexing (Global)",
      category: "General",
      description: global.loading ? "loading" : globalCfg().enabled ? "enabled" : "disabled",
    },
    {
      value: "projectToggle",
      title: "Indexing (Project)",
      category: "General",
      description: globalCfg().enabled ? "controlled by global" : indexing.enabled ? "enabled" : "disabled",
    },
    { value: "provider", title: "Embedding Provider", category: "Embedding", description: providerLabel },
    { value: "model", title: "Embedding Model", category: "Embedding", description: indexing.model ?? "default" },
    {
      value: "dimension",
      title: "Vector Dimension",
      category: "Embedding",
      description: indexing.dimension ? String(indexing.dimension) : "auto",
    },
    { value: "vectorStore", title: "Vector Store", category: "Storage", description: storeLabel },
    { value: "tuning", title: "Tuning Parameters", category: "Advanced", description: tuningDesc },
  ]

  if (indexing.provider) {
    const desc = providerSettingsDescription(sync, indexing, indexing.provider)
    options.splice(2, 0, {
      value: "providerSettings",
      title: `${PROVIDER_LABELS[indexing.provider]} Settings`,
      category: "Embedding",
      description: desc,
    })
  }

  return (
    <DialogSelect
      title="Indexing Configuration"
      options={options}
      skipFilter
      onSelect={async (option) => {
        switch (option.value) {
          case "globalToggle": {
            const enabled = !globalCfg().enabled
            const updated =
              enabled && !globalCfg().provider && !getIndexing(sync).provider && hasSaeeolAuth(sync)
                ? { ...defaultIndexing(sync, globalCfg()), enabled }
                : { enabled }
            await saveGlobalIndexing(sdk, sync, updated, toast)
            goBack()
            break
          }
          case "projectToggle": {
            if (globalCfg().enabled) {
              toast.show({ message: "Global indexing is enabled, so this project is already covered.", variant: "info" })
              goBack()
              break
            }
            const current = getIndexing(sync)
            const enabled = !indexing.enabled
            const updated =
              enabled && !current.provider && hasSaeeolAuth(sync) ? { ...defaultIndexing(sync), enabled } : { enabled }
            await saveProjectIndexing(sdk, sync, updated, toast)
            goBack()
            break
          }
          case "provider":
            dialog.replace(() => <ProviderSelect useSDK={props.useSDK} goBack={goBack} />)
            break
          case "providerSettings":
            if (indexing.provider) await showProviderSettings(dialog, sync, sdk, toast, indexing.provider, props.useSDK, goBack)
            break
          case "model": {
            const result = await DialogPrompt.show(dialog, "Embedding Model", {
              value: indexing.model ?? "",
              placeholder: indexing.provider === "saeeol" ? "provider/model" : "e.g. text-embedding-3-small",
            })
            if (result !== null) {
              const trimmed = result.trim()
              const updated = {
                ...getIndexing(sync),
                model: trimmed
                  ? indexing.provider === "saeeol"
                    ? (normalizeSaeeolEmbeddingModelId(trimmed) ?? trimmed)
                    : trimmed
                  : undefined,
              }
              await saveIndexing(sdk, sync, updated, toast)
            }
            goBack()
            break
          }
          case "dimension": {
            const result = await DialogPrompt.show(dialog, "Vector Dimension", {
              value: indexing.dimension ? String(indexing.dimension) : "",
              placeholder: "Leave empty for auto-detection",
            })
            if (result !== null) {
              const trimmed = result.trim()
              let dim: number | undefined
              if (trimmed) {
                dim = Number(trimmed)
                if (isNaN(dim) || dim <= 0 || !Number.isInteger(dim)) {
                  toast.show({ message: `Invalid dimension: "${trimmed}"`, variant: "error" })
                  goBack()
                  break
                }
              }
              const updated = { ...getIndexing(sync), dimension: dim }
              await saveIndexing(sdk, sync, updated, toast)
            }
            goBack()
            break
          }
          case "vectorStore":
            dialog.replace(() => <VectorStoreSelect useSDK={props.useSDK} goBack={goBack} />)
            break
          case "tuning":
            dialog.replace(() => <TuningMenu useSDK={props.useSDK} goBack={goBack} />)
            break
        }
      }}
    />
  )
}
