import { CloseBotClient, ok, err } from "../client.js";
import type { ToolDefinition, ToolResult, SourceDto, SourceDtoPaginated, AddSourceInput, UpdateSourceInput, SourceCalendarDto, SourceChannelDto, SourceFieldCollectionDto, SourceTagDto } from "../types.js";

export const tools: ToolDefinition[] = [
  {
    name: "list_sources",
    description: "List sources in the agency with pagination and filtering",
    inputSchema: {
      type: "object",
      properties: {
        page: { type: "number", description: "Page number (0-indexed)" },
        pageSize: { type: "number", description: "Page size (max 100, default 20)" },
        query: { type: "string", description: "Search by source name" },
        category: { type: "string", description: "Filter by category (GHL, HubSpot, WebHook, etc.)" },
        order: { type: "string", description: "Order results. +/- prefix for asc/desc (default: +id)" },
        forceTokenRefresh: { type: "boolean", description: "Refresh access tokens for returned sources" },
      },
    },
  },
  {
    name: "get_source",
    description: "Get detailed information for a single source",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "string", description: "The source ID" },
      },
      required: ["id"],
    },
  },
  {
    name: "add_source",
    description: "Add a new source to the agency",
    inputSchema: {
      type: "object",
      properties: {
        name: { type: "string", description: "Source name" },
        category: { type: "string", description: "Source category (GHL, WebHook, etc.)" },
        key: { type: "string", description: "Source key/identifier" },
        accessToken: { type: "string", description: "Access token for the source" },
        refreshToken: { type: "string", description: "Refresh token" },
        expiresIn: { type: "number", description: "Token expiry in seconds" },
        autoShutoff: { type: "boolean", description: "Enable auto shutoff" },
        gracefulGoodbye: { type: "boolean", description: "Enable graceful goodbye" },
        summarizeAttachments: { type: "boolean", description: "Enable attachment summarization" },
        webhookCallback: { type: "string", description: "Webhook callback URL" },
      },
      required: ["name"],
    },
  },
  {
    name: "update_source",
    description: "Update source fields. Only non-null fields are updated.",
    inputSchema: {
      type: "object",
      properties: {
        sourceId: { type: "string", description: "The source ID" },
        name: { type: "string", description: "New name" },
        autoShutoff: { type: "boolean", description: "Auto shutoff setting" },
        gracefulGoodbye: { type: "boolean", description: "Graceful goodbye setting" },
        isAvailabilityContactTimezone: { type: "boolean", description: "Use contact timezone for availability" },
        summarizeAttachments: { type: "boolean", description: "Summarize attachments" },
        respondToReactions: { type: "boolean", description: "Respond to reactions" },
        markConversationsAsUnread: { type: "boolean", description: "Mark conversations as unread" },
        webhookCallback: { type: "string", description: "Webhook callback URL" },
      },
      required: ["sourceId"],
    },
  },
  {
    name: "delete_source",
    description: "Delete a source and all associated data. Also attempts to uninstall from external CRM.",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "string", description: "The source ID" },
      },
      required: ["id"],
    },
  },
  {
    name: "list_source_calendars",
    description: "List all calendars attached to a source (manual + CRM calendars)",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "string", description: "The source ID" },
      },
      required: ["id"],
    },
  },
  {
    name: "list_source_channels",
    description: "List all channels available to a source",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "string", description: "The source ID" },
      },
      required: ["id"],
    },
  },
  {
    name: "list_source_fields",
    description: "List available fields for a source (contact, location, custom values)",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "string", description: "The source ID" },
      },
      required: ["id"],
    },
  },
  {
    name: "list_source_tags",
    description: "List all tags for a source",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "string", description: "The source ID" },
      },
      required: ["id"],
    },
  },
];

export async function handler(
  client: CloseBotClient,
  name: string,
  args: Record<string, unknown>
): Promise<ToolResult> {
  try {
    switch (name) {
      case "list_sources":
        return ok(
          await client.get<SourceDtoPaginated>("/agency/source", {
            page: args.page,
            pageSize: args.pageSize,
            query: args.query,
            category: args.category,
            order: args.order,
            forceTokenRefresh: args.forceTokenRefresh,
          })
        );

      case "get_source":
        return ok(await client.get<SourceDto>(`/agency/source/${args.id}`));

      case "add_source": {
        const body: AddSourceInput = {
          name: args.name as string,
          category: args.category as string | undefined,
          key: args.key as string | undefined,
          accessToken: args.accessToken as string | undefined,
          refreshToken: args.refreshToken as string | undefined,
          expiresIn: args.expiresIn as number | undefined,
          autoShutoff: args.autoShutoff as boolean | undefined,
          gracefulGoodbye: args.gracefulGoodbye as boolean | undefined,
          summarizeAttachments: args.summarizeAttachments as boolean | undefined,
          webhookCallback: args.webhookCallback as string | undefined,
        };
        return ok(await client.post<SourceDto>("/agency/source", body));
      }

      case "update_source": {
        const { sourceId, ...rest } = args;
        const body: UpdateSourceInput = {};
        if (rest.name !== undefined) body.name = rest.name as string;
        if (rest.autoShutoff !== undefined) body.autoShutoff = rest.autoShutoff as boolean;
        if (rest.gracefulGoodbye !== undefined) body.gracefulGoodbye = rest.gracefulGoodbye as boolean;
        if (rest.isAvailabilityContactTimezone !== undefined)
          body.isAvailabilityContactTimezone = rest.isAvailabilityContactTimezone as boolean;
        if (rest.summarizeAttachments !== undefined)
          body.summarizeAttachments = rest.summarizeAttachments as boolean;
        if (rest.respondToReactions !== undefined)
          body.respondToReactions = rest.respondToReactions as boolean;
        if (rest.markConversationsAsUnread !== undefined)
          body.markConversationsAsUnread = rest.markConversationsAsUnread as boolean;
        if (rest.webhookCallback !== undefined)
          body.webhookCallback = rest.webhookCallback as string;
        return ok(await client.put<SourceDto>(`/agency/source/${sourceId}`, body));
      }

      case "delete_source":
        return ok(await client.delete(`/agency/source/${args.id}`));

      case "list_source_calendars":
        return ok(
          await client.get<SourceCalendarDto[]>(`/agency/source/${args.id}/calendars`)
        );

      case "list_source_channels":
        return ok(
          await client.get<SourceChannelDto[]>(`/agency/source/${args.id}/channels`)
        );

      case "list_source_fields":
        return ok(
          await client.get<SourceFieldCollectionDto>(`/agency/source/${args.id}/fields`)
        );

      case "list_source_tags":
        return ok(
          await client.get<SourceTagDto[]>(`/agency/source/${args.id}/tags`)
        );

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