import { createMemo, createSignal } from "solid-js"
import { useLocal } from "@tui/context/local"
import { useSync } from "@tui/context/sync"
import { map, pipe, flatMap, entries, filter, sortBy } from "remeda"
import { DialogSelect, type DialogSelectRef } from "@tui/ui/dialog-select"
import { useDialog } from "@tui/ui/dialog"
import { Keybind } from "@/util/keybind"
import * as fuzzysort from "fuzzysort"

export function useConnected() {
  const sync = useSync()
  return createMemo(() => sync.data.provider.length > 0)
}

export function DialogModel() {
  const local = useLocal()
  const sync = useSync()
  const dialog = useDialog()
  const [ref, setRef] = createSignal<DialogSelectRef<unknown>>()
  const [query, setQuery] = createSignal("")

  const options = createMemo(() => {
    const q = query()
    const favorites = local.model.favorite()
    const recents = local.model.recent()

    const recentList = recents.filter(
      (item) => !favorites.some((fav) => fav.providerID === item.providerID && fav.modelID === item.modelID),
    )

    const favoriteOptions = favorites.flatMap((item) => {
      const provider = sync.data.provider.find((x) => x.id === item.providerID)
      if (!provider) return []
      const model = provider.models[item.modelID]
      if (!model) return []
      return [
        {
          key: item,
          value: {
            providerID: provider.id,
            modelID: model.id,
          },
          title: model.name ?? item.modelID,
          category: "Favorites",
          onSelect: () => {
            dialog.clear()
            local.model.set(
              {
                providerID: provider.id,
                modelID: model.id,
              },
              { recent: true },
            )
          },
        },
      ]
    })

    const recentOptions = recentList.flatMap((item) => {
      const provider = sync.data.provider.find((x) => x.id === item.providerID)
      if (!provider) return []
      const model = provider.models[item.modelID]
      if (!model) return []
      return [
        {
          key: item,
          value: {
            providerID: provider.id,
            modelID: model.id,
          },
          title: model.name ?? item.modelID,
          category: "Recent",
          onSelect: () => {
            dialog.clear()
            local.model.set(
              {
                providerID: provider.id,
                modelID: model.id,
              },
              { recent: true },
            )
          },
        },
      ]
    })

    const providerOptions = pipe(
      sync.data.provider,
      flatMap((provider) =>
        pipe(
          provider.models,
          entries(),
          filter(([_, info]) => info.status !== "deprecated"),
          map(([model, info]) => {
            const value = {
              providerID: provider.id,
              modelID: model,
            }
            return {
              value,
              title: info.name ?? model,
              description: favorites.some(
                (item) => item.providerID === value.providerID && item.modelID === value.modelID,
              )
                ? "(Favorite)"
                : undefined,
              onSelect() {
                dialog.clear()
                local.model.set(
                  {
                    providerID: provider.id,
                    modelID: model,
                  },
                  { recent: true },
                )
              },
            }
          }),
          filter((x) => {
            const value = x.value
            const inFavorites = favorites.some(
              (item) => item.providerID === value.providerID && item.modelID === value.modelID,
            )
            if (inFavorites) return false
            const inRecents = recentList.some(
              (item) => item.providerID === value.providerID && item.modelID === value.modelID,
            )
            if (inRecents) return false
            return true
          }),
          sortBy((x) => x.title),
        ),
      ),
    )

    if (q) {
      const filteredFavorites = fuzzysort.go(q, favoriteOptions, { keys: ["title"] }).map((x) => x.obj)
      const filteredRecents = fuzzysort
        .go(q, recentOptions, { keys: ["title"] })
        .map((x) => x.obj)
        .slice(0, 5)
      const filteredProviders = fuzzysort.go(q, providerOptions, { keys: ["title"] }).map((x) => x.obj)
      return [...filteredFavorites, ...filteredRecents, ...filteredProviders]
    }

    return [...favoriteOptions, ...recentOptions, ...providerOptions]
  })

  return (
    <DialogSelect
      keybind={[
        {
          keybind: Keybind.parse("ctrl+f")[0],
          title: "Favorite",
          onTrigger: (option) => {
            local.model.toggleFavorite(option.value as { providerID: string; modelID: string })
          },
        },
      ]}
      ref={setRef}
      onFilter={setQuery}
      skipFilter={true}
      title="Select model"
      current={local.model.current()}
      options={options()}
    />
  )
}
