import { t } from '#cli/i18n'
import { TBox, TDialog, TText } from '@simon_he/vue-tui'
import { defineComponent, h, ref, watch } from 'vue'
import { copyTextToClipboard } from '../../pages/utils/clipboard'
import { useUiTheme } from '../theme'

type ToastGlobal = typeof globalThis & {
  __VT_SHOW_COPY_TOAST__?: (text: string) => void
}

export const DimSdkNextApiOAuthDialog = defineComponent({
  name: 'DimSdkNextApiOAuthDialog',
  props: {
    modelValue: { type: Boolean, required: true },
    w: { type: Number, default: 70 },
    h: { type: Number, default: 28 },
    oauthStatus: { type: String, required: true },
    oauthEmail: { type: String, required: true },
    oauthUrl: { type: String, required: true },
    oauthError: { type: String, default: '' },
    selectedModel: { type: String, default: '' },
    nextApiModels: {
      type: Array as () => Array<{
        id: string
        name: string
        description: string
      }>,
      default: () => [],
    },
    modelIndex: { type: Number, default: 0 },
  },
  emits: {
    'update:modelValue': (_v: boolean) => true,
    'update:selectedModel': (_v: string) => true,
    'update:modelIndex': (_v: number) => true,
    login: () => true,
    logout: () => true,
    close: () => true,
    selectModel: (_modelId: string) => true,
    viewPlans: () => true,
  },
  setup(props, { emit }) {
    const ui = useUiTheme()
    const preferButtons = ref(false)
    const showCopyToast = (message: string) => {
      const handler = (globalThis as ToastGlobal).__VT_SHOW_COPY_TOAST__
      if (typeof handler === 'function') handler(message)
    }

    const copyOAuthUrl = async () => {
      const ok = await copyTextToClipboard(props.oauthUrl)
      showCopyToast(
        ok
          ? t('nextApiOAuthDialog.toast.urlCopied')
          : t('nextApiOAuthDialog.toast.urlCopyFailed'),
      )
    }

    watch(
      () => props.modelValue,
      (next, prev) => {
        if (next && !prev) preferButtons.value = false
      },
    )

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

      const dialogW = Math.max(48, Math.floor(props.w))
      const dialogH = Math.max(14, Math.floor(props.h))
      const innerW = Math.max(0, dialogW - 4)
      const innerH = Math.max(0, dialogH - 4)

      const dialogBg = ui.token('dialog.chrome')?.bg
      const dialogBgStyle = dialogBg ? { bg: dialogBg } : undefined
      const hintStyle = ui.style(['dialog.chrome', 'text.muted'])
      const boxStyle = ui.style(['dialog.chrome', 'border.default'])
      const textStyle = ui.style(['dialog.chrome', 'text.primary'])
      const successStyle = ui.style(['status.success'], dialogBgStyle)
      const warningStyle = ui.style(['status.warning'], dialogBgStyle)

      const isAuthenticated = props.oauthStatus === 'authenticated'
      const isLoading = props.oauthStatus === 'loading'
      const canCopyUrl = Boolean(props.oauthUrl && !isAuthenticated)

      const statusText = isAuthenticated
        ? t('nextApiOAuthDialog.statusAuthenticated', {
            email: props.oauthEmail,
          })
        : isLoading
          ? t('nextApiOAuthDialog.statusLoading')
          : t('nextApiOAuthDialog.statusNotLoggedIn')

      const statusStyle = isAuthenticated
        ? successStyle
        : isLoading
          ? warningStyle
          : hintStyle

      const instructionText = isAuthenticated
        ? t('nextApiOAuthDialog.instructionAuthenticated')
        : isLoading
          ? t('nextApiOAuthDialog.instructionLoading')
          : props.oauthError
            ? t('nextApiOAuthDialog.instructionNeedsSetup')
            : props.oauthUrl
              ? t('nextApiOAuthDialog.instructionWithUrl')
              : t('nextApiOAuthDialog.instructionUnauthed')

      return h(
        TDialog as any,
        {
          modelValue: props.modelValue,
          'onUpdate:modelValue': (v: boolean) => emit('update:modelValue', v),
          onKeydownCapture: (e: any) => {
            const lowerKey = String(e?.key || '').toLowerCase()

            if (e?.key === 'Escape') {
              e.preventDefault?.()
              e.stopPropagation?.()
              emit('close')
              emit('update:modelValue', false)
              return
            }

            if (
              canCopyUrl &&
              lowerKey === 'c' &&
              !e?.ctrlKey &&
              !e?.metaKey &&
              !e?.altKey
            ) {
              e.preventDefault?.()
              e.stopPropagation?.()
              void copyOAuthUrl()
              return
            }

            if (isAuthenticated && props.nextApiModels.length > 0) {
              if (e?.key === 'ArrowDown') {
                e.preventDefault?.()
                e.stopPropagation?.()
                preferButtons.value = false
                const nextIndex =
                  (props.modelIndex + 1) % props.nextApiModels.length
                emit('update:modelIndex', nextIndex)
                return
              }

              if (e?.key === 'ArrowUp') {
                e.preventDefault?.()
                e.stopPropagation?.()
                preferButtons.value = false
                const prevIndex =
                  (props.modelIndex - 1 + props.nextApiModels.length) %
                  props.nextApiModels.length
                emit('update:modelIndex', prevIndex)
                return
              }
            }

            if (e?.key === 'ArrowLeft' || e?.key === 'ArrowRight') {
              preferButtons.value = true
              return
            }

            if (e?.key === 'Enter' && !isLoading) {
              const targetRect = e?.target?.rect
              const isDialogRoot = Boolean(
                targetRect &&
                targetRect.w === dialogW &&
                targetRect.h === dialogH,
              )

              if (preferButtons.value || !isDialogRoot) return

              e.preventDefault?.()
              e.stopPropagation?.()
              if (isAuthenticated) {
                if (props.nextApiModels.length > 0) {
                  const model = props.nextApiModels[props.modelIndex]
                  if (model) {
                    emit('selectModel', model.id)
                    emit('update:selectedModel', model.id)
                    emit('close')
                    emit('update:modelValue', false)
                    return
                  }
                }
                emit('logout')
              } else {
                emit('login')
              }
              return
            }

            if (isAuthenticated && props.nextApiModels.length > 0) {
              const numKey = e?.key
              if (numKey >= '1' && numKey <= '9') {
                const index = Number.parseInt(numKey) - 1
                if (index < props.nextApiModels.length) {
                  e.preventDefault?.()
                  e.stopPropagation?.()
                  preferButtons.value = false
                  const model = props.nextApiModels[index]
                  emit('selectModel', model.id)
                  emit('update:selectedModel', model.id)
                  emit('update:modelIndex', index)
                  emit('close')
                  emit('update:modelValue', false)
                }
              }
            }
          },
          w: dialogW,
          h: dialogH,
          title: t('nextApiOAuthDialog.title'),
          placement: 'center',
          backdrop: false,
          closeOnBackdrop: false,
          padding: 1,
          style: ui.style(['dialog.chrome']),
          closeOnConfirm: false,
          buttons: isAuthenticated
            ? [
                {
                  label: t('nextApiOAuthDialog.viewAllPlans'),
                  value: 'view-plans',
                  kind: 'primary',
                  default: true,
                },
                {
                  label: t('nextApiOAuthDialog.logout'),
                  value: 'logout',
                  kind: 'danger',
                },
                { label: t('common.close'), value: 'close' },
              ]
            : isLoading
              ? [
                  ...(canCopyUrl
                    ? [
                        {
                          label: t('nextApiOAuthDialog.copyUrl'),
                          value: 'copy-url',
                        },
                      ]
                    : []),
                  { label: t('common.cancel'), value: 'close', default: true },
                ]
              : canCopyUrl
                ? [
                    {
                      label: t('nextApiOAuthDialog.login'),
                      value: 'login',
                      kind: 'primary',
                      default: true,
                    },
                    {
                      label: t('nextApiOAuthDialog.copyUrl'),
                      value: 'copy-url',
                    },
                    { label: t('common.cancel'), value: 'close' },
                  ]
                : [
                    {
                      label: t('nextApiOAuthDialog.login'),
                      value: 'login',
                      kind: 'primary',
                      default: true,
                    },
                    { label: t('common.cancel'), value: 'close' },
                  ],
          onConfirm: (btn: any) => {
            if (btn?.value === 'copy-url') void copyOAuthUrl()
            else if (btn?.value === 'login') emit('login')
            else if (btn?.value === 'logout') emit('logout')
            else if (btn?.value === 'view-plans') emit('viewPlans')
            else emit('close')
          },
          onClose: () => emit('close'),
        },
        () => [
          h(TText, {
            x: 0,
            y: 0,
            w: innerW,
            value: instructionText,
            style: hintStyle,
          }),

          h(
            TBox,
            {
              x: 0,
              y: 2,
              w: innerW,
              h: 3,
              border: true,
              title: t('nextApiOAuthDialog.statusTitle'),
              padding: 0,
              style: boxStyle,
              clear: true,
            },
            () =>
              h(TText, {
                x: 1,
                y: 0,
                w: Math.max(0, innerW - 4),
                value: statusText,
                style: statusStyle,
              }),
          ),

          props.oauthUrl && !isAuthenticated
            ? h(
                TBox,
                {
                  x: 0,
                  y: 6,
                  w: innerW,
                  h: Math.min(12, Math.max(6, innerH - 9)),
                  border: true,
                  title: isLoading
                    ? t('nextApiOAuthDialog.oauthUrlTitleLoading')
                    : t('nextApiOAuthDialog.oauthUrlTitleReady'),
                  padding: 1,
                  style: {
                    ...boxStyle,
                    ...ui.token('status.warning'),
                    ...dialogBgStyle,
                  },
                  clear: true,
                },
                () => {
                  const formatUrl = (url: string): string[] => {
                    try {
                      const [baseUrl, queryString] = url.split('?')
                      if (!queryString) return [url]

                      const lines: string[] = [`${baseUrl}?`]
                      const params = queryString.split('&')
                      params.forEach((param, index) => {
                        const isLast = index === params.length - 1
                        lines.push(`${param}${isLast ? '' : '&'}`)
                      })
                      return lines
                    } catch {
                      const maxWidth = Math.max(50, innerW - 6)
                      const lines: string[] = []
                      let current = url
                      while (current.length > 0) {
                        lines.push(current.substring(0, maxWidth))
                        current = current.substring(maxWidth)
                      }
                      return lines
                    }
                  }

                  return formatUrl(props.oauthUrl).map((line, index) =>
                    h(TText, {
                      x: 0,
                      y: index,
                      w: Math.max(0, innerW - 4),
                      value: line,
                      style: ui.style(['dialog.chrome', 'accent.cyan']),
                      wrap: false,
                    }),
                  )
                },
              )
            : null,

          isAuthenticated && props.nextApiModels.length > 0
            ? (() => {
                const boxH = Math.max(0, innerH - 9)
                const contentH = Math.max(0, boxH - 2)
                const linesPerModel = 1
                const visibleModels = Math.floor(contentH / linesPerModel)

                let scrollOffset = 0
                if (props.nextApiModels.length > visibleModels) {
                  const focusedPosition = props.modelIndex
                  if (focusedPosition >= scrollOffset + visibleModels)
                    scrollOffset = focusedPosition - visibleModels + 1
                  else if (focusedPosition < scrollOffset)
                    scrollOffset = focusedPosition
                }

                const showScrollIndicator =
                  props.nextApiModels.length > visibleModels
                const scrollIndicator = showScrollIndicator
                  ? t('nextApiOAuthDialog.scrollIndicator', {
                      start: scrollOffset + 1,
                      end: Math.min(
                        scrollOffset + visibleModels,
                        props.nextApiModels.length,
                      ),
                      total: props.nextApiModels.length,
                    })
                  : ''

                return h(
                  TBox,
                  {
                    x: 0,
                    y: 6,
                    w: innerW,
                    h: Math.max(0, innerH - 9),
                    border: true,
                    title: t('nextApiOAuthDialog.selectModelTitle', {
                      indicator: scrollIndicator,
                    }),
                    padding: 1,
                    style: boxStyle,
                    clear: true,
                  },
                  () =>
                    props.nextApiModels
                      .slice(scrollOffset, scrollOffset + visibleModels)
                      .map((model, visibleIndex) => {
                        const actualIndex = scrollOffset + visibleIndex
                        const isFocused = actualIndex === props.modelIndex
                        const isSelected = model.id === props.selectedModel
                        const lineStyle = isFocused
                          ? ui.style(['dialog.chrome', 'text.primary'], {
                              bg: 'blue',
                            })
                          : ui.style(['dialog.chrome', 'text.primary'])

                        const indicators = `${isSelected ? ' ✓' : ''}${isFocused ? ' ◄' : ''}`
                        const prefix = `${actualIndex + 1}. ${model.name}${indicators}`
                        const maxWidth = Math.max(0, innerW - 4)

                        let displayText = prefix
                        if (model.description && prefix.length < maxWidth - 5) {
                          const remainingSpace = maxWidth - prefix.length - 3
                          if (remainingSpace > 10) {
                            const truncatedDesc =
                              model.description.length > remainingSpace
                                ? `${model.description.substring(0, remainingSpace - 1)}…`
                                : model.description
                            displayText = `${prefix} - ${truncatedDesc}`
                          }
                        }

                        return h(TText, {
                          x: 0,
                          y: visibleIndex * linesPerModel,
                          w: maxWidth,
                          value: displayText,
                          style: lineStyle,
                        })
                      }),
                )
              })()
            : !isLoading && !props.oauthUrl
              ? h(
                  TBox,
                  {
                    x: 0,
                    y: 6,
                    w: innerW,
                    h: Math.max(0, innerH - 9),
                    border: true,
                    title: props.oauthError
                      ? t('nextApiOAuthDialog.setupTitle')
                      : t('nextApiOAuthDialog.aboutTitle'),
                    padding: 1,
                    style: props.oauthError
                      ? {
                          ...boxStyle,
                          ...ui.token('status.warning'),
                          ...dialogBgStyle,
                        }
                      : boxStyle,
                    clear: true,
                  },
                  () =>
                    props.oauthError
                      ? h(TText, {
                          x: 0,
                          y: 0,
                          w: Math.max(0, innerW - 4),
                          h: Math.max(0, innerH - 11),
                          value: props.oauthError,
                          style: warningStyle,
                        })
                      : [
                          h(TText, {
                            x: 0,
                            y: 0,
                            w: Math.max(0, innerW - 4),
                            value: t('nextApiOAuthDialog.aboutBulletOne'),
                            style: textStyle,
                          }),
                          h(TText, {
                            x: 0,
                            y: 1,
                            w: Math.max(0, innerW - 4),
                            value: t('nextApiOAuthDialog.aboutBulletTwo'),
                            style: textStyle,
                          }),
                          h(TText, {
                            x: 0,
                            y: 2,
                            w: Math.max(0, innerW - 4),
                            value: t('nextApiOAuthDialog.aboutBulletThree'),
                            style: textStyle,
                          }),
                        ],
                )
              : null,
        ],
      )
    }
  },
})
