import type { ThemeId, ThemeModeId } from '#cli/core/theme'
import type { TerminalColorCapability } from '@simon_he/vue-tui'
import type { UiThemeContext } from './ui-theme'
import { normalizeThemeId } from '#cli/core/theme'
import { ref } from 'vue'
import { getUiTheme } from './registry'
import { createUiThemeContext } from './ui-theme'

export type UiThemeSwitcher = Readonly<{
  context: UiThemeContext
  setMode: (mode: ThemeModeId | ThemeId) => void
  getMode: () => ThemeId
}>

export function createUiThemeSwitcher(
  opts: Readonly<{
    mode: ThemeModeId | ThemeId
    capability: TerminalColorCapability
  }>,
): UiThemeSwitcher {
  let currentId = normalizeThemeId(opts.mode)
  const version = ref(0)

  // Cache created contexts to avoid re-creating on every switch.
  const cache = new Map<ThemeId, UiThemeContext>()

  function getOrCreate(id: ThemeId): UiThemeContext {
    let ctx = cache.get(id)
    if (!ctx) {
      ctx = createUiThemeContext(getUiTheme(id), opts.capability)
      cache.set(id, ctx)
    }
    return ctx
  }

  let current = getOrCreate(currentId)

  const context: UiThemeContext = {
    get capability() {
      void version.value
      return current.capability
    },
    get tokens() {
      void version.value
      return current.tokens
    },
    get palette() {
      void version.value
      return current.palette
    },
    get version() {
      return version
    },
    token: (key: string) => {
      void version.value
      return current.token(key)
    },
    style: (keys: readonly string[], extra?: any) => {
      void version.value
      return current.style(keys, extra)
    },
  }

  return {
    context,
    setMode: (mode: ThemeModeId | ThemeId) => {
      const next = normalizeThemeId(mode)
      if (next === currentId)
        return
      currentId = next
      current = getOrCreate(next)
      version.value += 1
    },
    getMode: () => currentId,
  }
}
