import { t } from '#cli/i18n'
import { TDialog, TText, TView } from '@simon_he/vue-tui'
import { defineComponent, h } from 'vue'
import { useUiTheme } from '../theme'

export type MessageActionsAction =
  | 'revert'
  | 'revert_keep_files'
  | 'revert_files_only'
  | 'copy'
  | 'fork'
  | 'pin'
export type MessageActionsMode = 'full' | 'changed_files'

export const DimSdkMessageActionsDialog = defineComponent({
  name: 'DimSdkMessageActionsDialog',
  props: {
    modelValue: { type: Boolean, required: true },
    selectedIndex: { type: Number, required: true },
    pinLabel: { type: String, default: '' },
    mode: { type: String as () => MessageActionsMode, default: 'full' },
    w: { type: Number, default: 56 },
  },
  emits: {
    'update:modelValue': (_v: boolean) => true,
    'update:selectedIndex': (_v: number) => true,
    action: (_v: MessageActionsAction) => true,
  },
  setup(props, { emit }) {
    const ui = useUiTheme()
    const dialogBg = ui.token('dialog.chrome')?.bg
    const dialogBgStyle = dialogBg ? { bg: dialogBg } : undefined
    const highlightStyle = ui.style([], dialogBgStyle)
    const labels = () =>
      props.mode === 'changed_files'
        ? ([
            t('messageActionsDialog.revertWithFiles'),
            t('messageActionsDialog.revertFilesOnly'),
          ] as const)
        : ([
            t('messageActionsDialog.revert'),
            t('messageActionsDialog.revertKeepFiles'),
            t('messageActionsDialog.copy'),
            t('messageActionsDialog.fork'),
            props.pinLabel || t('messageActionsDialog.pin'),
          ] as const)

    function actionAtIndex(idx: number): MessageActionsAction {
      if (props.mode === 'changed_files')
        return idx === 0 ? 'revert' : 'revert_files_only'
      return idx === 0
        ? 'revert'
        : idx === 1
          ? 'revert_keep_files'
          : idx === 2
            ? 'copy'
            : idx === 3
              ? 'fork'
              : 'pin'
    }

    function close() {
      emit('update:modelValue', false)
      emit('update:selectedIndex', 0)
    }

    function onKeydown(e: any) {
      if (e.defaultPrevented) return
      if (e.key === 'ArrowUp') {
        e.preventDefault?.()
        e.stopPropagation?.()
        emit('update:selectedIndex', Math.max(0, props.selectedIndex - 1))
      } else if (e.key === 'ArrowDown') {
        e.preventDefault?.()
        e.stopPropagation?.()
        emit(
          'update:selectedIndex',
          Math.min(labels().length - 1, props.selectedIndex + 1),
        )
      } else if (e.key === 'Enter') {
        e.preventDefault?.()
        e.stopPropagation?.()
        emit('action', actionAtIndex(props.selectedIndex))
      } else if (e.key === 'Escape') {
        e.preventDefault?.()
        e.stopPropagation?.()
        close()
      }
    }

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

      const currentLabels = labels()
      const dialogW = Math.max(40, Math.floor(props.w))
      const innerW = Math.max(0, dialogW - 4)
      const dialogHeight = props.mode === 'changed_files' ? 6 : 9

      return h(
        TDialog as any,
        {
          modelValue: props.modelValue,
          'onUpdate:modelValue': (v: boolean) => {
            emit('update:modelValue', v)
            if (!v) emit('update:selectedIndex', 0)
          },
          onKeydownCapture: (e: any) => {
            // Block printable keys to avoid IME/layout issues (this dialog is navigation-only).
            if (
              typeof e?.key === 'string' &&
              e.key.length === 1 &&
              !e.ctrlKey &&
              !e.metaKey &&
              !e.altKey
            ) {
              e.preventDefault?.()
              e.stopPropagation?.()
            }
          },
          w: dialogW,
          h: dialogHeight,
          title: t('messageActionsDialog.title'),
          placement: 'center',
          backdrop: false,
          padding: 1,
          style: ui.style(['dialog.chrome']),
          onClose: close,
        },
        () =>
          h(
            TView,
            {
              x: 0,
              y: 0,
              w: innerW,
              h: currentLabels.length,
              focusable: true,
              autoFocus: true,
              onKeydownCapture: onKeydown,
            },
            () =>
              currentLabels.flatMap((label, i) => {
                const isSelected = props.selectedIndex === i
                const style = isSelected
                  ? highlightStyle
                  : ui.style(['dialog.chrome', 'text.muted'])
                const prefix = isSelected ? '▸ ' : '  '
                return [
                  h(TText, {
                    key: `action-t-${i}`,
                    x: 0,
                    y: i,
                    w: innerW,
                    value: `${prefix}${label}`,
                    style,
                  }),
                  h(TView as any, {
                    key: `action-v-${i}`,
                    x: 0,
                    y: i,
                    w: innerW,
                    h: 1,
                    onClick: (e: any) => {
                      e?.stopPropagation?.()
                      emit('update:selectedIndex', i)
                      emit('action', actionAtIndex(i))
                    },
                  }),
                ]
              }),
          ),
      )
    }
  },
})
