import { randomUUID } from "node:crypto";
import { runRustAgent } from "./rust-agent-adapter";
import { serverConfig } from "./config";
import type { AguiMessage } from "../types/agui-types";

const DEFAULT_COMPACTION_PROMPT = `Summarize the conversation so far so it can be compacted and later resumed.

Required structure:
1. Task Overview
The user's core request and success criteria
Any clarifications or constraints they specified

2. Current State
What has been completed so far
Files created, modified, or analyzed
Key outputs or artifacts produced

3. Important Discoveries
Technical constraints or requirements uncovered
Decisions made and their rationale
Errors encountered and how they were resolved
What approaches were tried that didn't work (and why)

4. Next Steps
Specific actions needed to complete the task
Any blockers or open questions to resolve
Priority order if multiple steps remain

5. Context to Preserve
User preferences or style requirements
Domain-specific details that aren't obvious
Any promises made to the user

Be concise but complete. Preserve concrete names, IDs, paths, prompts, and technical decisions that matter.
Wrap your answer in <summary></summary> tags.`;

function summarizeToolCalls(message: AguiMessage): string {
  if (!message.toolCalls || message.toolCalls.length === 0) {
    return "";
  }

  return message.toolCalls
    .map((toolCall) => {
      const args = toolCall.function.arguments?.trim();
      const compactArgs =
        args && args.length > 240 ? `${args.slice(0, 240)}...` : args;
      return compactArgs
        ? `Tool call: ${toolCall.function.name}(${compactArgs})`
        : `Tool call: ${toolCall.function.name}`;
    })
    .join("\n");
}

function clip(value: string, maxChars: number): string {
  const text = value.trim();
  if (text.length <= maxChars) {
    return text;
  }
  return `${text.slice(0, maxChars)}...`;
}

function serializeHistory(messages: AguiMessage[]): string {
  return messages
    .map((message) => {
      const prefix =
        message.role === "system"
          ? "System"
          : message.role === "assistant"
            ? "Assistant"
            : message.role === "tool"
              ? "Tool"
              : "User";

      const content = clip(message.content || "", message.role === "tool" ? 2000 : 4000);
      const toolCalls = summarizeToolCalls(message);

      return [toolCalls, content]
        .filter((part) => part.length > 0)
        .join("\n")
        .trim()
        ? `${prefix}:\n${[toolCalls, content].filter((part) => part.length > 0).join("\n")}`
        : `${prefix}:`;
    })
    .join("\n\n");
}

function extractSummary(text: string): string {
  const match = text.match(/<summary>([\s\S]*?)<\/summary>/i);
  const body = match?.[1]?.trim() || text.trim();
  return `<summary>\n${body}\n</summary>`;
}

export async function compactAguiHistory(
  messages: AguiMessage[],
  options?: {
    model?: string;
    summaryPrompt?: string;
  },
): Promise<AguiMessage[]> {
  let summaryText = "";

  const prompt = [
    options?.summaryPrompt || DEFAULT_COMPACTION_PROMPT,
    "",
    "Conversation to summarize:",
    serializeHistory(messages),
  ].join("\n");

  for await (const event of runRustAgent({
    prompt,
    cwd: process.cwd(),
    systemPrompt:
      "You are a context compaction assistant. Produce only the requested summary in <summary></summary> tags.",
    model: options?.model || serverConfig.compaction.model,
    tools: [],
    maxIterations: serverConfig.compaction.maxTurns,
    env: {
      LLM_PROVIDER: process.env.LLM_PROVIDER || "openai",
      OPENAI_API_KEY: process.env.OPENAI_API_KEY || process.env.ANTHROPIC_API_KEY || "",
      OPENAI_API_BASE_URL: process.env.OPENAI_API_BASE_URL || process.env.ANTHROPIC_BASE_URL || "",
      OPENAI_MODEL: process.env.OPENAI_MODEL || serverConfig.compaction.model,
      ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY || "",
      PATH: process.env.PATH || "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
      HOME: process.env.HOME || "/home/repopilot",
    },
  })) {
    if (event.type === "text_delta") {
      summaryText += event.content;
    } else if (event.type === "completed" && !summaryText && event.final_content) {
      summaryText = event.final_content;
    } else if (event.type === "failed") {
      throw new Error(event.error || "Compaction query failed");
    }
  }

  const compacted = extractSummary(summaryText);

  return [
    {
      id: `summary_${randomUUID()}`,
      role: "system",
      content: compacted,
    },
  ];
}

export function estimateHistoryTokens(messages: AguiMessage[]): number {
  const totalChars = messages.reduce((sum, message) => {
    const toolChars = (message.toolCalls || []).reduce(
      (toolSum, toolCall) =>
        toolSum +
        toolCall.function.name.length +
        (toolCall.function.arguments?.length || 0),
      0,
    );
    return sum + (message.content?.length || 0) + toolChars;
  }, 0);

  return Math.ceil(totalChars / 4);
}
