// src/tools/memory/pin-remove.ts
// Copyright (C) 2025 DTP Technologies, LLC
// All Rights Reserved

import type { ToolDefinition } from "../../lib/ai-client.js";

import {
  DtpTool,
  type ToolArguments,
  type ToolContext,
} from "../../lib/tool.js";
import { ChatSession, ChatSessionMode } from "../../models/chat-session.js";

export class PinRemoveTool extends DtpTool {
  get name(): string {
    return "PinRemoveTool";
  }
  get slug(): string {
    return "pin-remove";
  }
  get metadata() {
    return {
      name: this.definition.function.name || "pin_remove",
      category: "memory",
      tags: ["pin", "pinboard", "note", "memory", "context", "remove"],
      modes: [
        ChatSessionMode.Plan,
        ChatSessionMode.Build,
        ChatSessionMode.Test,
        ChatSessionMode.Ship,
        ChatSessionMode.Develop,
      ],
    };
  }

  public definition: ToolDefinition = {
    type: "function",
    function: {
      name: "pin_remove",
      description:
        "Remove a pin from the session pinboard by its ID. Use this to free up space on the pinboard or remove information that is no longer relevant.",
      parameters: {
        type: "object",
        properties: {
          pin_id: {
            type: "string",
            description:
              "The _id of the pin to remove. This is returned when the pin was added via pin_add, and is also visible in the PINBOARD section of the system prompt.",
          },
        },
        required: ["pin_id"],
      },
    },
  };

  public async execute(
    context: ToolContext,
    args: ToolArguments,
  ): Promise<string> {
    const pinId = args.pin_id as string | undefined;

    if (!pinId || pinId.trim().length === 0) {
      return this.error("INVALID_PARAMETER", "pin_id must not be empty.", {
        parameter: "pin_id",
        recoveryHint: "Provide the _id of the pin you want to remove.",
      });
    }

    const sessionId = context.session._id.toHexString();

    try {
      const session = await ChatSession.findById(sessionId);
      if (!session) {
        return this.error("NOT_FOUND", `Session not found: ${sessionId}`);
      }

      const pinIndex = session.pins.findIndex(
        (pin) => pin._id?.toString() === pinId,
      );

      if (pinIndex === -1) {
        return this.error(
          "NOT_FOUND",
          `Pin not found: ${pinId}. Check the pin ID and try again.`,
          {
            recoveryHint:
              "Pin IDs are shown in the PINBOARD section of the system prompt and returned when pins are added.",
          },
        );
      }

      const removedContent = session.pins[pinIndex]!.content;
      session.pins.splice(pinIndex, 1);
      await session.save();

      const totalChars = session.pins.reduce(
        (sum, pin) => sum + pin.content.length,
        0,
      );

      return this.success(
        {
          pinId,
          content: removedContent,
          totalPins: session.pins.length,
          totalChars,
          maxChars: 8192,
        },
        `Pin removed from pinboard (${session.pins.length} pins remaining, ${totalChars}/8192 characters used).`,
      );
    } catch (error) {
      const errorMessage =
        error instanceof Error ? error.message : String(error);

      this.log.error("Failed to remove pin", {
        sessionId,
        error: errorMessage,
      });

      return this.error(
        "OPERATION_FAILED",
        `Failed to remove pin: ${errorMessage}`,
      );
    }
  }
}

export default new PinRemoveTool();
