import type { Tool, ToolResult } from '../types.js';
import type { AgentConfigRegistry } from '../../agents/registry.js';
import type { ModelTier } from '../../models/router.js';
import type { TokenUsage } from '../../models/types.js';

interface AgentDelegateRunner {
  delegate(request: {
    tier: ModelTier;
    systemPrompt: string;
    message: string;
    maxTokens?: number;
  }): Promise<{
    content: string;
    usage: TokenUsage;
    tier: ModelTier;
  }>;
}

export interface AgentDelegateDeps {
  registry: AgentConfigRegistry;
  orchestrator: AgentDelegateRunner;
}

/**
 * Creates an agent.delegate tool that dispatches a task to a named sub-agent.
 *
 * The sub-agent runs as a single-turn delegation call at the configured model tier,
 * using the agent's system prompt. The result is returned to the calling agent.
 */
export function createAgentDelegateTool(deps: AgentDelegateDeps): Tool {
  return {
    name: 'agent.delegate',
    description:
      'Delegate a task to a named sub-agent. The sub-agent runs a single-turn call ' +
      'at its configured model tier with its own system prompt. Use agents.list to see ' +
      'available agents. Returns the sub-agent\'s response.',
    inputSchema: {
      type: 'object',
      properties: {
        agent: {
          type: 'string',
          description: 'Name of the agent to delegate to (e.g. "research", "code", "comms")',
        },
        task: {
          type: 'string',
          description: 'The task description or question to send to the sub-agent',
        },
        max_tokens: {
          type: 'number',
          description: 'Maximum tokens for the sub-agent response (optional, default 4096)',
        },
      },
      required: ['agent', 'task'],
    },
    execute: async (rawArgs: unknown): Promise<ToolResult> => {
      try {
        const args = rawArgs as { agent: string; task: string; max_tokens?: number };

        // Look up the agent config
        const agentConfig = deps.registry.get(args.agent);
        if (!agentConfig) {
          const available = deps.registry.list().map(c => c.name);
          return {
            success: false,
            output: '',
            error: `Agent "${args.agent}" not found. Available agents: ${available.length > 0 ? available.join(', ') : 'none'}`,
          };
        }

        // Use the agent's configured tier, or fall back to 'default'
        const tier: ModelTier = agentConfig.modelTier ?? 'default';

        // Use the agent's system prompt, or a generic one
        const systemPrompt = agentConfig.systemPrompt
          ?? `You are a sub-agent named "${args.agent}". Complete the assigned task concisely and accurately.`;

        const result = await deps.orchestrator.delegate({
          tier,
          systemPrompt,
          message: args.task,
          maxTokens: args.max_tokens ?? 4096,
        });

        return {
          success: true,
          output: `[Agent: ${args.agent} | Tier: ${result.tier} | Tokens: ${result.usage.inputTokens}+${result.usage.outputTokens}]\n\n${result.content}`,
        };
      } catch (error) {
        return {
          success: false,
          output: '',
          error: error instanceof Error ? error.message : String(error),
        };
      }
    },
  };
}
