import { reconcile } from "solid-js/store"
import { getSaeeolEmbeddingModel, normalizeSaeeolEmbeddingModelId } from "@saeeol/indexing/embedding-models"
import type { IndexingConfig, Config } from "@saeeol/sdk/v2"
import { hasSaeeolIndexingAuth, resolveSaeeolIndexingAuth, shouldDefaultIndexingToSaeeol } from "../indexing-auth"

type UseSDK = any
type SDK = any

export type EmbeddingProvider = NonNullable<IndexingConfig["provider"]>

export function saeeolModel(model: string | undefined): string | undefined {
  return getSaeeolEmbeddingModel(model)?.id
}

export const PROVIDER_LABELS: Record<EmbeddingProvider, string> = {
  saeeol: "SAEEOL",
  openai: "OpenAI",
  ollama: "Ollama (local)",
  "openai-compatible": "OpenAI-Compatible",
  gemini: "Gemini",
  mistral: "Mistral",
  "vercel-ai-gateway": "Vercel AI Gateway",
  bedrock: "AWS Bedrock",
  openrouter: "OpenRouter",
  voyage: "Voyage",
}

export type ProviderFieldDef = { key: string; label: string; placeholder: string; sensitive?: boolean }

export const PROVIDER_FIELDS: Record<EmbeddingProvider, ProviderFieldDef[]> = {
  saeeol: [],
  openai: [{ key: "apiKey", label: "API Key", placeholder: "sk-...", sensitive: true }],
  ollama: [{ key: "baseUrl", label: "Base URL", placeholder: "http://localhost:11434" }],
  "openai-compatible": [
    { key: "baseUrl", label: "Base URL", placeholder: "https://api.example.com/v1" },
    { key: "apiKey", label: "API Key", placeholder: "sk-...", sensitive: true },
  ],
  gemini: [{ key: "apiKey", label: "API Key", placeholder: "AI...", sensitive: true }],
  mistral: [{ key: "apiKey", label: "API Key", placeholder: "...", sensitive: true }],
  "vercel-ai-gateway": [{ key: "apiKey", label: "API Key", placeholder: "...", sensitive: true }],
  bedrock: [
    { key: "region", label: "AWS Region", placeholder: "us-east-1" },
    { key: "profile", label: "AWS Profile", placeholder: "default" },
  ],
  openrouter: [
    { key: "apiKey", label: "API Key", placeholder: "sk-or-...", sensitive: true },
    { key: "specificProvider", label: "Specific Provider", placeholder: "optional" },
  ],
  voyage: [{ key: "apiKey", label: "API Key", placeholder: "pa-...", sensitive: true }],
}

export const VECTOR_STORE_LABELS: Record<string, string> = {
  qdrant: "Qdrant (default)",
  lancedb: "LanceDB",
}

export interface SubDialogProps {
  useSDK: () => UseSDK
}

export type SyncType = ReturnType<typeof import("@tui/context/sync").useSync>
export type ToastType = ReturnType<typeof import("@tui/ui/toast").useToast>
export type DialogType = ReturnType<typeof import("@tui/ui/dialog").useDialog>

export function maskSecret(value: string | undefined): string {
  if (!value) return "not set"
  if (value.length <= 6) return "***"
  return value.slice(0, 3) + "..." + value.slice(-3)
}

export function getIndexing(sync: SyncType): IndexingConfig {
  return (sync.data.config as Config & { indexing?: IndexingConfig }).indexing ?? {}
}

export function globalIndexing(data: Config | undefined): IndexingConfig {
  return data?.indexing ?? {}
}

export function hasSaeeolAuth(sync: SyncType): boolean {
  const provider = sync.data.provider_next.all.find((item) => item.id === "saeeol")
  return hasSaeeolIndexingAuth({ config: sync.data.config, provider })
}

export function defaultIndexing(sync: SyncType, global?: IndexingConfig): IndexingConfig {
  const indexing = getIndexing(sync)
  const provider = sync.data.provider_next.all.find((item) => item.id === "saeeol")
  const auth = resolveSaeeolIndexingAuth({ config: sync.data.config, provider })
  if (!shouldDefaultIndexingToSaeeol({ ...global, ...indexing }, auth)) return indexing
  return { ...indexing, provider: "saeeol", model: saeeolModel(indexing.model) }
}

export async function saveIndexing(sdk: SDK, sync: SyncType, indexing: IndexingConfig, toast: ToastType): Promise<boolean> {
  const global = { ...indexing }
  delete global.enabled
  const responses = await Promise.all([
    ...(Object.keys(global).length > 0 ? [sdk.client.global.config.update({ config: { indexing: global } })] : []),
    ...(indexing.enabled !== undefined ? [sdk.client.config.update({ config: { indexing: { enabled: indexing.enabled } } })] : []),
  ])
  if (responses.some((r) => r.error)) {
    toast.show({ message: "Failed to save indexing config", variant: "error" })
    return false
  }
  const cfg = await sdk.client.config.get({})
  if (cfg.data) sync.set("config", reconcile(cfg.data))
  toast.show({ message: "Indexing config saved", variant: "success" })
  return true
}

export async function saveGlobalIndexing(sdk: SDK, sync: SyncType, indexing: IndexingConfig, toast: ToastType): Promise<boolean> {
  const response = await sdk.client.global.config.update({ config: { indexing } })
  if (response.error) {
    toast.show({ message: "Failed to save indexing config", variant: "error" })
    return false
  }
  const merged = await sdk.client.config.get({})
  if (merged.data) sync.set("config", reconcile(merged.data))
  toast.show({ message: "Indexing config saved", variant: "success" })
  return true
}

export async function saveProjectIndexing(sdk: SDK, sync: SyncType, indexing: IndexingConfig, toast: ToastType): Promise<boolean> {
  const response = await sdk.client.config.update({ config: { indexing: { enabled: indexing.enabled } } })
  if (response.error) {
    toast.show({ message: "Failed to save indexing config", variant: "error" })
    return false
  }
  const cfg = await sdk.client.config.get({})
  if (cfg.data) sync.set("config", reconcile(cfg.data))
  toast.show({ message: "Indexing config saved", variant: "success" })
  return true
}

export function providerSettingsDescription(sync: SyncType, indexing: IndexingConfig, provider: EmbeddingProvider): string {
  if (provider === "saeeol") return hasSaeeolAuth(sync) ? "uses Saeeol account" : "sign in to Saeeol"
  const fields = PROVIDER_FIELDS[provider]
  const settings = indexing[provider] as Record<string, string | undefined> | undefined
  if (!settings) return "not configured"
  const parts = fields.map((f) => {
    const val = settings[f.key]
    if (!val) return `${f.label}: not set`
    return `${f.label}: ${f.sensitive ? maskSecret(val) : val}`
  })
  return parts.join(", ")
}

export type TuningParam = {
  key: keyof Pick<IndexingConfig, "searchMinScore" | "searchMaxResults" | "embeddingBatchSize" | "scannerMaxBatchRetries">
  label: string
  defaultValue: number
}

export const TUNING_PARAMS: TuningParam[] = [
  { key: "searchMinScore", label: "Search Min Score", defaultValue: 0.4 },
  { key: "searchMaxResults", label: "Search Max Results", defaultValue: 50 },
  { key: "embeddingBatchSize", label: "Embedding Batch Size", defaultValue: 60 },
  { key: "scannerMaxBatchRetries", label: "Scanner Max Batch Retries", defaultValue: 3 },
]

export { normalizeSaeeolEmbeddingModelId }
