"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateBaseGlobalActions = generateBaseGlobalActions;
function generateBaseGlobalActions() {
    return `import { useAuth } from '@context-providers/auth-context-provider'
import { useTheme } from '@context-providers/theme-context-provider'
import { useMutation } from '@tanstack/react-query'
import { useNavigate } from '@tanstack/react-router'

import { useEffect } from 'react'

import { APP_CONFIG } from '@lib/config'
import { useTRPC } from '@lib/trpc'

import { formatInputValue, humanizeToken, toTitle } from './ai-action-text.utils'
import { command, waitForNextFrame } from './command-palette-action'
import { useAiAssistantActions } from './ai-assistant-store'
import { useCommandPaletteActions } from './command-palette-store'

export const useBaseGlobalActions = () => {
  useNavigationActions()
  useThemeActions()
  useAiAssistantExecutor()
}

type DoneInput = { summary?: string }
type AskUserInput = { question?: string }
type BackendLogEntry = { text: string; status: 'done' | 'error' }

const toActionProgressText = ({
  key,
  label,
  input,
}: {
  key: string
  label: string
  input: unknown
}): string => {
  const adminModelMatch = /^admin-([a-z0-9-]+)-/.exec(key)
  const adminModel = adminModelMatch ? toTitle(humanizeToken(adminModelMatch[1])) : ''
  const details = formatInputValue(input)

  if (key.endsWith('-clear-all-filters')) {
    return adminModel ? 'Cleaning all filters on ' + adminModel + ' table' : 'Cleaning all filters'
  }

  if (key.endsWith('-query-filters')) {
    return adminModel ? 'Checking active filters on ' + adminModel + ' table' : 'Checking active filters'
  }

  if (key.endsWith('-search')) {
    const base = adminModel ? 'Searching in ' + adminModel + ' table' : 'Searching'
    return details ? base + ' with ' + details : base
  }

  if (key === 'ask-user') {
    if (typeof input === 'object' && input && typeof (input as Record<string, unknown>).question === 'string') {
      return 'Asking you: ' + String((input as Record<string, unknown>).question)
    }
    return 'Asking you for additional input'
  }

  if (label.toLowerCase().startsWith('filter by ')) {
    const base = 'Applying ' + label.toLowerCase()
    return details ? base + ' with ' + details : base
  }

  if (label.toLowerCase().startsWith('open ')) {
    return 'Opening ' + label.slice('open '.length)
  }

  if (label.toLowerCase().startsWith('switch to ')) {
    return 'Switching to ' + label.slice('switch to '.length)
  }

  if (label.toLowerCase().startsWith('use ')) {
    return 'Using ' + label.slice('use '.length)
  }

  const base = 'Running ' + label.toLowerCase()
  return details ? base + ' with ' + details : base
}

const toActionDoneText = ({
  key,
  label,
  input,
}: {
  key: string
  label: string
  input: unknown
}): string => {
  const details = formatInputValue(input)
  if (key.endsWith('-clear-all-filters')) {
    return 'Filters cleared'
  }
  if (key.endsWith('-query-filters')) {
    return 'Active filters checked'
  }

  const base = 'Completed: ' + label
  return details ? base + ' (' + details + ')' : base
}

const extractSummary = (input: unknown): string | undefined => {
  if (!isRecord(input)) {
    return undefined
  }

  const value = input.summary
  return typeof value === 'string' && value.trim().length > 0 ? value.trim() : undefined
}

const parseDoneInput = (input: unknown): DoneInput | undefined => {
  if (!isRecord(input)) {
    return undefined
  }

  return input as DoneInput
}

const parseAskUserInput = (input: unknown): AskUserInput | undefined => {
  if (!isRecord(input)) {
    return undefined
  }

  return input as AskUserInput
}

const parseBackendLogEntries = (payload: unknown): BackendLogEntry[] => {
  if (!isRecord(payload)) {
    return []
  }

  const raw = payload.backendLogs
  if (!Array.isArray(raw)) {
    return []
  }

  return raw
    .filter((entry): entry is Record<string, unknown> => isRecord(entry))
    .map((entry) => {
      const status: BackendLogEntry['status'] = entry.status === 'error' ? 'error' : 'done'
      const normalized: BackendLogEntry = {
        text: typeof entry.text === 'string' ? entry.text : '',
        status,
      }
      return normalized
    })
    .filter((entry): entry is BackendLogEntry => entry.text.length > 0)
}

const isRecord = (value: unknown): value is Record<string, unknown> =>
  typeof value === 'object' && value !== null && !Array.isArray(value)

const appendBackendLogs = (
  payload: unknown,
  addEvent: (entry: { kind: 'system'; text: string; status: 'done' | 'error' }) => string,
) => {
  for (const entry of parseBackendLogEntries(payload)) {
    addEvent({
      kind: 'system',
      text: entry.text,
      status: entry.status,
    })
  }
}

const useNavigationActions = () => {
  const navigate = useNavigate()
  const { registerGlobalActions } = useCommandPaletteActions()
  const { setOpen } = useAiAssistantActions()

  useEffect(() => {
    const actions = [
      command({
        key: 'navigate-dashboard',
        visibility: 'visible',
        group: 'Navigate',
        label: 'Dashboard',
        run: async () => {
          await navigate({ to: '/dashboard' })
          await waitForNextFrame()
          return { kind: 'close' }
        },
      }),
    ]

    if (APP_CONFIG.enableAI) {
      actions.push(
        command({
          key: 'open-ai-assistant',
          visibility: 'visible',
          group: 'Navigate',
          label: 'Open AI assistant',
          run: async () => {
            setOpen(true)
            await waitForNextFrame()
            return { kind: 'close' }
          },
        }),
      )
    }

    registerGlobalActions(...actions)
  }, [navigate, registerGlobalActions, setOpen])
}

const useThemeActions = () => {
  const { setColorMode } = useTheme()
  const { registerGlobalActions } = useCommandPaletteActions()

  useEffect(() => {
    registerGlobalActions(
      command({
        key: 'set-theme-dark',
        visibility: 'visible',
        group: 'Appearance',
        label: 'Switch to dark mode',
        run: async () => {
          setColorMode('dark')
          await waitForNextFrame()
          return { kind: 'close' }
        },
      }),
      command({
        key: 'set-theme-light',
        visibility: 'visible',
        group: 'Appearance',
        label: 'Switch to light mode',
        run: async () => {
          setColorMode('light')
          await waitForNextFrame()
          return { kind: 'close' }
        },
      }),
      command({
        key: 'set-theme-system',
        visibility: 'visible',
        group: 'Appearance',
        label: 'Use system theme',
        run: async () => {
          setColorMode('system')
          await waitForNextFrame()
          return { kind: 'close' }
        },
      }),
    )
  }, [registerGlobalActions, setColorMode])
}

const useAiAssistantExecutor = () => {
  const trpc = useTRPC()
  const { mutateAsync: startAiExecution } = useMutation(trpc.ai.ask.mutationOptions())
  const { mutateAsync: nextAiExecution } = useMutation(trpc.ai.step.mutationOptions())
  const { mutateAsync: cancelAiExecution } = useMutation(trpc.ai.cancel.mutationOptions())

  const { loginState } = useAuth()
  const { calculateAvailableLLMActions, reset, select } = useCommandPaletteActions()
  const { setExecutor } = useAiAssistantActions()

  useEffect(() => {
    if (!APP_CONFIG.enableAI || loginState !== 'loggedIn') {
      setExecutor(null)
      return
    }

    setExecutor(async (task, { signal, addEvent, patchEvent, requestUserInput }) => {
      signal.throwIfAborted()

      const askUserToolKey = 'ask-user'
      const lookupAction = (key: string) =>
        key === askUserToolKey ? { key: askUserToolKey, label: 'Ask user for input' } : calculateAvailableLLMActions().find((action) => action.key === key)

      const availableTools = () =>
        [
          ...calculateAvailableLLMActions().map((action) => ({
            key: action.key,
            kind: action.kind,
            label: action.label,
            target: 'frontend' as const,
            inputSchema: action.inputSchema?.toJSONSchema(),
          })),
          {
            key: askUserToolKey,
            kind: 'input' as const,
            label: 'Ask user for input',
            target: 'frontend' as const,
            inputSchema: {
              type: 'object',
              properties: {
                question: { type: 'string' },
              },
              required: ['question'],
            },
          },
        ].map((action) => ({
          key: action.key,
          kind: action.kind,
          label: action.label,
          inputSchema: action.inputSchema,
        }))

      const first = await startAiExecution({ task, tools: availableTools() })
      let current = first
      appendBackendLogs(first, addEvent)

      while (current && current.key !== 'done') {
        signal.throwIfAborted()

        const matchedAction = lookupAction(current.key)
        const actionLabel = matchedAction?.label ?? humanizeToken(current.key)
        const runningText = toActionProgressText({
          key: current.key,
          label: actionLabel,
          input: current.input,
        })

        const actionEventId = addEvent({
          kind: 'action',
          status: 'running',
          text: runningText,
        })

        try {
          if (current.key === askUserToolKey) {
            const askUserInput = parseAskUserInput(current.input)
            const question =
              typeof askUserInput?.question === 'string' && askUserInput.question.trim().length > 0
                ? askUserInput.question.trim()
                : 'Please provide more details so I can continue.'
            patchEvent(actionEventId, {
              status: 'running',
              text: 'Waiting for your input: ' + question,
            })

            const answer = await requestUserInput(question)
            patchEvent(actionEventId, {
              status: 'done',
              text: 'Received your input',
            })

            current = await nextAiExecution({
              conversation: current.conversation,
              output: { answer },
              tools: availableTools(),
            })
            appendBackendLogs(current, addEvent)
            continue
          }

          const result = await select(current.key, signal, '', current.input ?? {})

          const doneText = toActionDoneText({
            key: current.key,
            label: actionLabel,
            input: current.input,
          })

          patchEvent(actionEventId, {
            status: 'done',
            text: doneText,
          })

          current = await nextAiExecution({
            conversation: current.conversation,
            output: result.kind === 'page' ? undefined : result.output,
            tools: availableTools(),
          })
          appendBackendLogs(current, addEvent)
        } catch (error) {
          patchEvent(actionEventId, {
            status: 'error',
            text: 'Failed: ' + actionLabel,
          })

          await cancelAiExecution({ conversation: current.conversation })
          throw error
        }
      }

      reset()

      const summary = extractSummary(parseDoneInput(current?.input)) ?? 'Task completed.'

      return { summary }
    })

    return () => {
      setExecutor(null)
    }
  }, [
    calculateAvailableLLMActions,
    cancelAiExecution,
    loginState,
    nextAiExecution,
    reset,
    select,
    setExecutor,
    startAiExecution,
  ])
}
`;
}
//# sourceMappingURL=base-global-actions.generator.js.map