"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateAiAssistantStore = generateAiAssistantStore;
function generateAiAssistantStore() {
    return `import { useSyncExternalStore } from 'react'
import type { ReactNode } from 'react'

export type AiEventKind = 'user' | 'action' | 'assistant' | 'system'
export type AiEventStatus = 'running' | 'done' | 'error'

export type AiAssistantEvent = {
  id: string
  kind: AiEventKind
  text: string
  status?: AiEventStatus
  createdAt: number
}

export type AiSidepaneTab = {
  id: string
  label: string
  render: () => ReactNode
}

type AiExecutionResult = {
  summary?: string
}

type AiExecutor = (
  task: string,
  helpers: {
    signal: AbortSignal
    addEvent: (entry: Omit<AiAssistantEvent, 'id' | 'createdAt'>) => string
    patchEvent: (id: string, patch: Partial<Pick<AiAssistantEvent, 'text' | 'status'>>) => void
    requestUserInput: (question: string) => Promise<string>
  },
) => Promise<AiExecutionResult>

type AiAssistantState = {
  open: boolean
  running: boolean
  pendingQuestion: string | null
  events: AiAssistantEvent[]
  tabs: AiSidepaneTab[]
  activeAdminTab: string
  executor: AiExecutor | null
  controller: AbortController | null
}

type AiAssistantActions = {
  setOpen: (open: boolean) => void
  clearEvents: () => void
  cancel: () => void
  submit: (task: string) => Promise<void>
  setExecutor: (executor: AiExecutor | null) => void
  registerTabs: (...tabs: AiSidepaneTab[]) => void
  deregisterTabs: (...tabIds: string[]) => void
  setActiveAdminTab: (tabId: string) => void
}

type AiAssistantStore = AiAssistantState & { actions: AiAssistantActions }

const listeners = new Set<() => void>()
const subscribe = (listener: () => void) => {
  listeners.add(listener)
  return () => listeners.delete(listener)
}

const notify = () => {
  for (const listener of listeners) {
    listener()
  }
}

const setStore = (update: Partial<AiAssistantState>) => {
  store = { ...store, ...update }
  notify()
}

const newId = () => globalThis.crypto?.randomUUID?.() ?? String(Date.now() + Math.random())

const addEvent = (entry: Omit<AiAssistantEvent, 'id' | 'createdAt'>): string => {
  const id = newId()
  const next: AiAssistantEvent = { id, createdAt: Date.now(), ...entry }
  setStore({ events: [...store.events, next] })
  return id
}

const patchEvent = (id: string, patch: Partial<Pick<AiAssistantEvent, 'text' | 'status'>>) => {
  setStore({
    events: store.events.map((event) => (event.id === id ? { ...event, ...patch } : event)),
  })
}

let pendingAnswerResolve: ((answer: string) => void) | null = null
let pendingAnswerReject: ((error: Error) => void) | null = null
let pendingSignalAbortUnsubscribe: (() => void) | null = null

const resetPendingInputRequest = () => {
  pendingAnswerResolve = null
  pendingAnswerReject = null
  pendingSignalAbortUnsubscribe?.()
  pendingSignalAbortUnsubscribe = null
  if (store.pendingQuestion) {
    setStore({ pendingQuestion: null })
  }
}

const requestUserInput = (question: string, signal: AbortSignal): Promise<string> => {
  resetPendingInputRequest()
  setStore({ pendingQuestion: question })

  return new Promise<string>((resolve, reject) => {
    pendingAnswerResolve = (answer) => {
      resetPendingInputRequest()
      resolve(answer)
    }
    pendingAnswerReject = (error) => {
      resetPendingInputRequest()
      reject(error)
    }

    const onAbort = () => {
      pendingAnswerReject?.(new Error('Execution cancelled'))
    }

    signal.addEventListener('abort', onAbort, { once: true })
    pendingSignalAbortUnsubscribe = () => signal.removeEventListener('abort', onAbort)
  })
}

let store: AiAssistantStore = {
  open: false,
  running: false,
  pendingQuestion: null,
  events: [],
  tabs: [],
  activeAdminTab: 'ai',
  executor: null,
  controller: null,
  actions: {} as AiAssistantActions,
}

store.actions = {
  setOpen(open) {
    setStore({ open })
  },

  clearEvents() {
    setStore({ events: [] })
  },

  cancel() {
    pendingAnswerReject?.(new Error('Execution cancelled'))
    store.controller?.abort()
    setStore({ running: false, controller: null, pendingQuestion: null })
  },

  async submit(task) {
    const trimmed = task.trim()
    if (!trimmed) {
      return
    }

    if (store.running && store.pendingQuestion) {
      addEvent({ kind: 'user', text: trimmed })
      pendingAnswerResolve?.(trimmed)
      return
    }

    if (store.running || !store.executor) {
      return
    }

    const controller = new AbortController()
    setStore({ running: true, open: true, controller })

    addEvent({ kind: 'user', text: trimmed })

    try {
      const result = await store.executor(trimmed, {
        signal: controller.signal,
        addEvent,
        patchEvent,
        requestUserInput: (question) => requestUserInput(question, controller.signal),
      })

      if (result.summary) {
        addEvent({ kind: 'assistant', text: result.summary, status: 'done' })
      }
    } catch (error) {
      if (controller.signal.aborted) {
        addEvent({ kind: 'system', text: 'Execution cancelled.' })
      } else {
        addEvent({ kind: 'assistant', text: String(error), status: 'error' })
      }
    } finally {
      resetPendingInputRequest()
      setStore({ running: false, controller: null, pendingQuestion: null })
    }
  },

  setExecutor(executor) {
    setStore({ executor })
  },

  registerTabs(...tabs) {
    const incoming = new Set(tabs.map((tab) => tab.id))
    const next = [...store.tabs.filter((tab) => !incoming.has(tab.id)), ...tabs]
    setStore({ tabs: next })
  },

  deregisterTabs(...tabIds) {
    const toRemove = new Set(tabIds)
    setStore({ tabs: store.tabs.filter((tab) => !toRemove.has(tab.id)) })
  },

  setActiveAdminTab(tabId) {
    setStore({ activeAdminTab: tabId })
  },
}

export const useAiAssistantState = <T>(selector: (state: AiAssistantState) => T): T =>
  useSyncExternalStore(subscribe, () => selector(store), () => selector(store))

export const useAiAssistantActions = (): AiAssistantActions =>
  useSyncExternalStore(subscribe, () => store.actions, () => store.actions)
`;
}
//# sourceMappingURL=ai-assistant-store.generator.js.map