import type {
  CompositionStyles,
  Config,
  CssKeyframes,
  GlobalFontface,
  GlobalStyleObject,
  HooksApiInterface,
  Mixins,
  BambooPlugin,
  PatternConfig,
  PatternProperties,
  Preset,
  PropertyConfig,
  RecipeConfig,
  RecipeVariantRecord,
  SemanticTokens,
  SlotRecipeConfig,
  SlotRecipeVariantRecord,
  SystemStyleObject,
  ThemeVariant,
  Tokens,
} from '@bamboocss/types'

/* -----------------------------------------------------------------------------
 * Config creators
 * -----------------------------------------------------------------------------*/

export function defineConfig(config: Config) {
  return Object.assign(config, { name: '__bamboo.config__' })
}

export function defineRecipe<T extends RecipeVariantRecord>(config: RecipeConfig<T>): RecipeConfig {
  return config as RecipeConfig
}

export function defineSlotRecipe<S extends string, T extends SlotRecipeVariantRecord<S>>(
  config: SlotRecipeConfig<S, T>,
) {
  return config as SlotRecipeConfig
}

export function definePattern<T extends PatternConfig>(config: T) {
  return config as PatternConfig
}

export function definePreset(preset: Preset): Preset {
  return preset
}

export function defineKeyframes(keyframes: CssKeyframes) {
  return keyframes
}

export function defineGlobalStyles(definition: GlobalStyleObject) {
  return definition
}

export function defineGlobalFontface(definition: GlobalFontface) {
  return definition
}

export function defineUtility(utility: PropertyConfig) {
  return utility
}

export function definePlugin(plugin: BambooPlugin) {
  return plugin
}

export function defineThemeVariant<T extends ThemeVariant>(theme: T) {
  return theme
}

export function defineThemeContract<C extends Partial<Omit<ThemeVariant, 'selector'>>>(_contract: C) {
  return <T extends C & ThemeVariant>(theme: T) => defineThemeVariant(theme as T)
}

/* -----------------------------------------------------------------------------
 * Token creators
 * -----------------------------------------------------------------------------*/

type ProxyValue<T> = {
  <Value>(definition: Value extends T ? Value : T): Value
} & {
  [K in keyof Required<T>]: <Value>(definition: Value extends T[K] ? Value : T[K]) => Value
}

function createProxy<T>(): ProxyValue<T> {
  const identity = (v: unknown) => v
  return new Proxy(identity as any, {
    get() {
      return identity
    },
  })
}

export const defineTokens = /* @__PURE__ */ createProxy<Tokens>()
export const defineSemanticTokens = /* @__PURE__ */ createProxy<SemanticTokens>()

export function defineMixins(definition: CompositionStyles['mixins']) {
  return definition
}

export function defineStyles(definition: SystemStyleObject) {
  return definition
}

export type {
  CompositionStyles,
  Config,
  CssKeyframes,
  GlobalStyleObject,
  HooksApiInterface,
  Mixins,
  PatternConfig,
  PatternProperties,
  Preset,
  PropertyConfig,
  RecipeConfig,
  RecipeVariantRecord,
  SemanticTokens,
  SlotRecipeConfig,
  SlotRecipeVariantRecord,
  SystemStyleObject,
  Tokens,
}
