import { TRenderLayer, useTerminal } from '@simon_he/vue-tui'
import { defineComponent, getCurrentInstance, h, inject, watch } from 'vue'
import { mergeAskUserQuestions } from '../../../ask-user'
import { DimSdkAskUserDialog } from '../../../ui/components/AskUserDialog'
import { ChatPageContextKey } from '../context'
import { renderApprovalOverlays } from './overlays/approvals'
import { renderCommandPaletteOverlay } from './overlays/command-palette'
import { renderCopyToastOverlay } from './overlays/copy-toast'
import { renderExitOverlay } from './overlays/exit'
import { renderHelpOverlay } from './overlays/help'
import { renderMcpSettingsOverlay } from './overlays/mcp-settings'
import { renderPluginsOverlay } from './overlays/plugins'
import { renderMessageOverlays } from './overlays/messages'
import { renderNextApiOAuthOverlay } from './overlays/next-api-oauth'
import { renderPathPickerOverlay } from './overlays/path-picker'
import { renderPausedQueueDecisionOverlay } from './overlays/paused-queue-decision'
import { renderPinnedOverlay } from './overlays/pinned'
import { renderProviderOverlays } from './overlays/providers'
import { renderQueueConfirmOverlay } from './overlays/queue-confirm'
import { renderRenameOverlay } from './overlays/rename'
import { renderSessionsOverlay } from './overlays/sessions'
import { renderSessionTraceOverlay } from './overlays/session-trace'
import { renderSkillsOverlay } from './overlays/skills'
import { renderSettingsOverlays } from './overlays/settings'
import { renderTimelineOverlay } from './overlays/timeline'
import { renderToolSettingsOverlay } from './overlays/tool-settings'
import { renderUpgradeToastOverlay } from './overlays/upgrade-toast'

export const DimSdkChatOverlays = defineComponent({
  name: 'DimSdkChatOverlays',
  props: {
    refreshKey: { type: String, required: true },
  },
  setup(props) {
    const injected = inject(ChatPageContextKey)
    if (!injected) throw new Error('DimSdkChatOverlays missing ChatPageContext')
    const ctx = injected
    const instance = getCurrentInstance()
    const { render, scheduler } = useTerminal()

    watch(
      () => [
        props.refreshKey,
        ctx.store.state.messages.length,
        ctx.showCommands.value,
        ctx.showHelp.value,
        ctx.showTimeline.value,
        ctx.showSessionTrace.value,
        ctx.showPinned.value,
        ctx.showPathPicker.value,
        ctx.showSessions.value,
        ctx.showConfig.value,
        ctx.showLanguage.value,
        ctx.showTheme.value,
        ctx.showConnect.value,
        ctx.showModels.value,
        ctx.showConnectDialog.value,
        ctx.showNextApiOAuth.value,
        ctx.showSkills.value,
        ctx.showToolSettings.value,
        ctx.showMcpSettings.value,
        ctx.showPlugins.value,
        ctx.showPluginConfig.value,
        ctx.showRenameSession.value,
        ctx.showAskUser.value,
        ctx.showApproval.value,
        ctx.showExitConfirm.value,
        ctx.copyToastVisible.value,
        ctx.copyToastText.value,
        ctx.sessionTraceLoading.value,
        ctx.sessionTraceError.value,
        ctx.sessionTraceIndex.value,
        ctx.sessionTrace.value?.requests.length ?? 0,
      ],
      () => {
        if (instance?.isMounted)
          ;(instance as any)?.update?.()
        render.invalidatePlane('overlay')
        scheduler.invalidate({ priority: 'high', plane: 'overlay' })
      },
      { flush: 'post' },
    )

    return () => {
      void props.refreshKey
      const copyToast = renderCopyToastOverlay(ctx)
      const resolveAskUserQuestions = (): unknown[] => {
        const toolCallId = String(ctx.activeAskUser.value?.toolCallId ?? '').trim()
        if (!toolCallId)
          return mergeAskUserQuestions(ctx.activeAskUser.value?.questions, null)

        let fallbackRaw: unknown = null
        for (const message of ctx.store.state.messages) {
          if (message.role !== 'assistant') continue
          for (const part of message.parts) {
            if (part.type !== 'tool_call') continue
            if (String(part.call.id ?? '').trim() !== toolCallId) continue
            fallbackRaw = part.call.arguments
            break
          }
          if (fallbackRaw)
            break
        }
        return mergeAskUserQuestions(ctx.activeAskUser.value?.questions, fallbackRaw)
      }

      return [
        ...renderCommandPaletteOverlay(ctx),
        ...renderHelpOverlay(ctx),
        ...renderTimelineOverlay(ctx),
        ...renderSessionTraceOverlay(ctx),
        ...renderPinnedOverlay(ctx),
        ...renderPathPickerOverlay(ctx),
        ...renderSessionsOverlay(ctx),
        ...renderSettingsOverlays(ctx),
        ...renderProviderOverlays(ctx),
        ...renderNextApiOAuthOverlay(ctx),
        ...renderSkillsOverlay(ctx),
        ...renderToolSettingsOverlay(ctx),
        ...renderMcpSettingsOverlay(ctx),
        ...renderPluginsOverlay(ctx),
        ...renderRenameOverlay(ctx),
        ctx.showAskUser.value && ctx.activeAskUser.value
          ? h(DimSdkAskUserDialog, {
              'modelValue': ctx.showAskUser.value,
              'onUpdate:modelValue': (v: boolean) => (ctx.showAskUser.value = v),
              'toolCallId': String(ctx.activeAskUser.value.toolCallId ?? ''),
              'questions': resolveAskUserQuestions() as any,
              'w': ctx.askUserW.value,
              'h': ctx.askUserH.value,
              'onSubmit': (answers: Record<string, string | string[]>) =>
                void ctx.store.submitAskUserAnswers(answers),
              'onCancel': () => ctx.store.cancelAskUser(),
            })
          : null,
        ...renderApprovalOverlays(ctx),
        ...renderMessageOverlays(ctx),
        ...renderExitOverlay(ctx),
        copyToast.length
          ? h(TRenderLayer, { zIndex: 2000 }, () => copyToast)
          : null,
        ...renderPausedQueueDecisionOverlay(ctx),
        ...renderQueueConfirmOverlay(ctx),
        ...renderUpgradeToastOverlay(ctx),
      ]
    }
  },
})
