import { CloseBotClient, ok, err } from "../client.js";
import type { ToolDefinition, ToolResult, AgencyDashboardSummaryResponse, BotMetricAction, BotMetricMessage, BotMetricLog, LeaderboardResponse, MessageFeedbackRequest, MessageFeedbackResponse, MessageLikesResponse, MessageReason } from "../types.js";

export const tools: ToolDefinition[] = [
  {
    name: "get_agency_summary",
    description: "Get agency dashboard summary with message counts, bookings, sources, contacts, and storage",
    inputSchema: {
      type: "object",
      properties: {
        sourceId: { type: "string", description: "Optional source ID to filter by" },
      },
    },
  },
  {
    name: "get_agency_metric",
    description: "Get a specific agency metric over time. Metrics: responses, bookings, activeSources, contacts, totalStorage, revenue",
    inputSchema: {
      type: "object",
      properties: {
        metric: { type: "string", description: "Metric name: responses, bookings, activeSources, contacts, totalStorage, revenue" },
        start: { type: "string", description: "Start date (ISO 8601)" },
        end: { type: "string", description: "End date (ISO 8601)" },
        resolution: { type: "string", description: "Time resolution (hourly, daily, monthly)" },
        sourceId: { type: "string", description: "Optional source ID" },
      },
      required: ["metric", "start", "end"],
    },
  },
  {
    name: "get_booking_graph",
    description: "Get booking graph data over a time range",
    inputSchema: {
      type: "object",
      properties: {
        start: { type: "string", description: "Start date (ISO 8601)" },
        end: { type: "string", description: "End date (ISO 8601)" },
        resolution: { type: "string", description: "Resolution: hourly, daily, or monthly" },
        sourceId: { type: "string", description: "Optional source ID" },
      },
      required: ["start", "end"],
    },
  },
  {
    name: "get_action_count",
    description: "Get the count of bot actions, optionally filtered by lead, source, bot, and date range",
    inputSchema: {
      type: "object",
      properties: {
        leadId: { type: "string", description: "Optional lead ID" },
        sourceId: { type: "string", description: "Optional source ID" },
        botId: { type: "string", description: "Optional bot ID" },
        start: { type: "string", description: "Start date (ISO 8601)" },
        end: { type: "string", description: "End date (ISO 8601)" },
      },
    },
  },
  {
    name: "get_actions",
    description: "Get detailed bot actions with optional filters",
    inputSchema: {
      type: "object",
      properties: {
        leadId: { type: "string", description: "Optional lead ID" },
        sourceId: { type: "string", description: "Optional source ID" },
        botId: { type: "string", description: "Optional bot ID" },
        start: { type: "string", description: "Start date (ISO 8601)" },
        end: { type: "string", description: "End date (ISO 8601)" },
        maxCount: { type: "number", description: "Maximum number of actions to return" },
      },
    },
  },
  {
    name: "get_message_count",
    description: "Get message count, optionally filtered by source, lead, and date range",
    inputSchema: {
      type: "object",
      properties: {
        sourceId: { type: "string", description: "Optional source ID" },
        leadId: { type: "string", description: "Optional lead ID" },
        start: { type: "string", description: "Start date (ISO 8601)" },
        end: { type: "string", description: "End date (ISO 8601)" },
      },
    },
  },
  {
    name: "get_messages",
    description: "Get messages with optional filters. Returns message content, direction, attachments, and activities.",
    inputSchema: {
      type: "object",
      properties: {
        sourceId: { type: "string", description: "Optional source ID" },
        leadId: { type: "string", description: "Optional lead ID" },
        start: { type: "string", description: "Start date (ISO 8601)" },
        end: { type: "string", description: "End date (ISO 8601)" },
        maxCount: { type: "number", description: "Maximum messages to return" },
      },
    },
  },
  {
    name: "get_message_feedback",
    description: "Get message IDs that have feedback for a lead",
    inputSchema: {
      type: "object",
      properties: {
        leadId: { type: "string", description: "The lead ID" },
      },
      required: ["leadId"],
    },
  },
  {
    name: "save_message_feedback",
    description: "Save feedback (like/dislike with reasons) for a specific message",
    inputSchema: {
      type: "object",
      properties: {
        messageId: { type: "string", description: "The message ID" },
        leadId: { type: "string", description: "The lead ID" },
        liked: { type: "boolean", description: "Whether the message was liked" },
        reasons: { type: "string", description: "Feedback reasons" },
      },
      required: ["messageId", "leadId"],
    },
  },
  {
    name: "get_message_likes",
    description: "Get message IDs that have likes for a lead",
    inputSchema: {
      type: "object",
      properties: {
        leadId: { type: "string", description: "The lead ID" },
      },
      required: ["leadId"],
    },
  },
  {
    name: "get_message_reason",
    description: "Get the feedback reason for a specific message",
    inputSchema: {
      type: "object",
      properties: {
        messageId: { type: "string", description: "The message ID" },
      },
      required: ["messageId"],
    },
  },
  {
    name: "get_leaderboard",
    description: "Get the global leaderboard. Metrics: responses, bookings, contacts",
    inputSchema: {
      type: "object",
      properties: {
        metric: { type: "string", description: "Metric: responses, bookings, contacts" },
        start: { type: "string", description: "Start date (ISO 8601)" },
        end: { type: "string", description: "End date (ISO 8601)" },
        numTopLeaders: { type: "number", description: "Number of top leaders to return" },
      },
      required: ["metric", "start", "end"],
    },
  },
  {
    name: "get_local_leaderboard",
    description: "Get the local leaderboard (your agency + surrounding). Metrics: responses, bookings, contacts",
    inputSchema: {
      type: "object",
      properties: {
        metric: { type: "string", description: "Metric: responses, bookings, contacts" },
        start: { type: "string", description: "Start date (ISO 8601)" },
        end: { type: "string", description: "End date (ISO 8601)" },
        numSurroundingAgencies: { type: "number", description: "Number of surrounding agencies" },
      },
      required: ["metric", "start", "end"],
    },
  },
  {
    name: "get_logs",
    description: "Get bot execution logs with optional filters. Includes prompts, tokens, model info.",
    inputSchema: {
      type: "object",
      properties: {
        botId: { type: "string", description: "Optional bot ID" },
        messageId: { type: "string", description: "Optional message ID" },
        sourceId: { type: "string", description: "Optional source ID" },
        leadId: { type: "string", description: "Optional lead ID" },
        actionId: { type: "string", description: "Optional action ID" },
        start: { type: "string", description: "Start date (ISO 8601)" },
        end: { type: "string", description: "End date (ISO 8601)" },
        maxCount: { type: "number", description: "Maximum logs to return" },
      },
    },
  },
];

