import { CloseBotClient, ok, err } from "../client.js";
import type { ToolDefinition, ToolResult, TestSession, TestSessionMessageInput, UpdateSessionInput, UpdateSessionDto, BotTestingRollbackInput, BotTestingRollbackOutput, ListLeadDto } from "../types.js";

export const tools: ToolDefinition[] = [
  {
    name: "create_test_session",
    description: "Create a new test session for a bot. Returns a lead ID and source ID for the test.",
    inputSchema: {
      type: "object",
      properties: {
        botId: { type: "string", description: "The bot ID" },
      },
      required: ["botId"],
    },
  },
  {
    name: "list_test_sessions",
    description: "List test sessions for a bot with pagination",
    inputSchema: {
      type: "object",
      properties: {
        botId: { type: "string", description: "The bot ID" },
        offset: { type: "number", description: "Offset (default 0)" },
        maxCount: { type: "number", description: "Max results (default 100)" },
      },
      required: ["botId"],
    },
  },
  {
    name: "delete_test_session",
    description: "Delete a test session",
    inputSchema: {
      type: "object",
      properties: {
        botId: { type: "string", description: "The bot ID" },
        leadId: { type: "string", description: "The test session lead ID" },
      },
      required: ["botId", "leadId"],
    },
  },
  {
    name: "update_test_session",
    description: "Update a test session (e.g., change mimic source)",
    inputSchema: {
      type: "object",
      properties: {
        botId: { type: "string", description: "The bot ID" },
        leadId: { type: "string", description: "The test session lead ID" },
        mimicSourceId: { type: "string", description: "Source ID to mimic" },
      },
      required: ["botId", "leadId"],
    },
  },
  {
    name: "send_test_message",
    description: "Send a message to a test session and get bot response",
    inputSchema: {
      type: "object",
      properties: {
        botId: { type: "string", description: "The bot ID" },
        leadId: { type: "string", description: "The test session lead ID" },
        message: { type: "string", description: "The message to send" },
      },
      required: ["botId", "leadId", "message"],
    },
  },
  {
    name: "force_test_step",
    description: "Force the bot to process the next step in a test session",
    inputSchema: {
      type: "object",
      properties: {
        botId: { type: "string", description: "The bot ID" },
        leadId: { type: "string", description: "The test session lead ID" },
      },
      required: ["botId", "leadId"],
    },
  },
  {
    name: "rollback_test_session",
    description: "Rollback a test session to a specific message (deletes that message and all subsequent)",
    inputSchema: {
      type: "object",
      properties: {
        botId: { type: "string", description: "The bot ID" },
        leadId: { type: "string", description: "The test session lead ID" },
        messageId: { type: "string", description: "The message ID to rollback to (this and subsequent are deleted)" },
      },
      required: ["botId", "leadId", "messageId"],
    },
  },
];

export async function handler(
  client: CloseBotClient,
  name: string,
  args: Record<string, unknown>
): Promise<ToolResult> {
  try {
    switch (name) {
      case "create_test_session":
        return ok(
          await client.post<TestSession>(`/bot/${args.botId}/testSession`)
        );

      case "list_test_sessions":
        return ok(
          await client.get<ListLeadDto>(`/bot/${args.botId}/testSession`, {
            offset: args.offset,
            maxCount: args.maxCount,
          })
        );

      case "delete_test_session":
        return ok(
          await client.delete(`/bot/${args.botId}/testSession/${args.leadId}`)
        );

      case "update_test_session": {
        const body: UpdateSessionInput = {
          mimicSourceId: args.mimicSourceId as string | undefined,
        };
        return ok(
          await client.put<UpdateSessionDto>(
            `/bot/${args.botId}/testSession/${args.leadId}`,
            body
          )
        );
      }

      case "send_test_message": {
        const body: TestSessionMessageInput = {
          leadId: args.leadId as string,
          message: args.message as string,
        };
        return ok(
          await client.post(`/bot/${args.botId}/testSession/message`, body)
        );
      }

      case "force_test_step":
        return ok(
          await client.post(
            `/bot/${args.botId}/testSession/${args.leadId}/force-step`
          )
        );

      case "rollback_test_session": {
        const body: BotTestingRollbackInput = {
          messageId: args.messageId as string,
        };
        return ok(
          await client.post<BotTestingRollbackOutput>(
            `/bot/${args.botId}/testSession/${args.leadId}/rollback`,
            body
          )
        );
      }

      default:
        return err(`Unknown tool: ${name}`);
    }
  } catch (error) {
    return err(error);
  }
}
