import type {
  GoatChainContext as DimSdkContext,
  ToolCall,
  ToolResult,
} from '#cli/core/model'
import type { PropType, Ref } from 'vue'
import type { CliAgentBridge as DimSdkAgent } from './agent-bridge'
import type { DimSdkStore } from './core/store'
import type { DimSdkSessionsApi } from './keys'
import {
  defineComponent,
  h,
  inject,
  onUnmounted,
  provide,
  readonly,
  ref,
} from 'vue'
import { exitImmediately, registerExitUiHandler } from './cli/exit-controller'
import { createDimSdkStore } from './core/store'
import { DimSdkBridgeKey } from './keys'
import { DimSdkExitAppDialog } from './ui/components/ExitAppDialog'

export const DimSdkProviderStateKey = Symbol(
  'DimSdkProviderState',
) as symbol & { __type: Readonly<{ showExitConfirm: Ref<boolean> }> }

export type ToolRunner = (call: ToolCall) => Promise<ToolResult>

export const DimSdkProvider = defineComponent({
  name: 'DimSdkProvider',
  props: {
    toolRunner: { type: Function as PropType<ToolRunner>, required: true },
    context: { type: Object as PropType<DimSdkContext>, required: true },
    agent: { type: Object as PropType<DimSdkAgent>, required: true },
    onStoreCreated: {
      type: Function as PropType<((store: DimSdkStore) => void) | undefined>,
      default: undefined,
    },
    sessions: {
      type: Object as PropType<DimSdkSessionsApi | undefined>,
      default: undefined,
    },
    uiForcedSkills: {
      type: Object as PropType<Set<string> | undefined>,
      default: undefined,
    },
  },
  setup(props, { slots }) {
    const existing = inject(DimSdkBridgeKey, null)
    if (existing) return () => slots.default?.()

    const store = createDimSdkStore({
      toolRunner: props.toolRunner,
      context: props.context,
      agent: props.agent,
    })
    props.onStoreCreated?.(store)
    provide(DimSdkBridgeKey, {
      store,
      sessions: props.sessions,
      agent: props.agent,
      uiForcedSkills: props.uiForcedSkills,
    })

    const showExitConfirm = ref(false)
    const exitReason = ref('')

    // Provide the showExitConfirm state so child components (ChatPage) can check if the app exit dialog is open
    provide(DimSdkProviderStateKey, readonly({ showExitConfirm }))

    const busyReason = (): string => {
      const s = store.state
      if (s.runningAgentRound) return 'Agent is still responding'
      if (s.paused?.kind === 'ask_user') return 'Awaiting AskUser answers'
      if (s.paused?.kind === 'tool_approval') return 'Awaiting tool approval'
      if (s.approval?.active?.status === 'pending') return 'Pending approval'
      return ''
    }

    const unregister = registerExitUiHandler({
      isBusy: () => {
        const s = store.state
        if (s.runningAgentRound) return true
        if (s.paused) return true
        return Boolean(
          s.approval?.active && s.approval.active.status === 'pending',
        )
      },
      showConfirm: () => {
        exitReason.value = busyReason()
        showExitConfirm.value = true
      },
    })
    onUnmounted(() => unregister())

    return () =>
      h('div', null, [
        slots.default?.(),
        h(DimSdkExitAppDialog, {
          modelValue: showExitConfirm.value,
          'onUpdate:modelValue': (v: boolean) => (showExitConfirm.value = v),
          reason: exitReason.value,
          onExit: () => exitImmediately(),
        }),
      ])
  },
})
