import type { BaseLLM } from '../models/base/llm.js';
import type { Message } from '../types.js';
import { getTools, getTool, getToolSchemasForLLM } from '../tools/registry.js';
import type { AgentContext } from '../tools/types.js';
import { MASTER_SYSTEM_PROMPT } from '../prompts/master.js';

export type MasterAgentInput = {
  task: string;
  chatHistory?: [string, string][];
  context: AgentContext;
  maxSteps?: number;
};

export type MasterAgentOutput = {
  content: string;
  steps: number;
}

export async function runMasterAgent(
  llm: BaseLLM,
  input: MasterAgentInput,
): Promise<MasterAgentOutput> {
  const maxSteps = input.maxSteps ?? 15;
  const tools = getTools();
  const toolSchemas = getToolSchemasForLLM();

  const historyStr =
    input.chatHistory?.length
      ? input.chatHistory
          .slice(-6)
          .map(([role, content]) => `${role === 'human' ? 'User' : 'Assistant'}: ${content}`)
          .join('\n')
      : '';

  const userContent = historyStr
    ? `<recent_conversation>\n${historyStr}\n</recent_conversation>\n\n<current_task>\n${input.task}\n</current_task>`
    : input.task;

  const messages: Message[] = [
    { role: 'system', content: MASTER_SYSTEM_PROMPT },
    { role: 'user', content: userContent },
  ];

  let steps = 0;

  while (steps < maxSteps) {
    steps += 1;

    const result = await llm.generateText({
      messages,
      tools: toolSchemas,
    });

    if (result.toolCalls.length === 0) {
      return {
        content: result.content.trim() || 'Нет ответа.',
        steps,
      };
    }

    messages.push({
      role: 'assistant',
      content: result.content,
      tool_calls: result.toolCalls,
    });

    for (const tc of result.toolCalls) {
      const tool = getTool(tc.name);
      if (!tool) {
        messages.push({
          role: 'tool',
          id: tc.id,
          name: tc.name,
          content: JSON.stringify({ error: `Unknown tool: ${tc.name}` }),
        });
        continue;
      }

      let toolResult: string;
      try {
        toolResult = await tool.execute(tc.arguments, input.context);
      } catch (err) {
        toolResult = JSON.stringify({
          error: err instanceof Error ? err.message : String(err),
        });
      }

      messages.push({
        role: 'tool',
        id: tc.id,
        name: tc.name,
        content: toolResult.length > 12000 ? toolResult.slice(0, 12000) + '\n...[truncated]' : toolResult,
      });
    }
  }

  const finalResult = await llm.generateText({
    messages,
    tools: [],
  });

  return {
    content: finalResult.content.trim() || 'Достигнут лимит шагов. Попробуйте уточнить запрос.',
    steps,
  };
}
