import { createAuditEntry } from "../lib/audit.js";
import {
  clearPendingAssistantApproval,
  consumePendingAssistantApproval,
  toApprovalPayload,
  type PendingAssistantApproval,
} from "./assistant-approvals.js";
import {
  canExecuteMutationTool,
  isCancellationReply,
  parseToolArguments,
  type ChatMessage,
} from "./assistant-confirmation.js";
import { buildAssistantInsight, type AssistantInsight } from "./assistant-insights.js";
import { readToolError, readToolSuccessMessage } from "./assistant-tool-results.js";
import { executeTool, type ToolAction, type ToolContext } from "./assistant-tools.js";

export type AssistantChatResponse = {
  content: string;
  role: "assistant";
  approval?: ReturnType<typeof toApprovalPayload>;
  insights?: AssistantInsight[];
  actions?: ToolAction[];
};

export function mergeInsights(existing: AssistantInsight[], next: AssistantInsight): AssistantInsight[] {
  const duplicateIndex = existing.findIndex((item) => item.kind === next.kind && item.title === next.title && item.subtitle === next.subtitle);
  if (duplicateIndex >= 0) {
    const copy = [...existing];
    copy[duplicateIndex] = next;
    return copy;
  }

  return [...existing, next].slice(-6);
}

export function buildAssistantChatResponse(input: {
  content: string;
  approval?: ReturnType<typeof toApprovalPayload> | undefined;
  insights: AssistantInsight[];
  actions: ToolAction[];
}): AssistantChatResponse {
  return {
    content: input.content,
    role: "assistant",
    ...(input.approval !== undefined ? { approval: input.approval } : {}),
    ...(input.insights.length > 0 ? { insights: input.insights } : {}),
    ...(input.actions.length > 0 ? { actions: input.actions } : {}),
  };
}

export async function handlePendingAssistantApproval(input: {
  db: ToolContext["db"];
  dbUserId?: string | undefined;
  toolCtx: ToolContext;
  conversationId: string;
  pendingApproval: PendingAssistantApproval | null;
  lastUserMessage?: ChatMessage | undefined;
  messages: ChatMessage[];
  collectedActions: ToolAction[];
  collectedInsights: AssistantInsight[];
}): Promise<{
  response: AssistantChatResponse;
  collectedActions: ToolAction[];
  collectedInsights: AssistantInsight[];
} | null> {
  const { pendingApproval, lastUserMessage } = input;

  if (!pendingApproval || lastUserMessage?.role !== "user") {
    return null;
  }

  if (isCancellationReply(lastUserMessage.content)) {
    await clearPendingAssistantApproval(input.db, input.toolCtx.userId, input.conversationId);
    void createAuditEntry({
      db: input.db,
      entityType: "AiToolExecution",
      entityId: pendingApproval.id,
      entityName: pendingApproval.toolName,
      action: "DELETE",
      source: "ai",
      summary: `AI approval cancelled: ${pendingApproval.toolName}`,
      after: {
        approvalId: pendingApproval.id,
        params: parseToolArguments(pendingApproval.toolArguments),
        executed: false,
      },
      ...(input.dbUserId !== undefined ? { userId: input.dbUserId } : {}),
    });

    return {
      response: buildAssistantChatResponse({
        content: `Aktion verworfen: ${pendingApproval.summary}`,
        approval: toApprovalPayload(pendingApproval, "cancelled"),
        insights: input.collectedInsights,
        actions: input.collectedActions,
      }),
      collectedActions: input.collectedActions,
      collectedInsights: input.collectedInsights,
    };
  }

  if (!canExecuteMutationTool(input.messages, pendingApproval.toolName, pendingApproval)) {
    return null;
  }

  const approvedAction =
    await consumePendingAssistantApproval(input.db, input.toolCtx.userId, input.conversationId)
    ?? pendingApproval;
  const result = await executeTool(
    approvedAction.toolName,
    approvedAction.toolArguments,
    input.toolCtx,
  );

  let collectedInsights = input.collectedInsights;
  const insight = buildAssistantInsight(approvedAction.toolName, result.data);
  if (insight) {
    collectedInsights = mergeInsights(collectedInsights, insight);
  }

  const collectedActions = result.action
    ? [...input.collectedActions, result.action]
    : input.collectedActions;

  const errorMessage = readToolError(result);
  const successMessage = readToolSuccessMessage(result);
  const finalContent = errorMessage
    ? `Die bestätigte Aktion konnte nicht ausgeführt werden: ${errorMessage}`
    : successMessage
      ? `Ausgeführt: ${successMessage}`
      : `Ausgeführt: ${approvedAction.summary}`;

  void createAuditEntry({
    db: input.db,
    entityType: "AiToolExecution",
    entityId: approvedAction.id,
    entityName: approvedAction.toolName,
    action: "CREATE",
    source: "ai",
    summary: errorMessage
      ? `AI confirmed tool failed: ${approvedAction.toolName}`
      : `AI executed previously approved tool: ${approvedAction.toolName}`,
    after: {
      approvalId: approvedAction.id,
      params: parseToolArguments(approvedAction.toolArguments),
      executed: !errorMessage,
    },
    ...(input.dbUserId !== undefined ? { userId: input.dbUserId } : {}),
  });

  return {
    response: buildAssistantChatResponse({
      content: finalContent,
      approval: toApprovalPayload(approvedAction, "approved"),
      insights: collectedInsights,
      actions: collectedActions,
    }),
    collectedActions,
    collectedInsights,
  };
}