export async function handler(
  client: CloseBotClient,
  name: string,
  args: Record<string, unknown>
): Promise<ToolResult> {
  try {
    switch (name) {
      case "get_agency_summary":
        return ok(
          await client.get<AgencyDashboardSummaryResponse>("/botMetric/agencySummary", {
            sourceId: args.sourceId,
          })
        );

      case "get_agency_metric":
        return ok(
          await client.get("/botMetric/agencyMetric", {
            metric: args.metric,
            start: args.start,
            end: args.end,
            resolution: args.resolution,
            sourceId: args.sourceId,
          })
        );

      case "get_booking_graph":
        return ok(
          await client.get("/botMetric/bookingGraph", {
            start: args.start,
            end: args.end,
            resolution: args.resolution,
            sourceId: args.sourceId,
          })
        );

      case "get_action_count":
        return ok(
          await client.get<number>("/botMetric/actionCount", {
            leadId: args.leadId,
            sourceId: args.sourceId,
            botId: args.botId,
            start: args.start,
            end: args.end,
          })
        );

      case "get_actions":
        return ok(
          await client.get<BotMetricAction[]>("/botMetric/actions", {
            leadId: args.leadId,
            sourceId: args.sourceId,
            botId: args.botId,
            start: args.start,
            end: args.end,
            maxCount: args.maxCount,
          })
        );

      case "get_message_count":
        return ok(
          await client.get<number>("/botMetric/messageCount", {
            sourceId: args.sourceId,
            leadId: args.leadId,
            start: args.start,
            end: args.end,
          })
        );

      case "get_messages":
        return ok(
          await client.get<BotMetricMessage[]>("/botMetric/messages", {
            sourceId: args.sourceId,
            leadId: args.leadId,
            start: args.start,
            end: args.end,
            maxCount: args.maxCount,
          })
        );

      case "get_message_feedback":
        return ok(
          await client.get<MessageFeedbackResponse>("/botMetric/messageFeedback", {
            leadId: args.leadId,
          })
        );

      case "save_message_feedback": {
        const body: MessageFeedbackRequest = {
          messageId: args.messageId as string,
          leadId: args.leadId as string,
          liked: args.liked as boolean | undefined,
          reasons: args.reasons as string | undefined,
        };
        return ok(await client.post("/botMetric/messageFeedback", body));
      }

      case "get_message_likes":
        return ok(
          await client.get<MessageLikesResponse>("/botMetric/messageLikes", {
            leadId: args.leadId,
          })
        );

      case "get_message_reason":
        return ok(
          await client.get<MessageReason>("/botMetric/messageReason", {
            messageId: args.messageId,
          })
        );

      case "get_leaderboard":
        return ok(
          await client.get<LeaderboardResponse[]>("/botMetric/leaderboard", {
            metric: args.metric,
            start: args.start,
            end: args.end,
            numTopLeaders: args.numTopLeaders,
          })
        );

      case "get_local_leaderboard":
        return ok(
          await client.get<LeaderboardResponse[]>("/botMetric/localleaderboard", {
            metric: args.metric,
            start: args.start,
            end: args.end,
            numSurroundingAgencies: args.numSurroundingAgencies,
          })
        );

      case "get_logs":
        return ok(
          await client.get<BotMetricLog[]>("/botMetric/logs", {
            botId: args.botId,
            messageId: args.messageId,
            sourceId: args.sourceId,
            leadId: args.leadId,
            actionId: args.actionId,
            start: args.start,
            end: args.end,
            maxCount: args.maxCount,
          })
        );

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