/**
 * Agent Registry
 * Central dispatch for all command actions.
 *
 * Usage:
 *   import { executeAction, isStreamingAction } from 'upfynai-shared/agents';
 *
 *   // Sync action (file-read, git-operation, etc.)
 *   const result = await executeAction('file-read', { filePath: '/foo' }, ctx);
 *   // result = { content: '...' }
 *
 *   // Streaming action (claude-query, codex-query, etc.)
 *   const result = await executeAction('claude-query', params, {
 *     ...ctx,
 *     stream: (data) => ws.send(JSON.stringify({ type: 'relay-stream', requestId, data })),
 *   });
 *   // result = { exitCode: 0, sessionId: '...' }
 */
import claudeAgent from './claude.js';
import codexAgent from './codex.js';
import cursorAgent from './cursor.js';
import shellAgent from './shell.js';
import filesAgent from './files.js';
import gitAgent from './git.js';
import execAgent from './exec.js';
import detectAgent from './detect.js';
import gitagentAgent from './gitagent.js';

const agents = [claudeAgent, codexAgent, cursorAgent, shellAgent, filesAgent, gitAgent, execAgent, detectAgent, gitagentAgent];

/** Map of action name → handler function */
const actionMap = new Map();

/** Set of actions that use streaming (ctx.stream) instead of returning data */
const streamingActions = new Set(['claude-query', 'claude-task-query', 'codex-query', 'cursor-query']);

for (const agent of agents) {
  for (const [action, handler] of Object.entries(agent.actions)) {
    actionMap.set(action, handler);
  }
}

/**
 * Execute an agent action.
 * @param {string} action - Action name (e.g., 'file-read', 'claude-query')
 * @param {object} params - Action parameters from the command payload
 * @param {object} ctx - Execution context:
 *   - stream(data): Send streaming chunk (required for streaming actions)
 *   - requestId: Current request ID
 *   - trackProcess(id, entry): Register process for abort support
 *   - untrackProcess(id): Remove process from tracking
 *   - getPersistentShell(cwd): Get persistent shell instance (CLI only)
 *   - resolveBinary(name): Resolve binary path (CLI only)
 *   - localBinDir: Path to local node_modules/.bin (CLI only)
 *   - streamMode: 'structured' | 'simple' (claude agent only)
 *   - log(msg): Logging function
 * @returns {Promise<object>} Action result
 */
export async function executeAction(action, params, ctx = {}) {
  const handler = actionMap.get(action);
  if (!handler) throw new Error(`Unknown action: ${action}`);
  return handler(params, ctx);
}

/**
 * Check if an action uses streaming.
 * Streaming actions require ctx.stream() and return { exitCode, ... } via Promise.
 * Non-streaming actions return { data } directly.
 */
export function isStreamingAction(action) {
  return streamingActions.has(action);
}

/**
 * Check if an action is registered.
 */
export function hasAction(action) {
  return actionMap.has(action);
}

/**
 * Get all registered action names.
 */
export function getActionNames() {
  return Array.from(actionMap.keys());
}

export { agents };
