import type {
  AnsiColorName,
  Style,
  TerminalColorCapability,
  TerminalColorLevel,
} from '@simon_he/vue-tui'
import type { Ref } from 'vue'
import { ref } from 'vue'

export type TokenStyle = Pick<
  Style,
  'fg' | 'bg' | 'bold' | 'dim' | 'italic' | 'underline' | 'inverse'
>

export type UiTokens = Readonly<Record<string, TokenStyle>>

export type UiTheme = Readonly<{
  palette256: Partial<Record<AnsiColorName, string>>
  tokensByLevel: Readonly<Record<TerminalColorLevel, UiTokens>>
}>

export type UiThemeContext = Readonly<{
  capability: TerminalColorCapability
  tokens: UiTokens
  palette: Partial<Record<AnsiColorName, string>> | null
  version: Ref<number>
  token: (key: string) => TokenStyle
  style: (keys: readonly string[], extra?: Style) => Style
}>

export function resolveUiTokens(
  theme: UiTheme,
  level: TerminalColorLevel,
): UiTokens {
  return theme.tokensByLevel[level] ?? theme.tokensByLevel[256]
}

export function styleFromTokens(
  tokens: UiTokens,
  keys: readonly string[],
  extra?: Style,
): Style {
  const out: Style = {}
  for (const key of keys) {
    const t = tokens[key]
    if (!t) continue
    Object.assign(out, t)
  }
  if (extra) Object.assign(out, extra)
  return out
}

export function createUiThemeContext(
  theme: UiTheme,
  capability: TerminalColorCapability,
  versionRef?: Ref<number>,
): UiThemeContext {
  const tokens = resolveUiTokens(theme, capability.level)
  const palette = capability.level === 256 ? theme.palette256 : null
  const version = versionRef ?? ref(0)

  return {
    capability,
    tokens,
    palette,
    version,
    token: (key: string) => {
      void version.value
      return tokens[key] ?? ({} as TokenStyle)
    },
    style: (keys: readonly string[], extra?: Style) => {
      void version.value
      return styleFromTokens(tokens, keys, extra)
    },
  }
}
