import Anthropic from "@anthropic-ai/sdk";
import { toolDefs, executeTool } from "./tools.js";
import * as store from "./store.js";
import * as tg from "./telegram.js";

const client = new Anthropic();
const MODEL = "claude-sonnet-4-20250514";
const MAX_TURNS = 50;

// Map of agentId -> resolve function for when user replies
const waitingForUser = new Map<number, (response: string) => void>();

export function isWaitingForUser(agentId: number): boolean {
  return waitingForUser.has(agentId);
}

export function resolveUserResponse(agentId: number, response: string): void {
  const resolve = waitingForUser.get(agentId);
  if (resolve) {
    waitingForUser.delete(agentId);
    resolve(response);
  }
}

function buildSystemPrompt(task: string): string {
  return `You are an autonomous coding agent. You have been assigned a specific task.

YOUR TASK:
${task}

GUIDELINES:
- Work independently to complete the task
- Use the bash tool for running commands, git, etc.
- Use read_file, write_file, edit_file for file operations
- When you're done, call the "done" tool with a summary
- If you need user input or a decision, call "ask_user"
- Be efficient — don't explain what you're about to do, just do it
- If something fails, try to fix it yourself before asking the user

WORKING DIRECTORY: ${process.cwd()}`;
}

export async function runAgent(agentId: number): Promise<void> {
  const agent = store.getAgent(agentId);
  if (!agent) return;

  store.updateAgent(agentId, { status: "working" });
  store.addLog(agentId, "system", `Agent started: ${agent.task}`);

  const messages: Anthropic.MessageParam[] = [
    { role: "user", content: agent.task },
  ];

  let turns = 0;

  try {
    while (turns < MAX_TURNS) {
      turns++;

      const response = await client.messages.create({
        model: MODEL,
        max_tokens: 8096,
        system: buildSystemPrompt(agent.task),
        tools: toolDefs as any,
        messages,
      });

      // Collect assistant content
      const assistantContent = response.content;
      messages.push({ role: "assistant", content: assistantContent });

      // Log text blocks (no Telegram notification — reduces noise)
      for (const block of assistantContent) {
        if (block.type === "text" && block.text.trim()) {
          store.addLog(agentId, "assistant", block.text);
        }
      }

      // If no tool use, we're done
      if (response.stop_reason !== "tool_use") {
        store.updateAgent(agentId, {
          status: "done",
          summary: "Completed (no more actions)",
        });
        store.addLog(agentId, "system", "Agent finished (end_turn)");
        await tg.send(
          `✅ *Agent #${agentId}* finished.\nTask: ${agent.task}`,
          agent.chat_id,
          { reply_to: agent.thread_msg_id || undefined }
        );
        return;
      }

      // Process tool calls
      const toolResults: Anthropic.ToolResultBlockParam[] = [];

      for (const block of assistantContent) {
        if (block.type !== "tool_use") continue;

        const toolName = block.name;
        const toolInput = block.input as Record<string, unknown>;

        store.addLog(
          agentId,
          "tool",
          `${toolName}: ${JSON.stringify(toolInput).slice(0, 500)}`
        );

        if (toolName === "ask_user") {
          // Pause and wait for user response
          store.updateAgent(agentId, { status: "waiting" });
          await tg.send(
            `❓ *Agent #${agentId}* needs your input:\n\n${toolInput.question}`,
            agent.chat_id,
            {
              reply_to: agent.thread_msg_id || undefined,
              keyboard: [
                [{ text: "💬 Reply", callback_data: `talk_${agentId}` }],
              ],
            }
          );
          store.addLog(agentId, "system", `Waiting for user: ${toolInput.question}`);

          // Wait for user response
          const userResponse = await new Promise<string>((resolve) => {
            waitingForUser.set(agentId, resolve);
          });

          store.updateAgent(agentId, { status: "working" });
          store.addLog(agentId, "user", `User replied: ${userResponse}`);

          toolResults.push({
            type: "tool_result",
            tool_use_id: block.id,
            content: `User responded: ${userResponse}`,
          });
          continue;
        }

        if (toolName === "done") {
          const summary = (toolInput.summary as string) || "Task completed";
          store.updateAgent(agentId, { status: "done", summary });
          store.addLog(agentId, "system", `Done: ${summary}`);
          await tg.send(
            `✅ *Agent #${agentId}* completed!\n\n*Summary:* ${summary}\n*Task:* ${agent.task}`,
            agent.chat_id,
            { reply_to: agent.thread_msg_id || undefined }
          );

          toolResults.push({
            type: "tool_result",
            tool_use_id: block.id,
            content: summary,
          });
          // Push tool results and stop
          messages.push({ role: "user", content: toolResults });
          return;
        }

        // Execute the tool
        const { result } = executeTool(toolName, toolInput);
        store.addLog(
          agentId,
          "tool_result",
          `${toolName} → ${result.slice(0, 500)}`
        );

        toolResults.push({
          type: "tool_result",
          tool_use_id: block.id,
          content: result,
        });
      }

      messages.push({ role: "user", content: toolResults });
    }

    // Hit max turns
    store.updateAgent(agentId, {
      status: "done",
      summary: `Stopped after ${MAX_TURNS} turns`,
    });
    await tg.send(
      `⚠️ *Agent #${agentId}* hit max turns (${MAX_TURNS}). Task: ${agent.task}`,
      agent.chat_id,
      { reply_to: agent.thread_msg_id || undefined }
    );
  } catch (e: any) {
    console.error(`[agent ${agentId}] error:`, e);
    store.updateAgent(agentId, { status: "error", error: e.message });
    store.addLog(agentId, "error", e.message);
    await tg.send(
      `❌ *Agent #${agentId}* error:\n${e.message?.slice(0, 500)}`,
      agent.chat_id,
      { reply_to: agent.thread_msg_id || undefined }
    );
  }
}
