import type { ThemeId } from '#cli/core/theme'
import type { PropType } from 'vue'
import {
  getRegisteredThemeIds,
  getThemeEntry,
} from '#cli/core/theme'
import { t } from '#cli/i18n'
import { TDialog, TSelect, TText } from '@simon_he/vue-tui'
import { computed, defineComponent, h } from 'vue'
import { useUiTheme } from '../theme'
import { clamp } from '../utils/math'

export const DimSdkThemeDialog = defineComponent({
  name: 'DimSdkThemeDialog',
  props: {
    modelValue: { type: Boolean, required: true },
    mode: { type: String as PropType<ThemeId>, required: true },
    w: { type: Number, default: 56 },
  },
  emits: {
    'update:modelValue': (_v: boolean) => true,
    'update:mode': (_v: ThemeId) => true,
    'apply': () => true,
    'cancel': () => true,
  },
  setup(props, { emit }) {
    const ui = useUiTheme()

    const themeIds = computed(() => getRegisteredThemeIds())
    const themeLabels = computed(() =>
      themeIds.value.map((id) => {
        const entry = getThemeEntry(id)
        return entry?.label ?? id
      }),
    )
    const modeIndex = computed(() => {
      const idx = themeIds.value.indexOf(props.mode)
      return idx >= 0 ? idx : 0
    })

    return () => {
      if (!props.modelValue) return null

      const dialogBg = ui.token('dialog.chrome')?.bg
      const dialogBgStyle = dialogBg ? { bg: dialogBg } : undefined
      const highlightStyle = ui.style(['select.item'])
      const selectStyle = ui.style(['input.field'], dialogBgStyle)
      const labelStyle = ui.style(['text.primary'], {
        ...dialogBgStyle,
        bold: true,
      })
      const hintStyle = ui.style(['text.muted'], dialogBgStyle)
      const ids = themeIds.value
      const labels = themeLabels.value
      const listH = Math.min(ids.length, 6)
      const dialogW = Math.max(40, Math.floor(props.w))
      const innerW = Math.max(0, dialogW - 4)

      return h(
        TDialog as any,
        {
          modelValue: props.modelValue,
          'onUpdate:modelValue': (v: boolean) => emit('update:modelValue', v),
          onKeydownCapture: (e: any) => {
            if (e?.key === 'Escape') {
              e.preventDefault?.()
              e.stopPropagation?.()
              emit('cancel')
              emit('update:modelValue', false)
              return
            }
            if (
              typeof e?.key === 'string'
              && e.key.length === 1
              && !e.ctrlKey
              && !e.metaKey
              && !e.altKey
            ) {
              e.preventDefault?.()
              e.stopPropagation?.()
            }
          },
          w: dialogW,
          h: 10 + listH,
          title: t('themeDialog.title'),
          placement: 'center',
          backdrop: false,
          padding: 1,
          style: ui.style(['dialog.chrome']),
          buttons: [
            {
              label: t('common.apply'),
              value: 'apply',
              kind: 'primary',
              default: true,
            },
            { label: t('common.cancel'), value: 'cancel' },
          ],
          onConfirm: (btn: any) => {
            if (btn?.value === 'apply') emit('apply')
            else emit('cancel')
          },
          onClose: () => emit('cancel'),
        },
        () => [
          h(TText, {
            x: 0,
            y: 0,
            w: innerW,
            value: t('themeDialog.hint'),
            style: hintStyle,
          }),
          h(TText, {
            x: 0,
            y: 1,
            w: innerW,
            value: t('themeDialog.mode'),
            style: labelStyle,
          }),
          h(TSelect, {
            x: 0,
            y: 2,
            w: innerW,
            h: listH + 2,
            options: labels,
            modelValue: modeIndex.value,
            'onUpdate:modelValue': (v: number) => {
              const next = ids[clamp(v, 0, ids.length - 1)]
              if (next) emit('update:mode', next)
            },
            autoFocus: true,
            style: selectStyle,
            highlightStyle: highlightStyle,
          }),
          h(TText, {
            x: 0,
            y: listH + 4,
            w: innerW,
            value: t('themeDialog.tip'),
            style: hintStyle,
          }),
        ],
      )
    }
  },
})
