import { CloseBotClient, ok, err } from "../client.js";
import type {
  ToolDefinition, ToolResult, PersonaDto, CreatePersonaInput, UpdatePersonaInput,
  SmartFAQDto, CreateSmartFAQRequest, AnswerMultipleFAQsRequest, AnsweredFAQFollowUpRequest,
  ListHierarchyResult, AddHierarchyInput, HierarchyInput,
  NotificationDto, NotificationUpdateDto, NotificationForwardingDto,
  ApiKeyDTO, CreateApiKeyInput, CreateApiKeyOutput,
  LiveDemoDto, LiveDemoCreateDto,
  BotVariableDto, BotVariableUpdateInput,
} from "../types.js";

export const tools: ToolDefinition[] = [
  // --- Personas ---
  {
    name: "list_personas",
    description: "List all personas in the agency",
    inputSchema: { type: "object", properties: {} },
  },
  {
    name: "get_persona",
    description: "Get a persona by ID",
    inputSchema: {
      type: "object",
      properties: { id: { type: "string", description: "Persona ID" } },
      required: ["id"],
    },
  },
  {
    name: "create_persona",
    description: "Create a new persona with voice style, response settings, and AI preferences",
    inputSchema: {
      type: "object",
      properties: {
        personaName: { type: "string", description: "Persona name" },
        description: { type: "string", description: "Description" },
        voiceStyles: { type: "string", description: "Voice styles" },
        howToRespond: { type: "string", description: "How to respond instructions" },
        typoPercent: { type: "number", description: "Typo percentage (0-100)" },
        breakupLargeMessagePercent: { type: "number", description: "Break up large message percent (0-100)" },
        responseTime: { type: "string", description: "Response time setting" },
        responseDelay: { type: "number", description: "Response delay in ms" },
        aiProviderPreferences: { type: "array", items: { type: "string" }, description: "AI provider preferences" },
        color: { type: "string", description: "Persona color" },
      },
      required: ["personaName"],
    },
  },
  {
    name: "update_persona",
    description: "Update a persona. Only non-null fields are updated.",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "string", description: "Persona ID" },
        personaName: { type: "string" },
        description: { type: "string" },
        voiceStyles: { type: "string" },
        howToRespond: { type: "string" },
        typoPercent: { type: "number" },
        breakupLargeMessagePercent: { type: "number" },
        responseTime: { type: "string" },
        responseDelay: { type: "number" },
        aiProviderPreferences: { type: "array", items: { type: "string" } },
        folderId: { type: "string" },
        favorited: { type: "boolean" },
        trash: { type: "boolean" },
        default: { type: "boolean" },
        color: { type: "string" },
      },
      required: ["id"],
    },
  },
  {
    name: "delete_persona",
    description: "Delete a persona",
    inputSchema: {
      type: "object",
      properties: { id: { type: "string", description: "Persona ID" } },
      required: ["id"],
    },
  },
  // --- FAQs ---
  {
    name: "list_faqs",
    description: "List smart FAQs, optionally filtered by source, state, and answered status",
    inputSchema: {
      type: "object",
      properties: {
        sourceId: { type: "string", description: "Source ID" },
        state: { type: "string", description: "State: compressed or uncompressed" },
        answered: { type: "string", description: "Filter: answered or unanswered" },
      },
    },
  },
  {
    name: "create_faq",
    description: "Create a new FAQ for a source",
    inputSchema: {
      type: "object",
      properties: {
        sourceId: { type: "string", description: "Source ID" },
        question: { type: "string", description: "FAQ question" },
        answer: { type: "string", description: "FAQ answer" },
      },
      required: ["sourceId", "question"],
    },
  },
  {
    name: "delete_faq",
    description: "Delete an FAQ",
    inputSchema: {
      type: "object",
      properties: { id: { type: "string", description: "FAQ ID" } },
      required: ["id"],
    },
  },
  {
    name: "answer_faqs",
    description: "Answer multiple FAQs at once",
    inputSchema: {
      type: "object",
      properties: {
        faqs: {
          type: "array",
          items: {
            type: "object",
            properties: {
              id: { type: "string", description: "FAQ ID" },
              answer: { type: "string", description: "Answer text" },
            },
          },
          description: "Array of FAQ answers",
        },
      },
      required: ["faqs"],
    },
  },
  {
    name: "followup_answered_faqs",
    description: "Follow up with leads who asked a now-answered FAQ",
    inputSchema: {
      type: "object",
      properties: {
        faqId: { type: "string", description: "The answered FAQ ID" },
        leadIds: { type: "array", items: { type: "string" }, description: "Lead IDs to follow up with" },
      },
      required: ["faqId", "leadIds"],
    },
  },
  // --- Folders ---
  {
    name: "list_folders",
    description: "List all folders (hierarchy) in the agency",
    inputSchema: { type: "object", properties: {} },
  },
  {
    name: "get_folder",
    description: "Get a folder by ID",
    inputSchema: {
      type: "object",
      properties: { id: { type: "string", description: "Folder ID" } },
      required: ["id"],
    },
  },
  {
    name: "create_folder",
    description: "Create a new folder",
    inputSchema: {
      type: "object",
      properties: {
        name: { type: "string", description: "Folder name" },
        parentId: { type: "string", description: "Parent folder ID" },
      },
      required: ["name"],
    },
  },
  {
    name: "update_folder",
    description: "Rename a folder",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "string", description: "Folder ID" },
        name: { type: "string", description: "New name" },
      },
      required: ["id", "name"],
    },
  },
  {
    name: "delete_folder",
    description: "Delete a folder",
    inputSchema: {
      type: "object",
      properties: { id: { type: "string", description: "Folder ID" } },
      required: ["id"],
    },
  },
  // --- Notifications ---
  {
    name: "list_notifications",
    description: "List all notifications",
    inputSchema: { type: "object", properties: {} },
  },
  {
    name: "update_notification",
    description: "Update a notification (mark as viewed)",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "string", description: "Notification ID" },
        viewed: { type: "boolean", description: "Mark as viewed" },
      },
      required: ["id"],
    },
  },
  {
    name: "delete_notification",
    description: "Delete a notification",
    inputSchema: {
      type: "object",
      properties: { id: { type: "string", description: "Notification ID" } },
      required: ["id"],
    },
  },
  {
    name: "get_notification_forwarding",
    description: "Get notification forwarding settings",
    inputSchema: { type: "object", properties: {} },
  },
  {
    name: "update_notification_forwarding",
    description: "Update notification forwarding settings",
    inputSchema: {
      type: "object",
      properties: {
        enabled: { type: "boolean", description: "Enable forwarding" },
        channelsEnabled: { type: "array", items: { type: "string" }, description: "Channels to forward" },
        webhookEndpoint: { type: "string", description: "Webhook endpoint" },
      },
    },
  },
  // --- API Keys ---
  {
    name: "list_api_keys",
    description: "List all API keys",
    inputSchema: { type: "object", properties: {} },
  },
  {
    name: "create_api_key",
    description: "Create a new API key",
    inputSchema: {
      type: "object",
      properties: { name: { type: "string", description: "Key name" } },
      required: ["name"],
    },
  },
  {
    name: "delete_api_key",
    description: "Delete an API key",
    inputSchema: {
      type: "object",
      properties: { keyId: { type: "string", description: "Key ID" } },
      required: ["keyId"],
    },
  },
  // --- Webhook ---
  {
    name: "send_webhook_event",
    description: "Send a webhook event to a WebHook source",
    inputSchema: {
      type: "object",
      properties: {
        sourceId: { type: "string", description: "The WebHook source ID" },
        body: { type: "object", description: "The webhook event body (any JSON)" },
      },
      required: ["sourceId", "body"],
    },
  },
  // --- Live Demo ---
  {
    name: "list_live_demos",
    description: "List live demos for a bot",
    inputSchema: {
      type: "object",
      properties: { botId: { type: "string", description: "Bot ID" } },
      required: ["botId"],
    },
  },
  {
    name: "create_live_demo",
    description: "Create a live demo for a bot",
    inputSchema: {
      type: "object",
      properties: {
        botId: { type: "string", description: "Bot ID" },
        name: { type: "string", description: "Demo name" },
        mimicSourceId: { type: "string", description: "Source ID to mimic" },
        active: { type: "boolean", description: "Whether demo is active" },
      },
      required: ["botId", "name"],
    },
  },
  {
    name: "update_live_demo",
    description: "Update a live demo",
    inputSchema: {
      type: "object",
      properties: {
        botId: { type: "string", description: "Bot ID" },
        key: { type: "string", description: "Demo key" },
        name: { type: "string", description: "Demo name" },
        mimicSourceId: { type: "string", description: "Source ID to mimic" },
        active: { type: "boolean", description: "Whether active" },
      },
      required: ["botId", "key"],
    },
  },
  {
    name: "delete_live_demo",
    description: "Delete a live demo",
    inputSchema: {
      type: "object",
      properties: {
        botId: { type: "string", description: "Bot ID" },
        key: { type: "string", description: "Demo key" },
      },
      required: ["botId", "key"],
    },
  },
  // --- Bot Source Variables ---
  {
    name: "get_source_variables",
    description: "Get source variables for a bot-source pair",
    inputSchema: {
      type: "object",
      properties: {
        botId: { type: "string", description: "Bot ID" },
        sourceId: { type: "string", description: "Source ID" },
      },
      required: ["botId", "sourceId"],
    },
  },
  {
    name: "update_source_variables",
    description: "Update source variables for a bot-source pair",
    inputSchema: {
      type: "object",
      properties: {
        botId: { type: "string", description: "Bot ID" },
        sourceId: { type: "string", description: "Source ID" },
        variables: {
          type: "array",
          items: {
            type: "object",
            properties: {
              id: { type: "string", description: "Variable ID" },
              value: { type: "string", description: "Variable value" },
            },
          },
          description: "Variables to update",
        },
      },
      required: ["botId", "sourceId", "variables"],
    },
  },
];

export async function handler(
  client: CloseBotClient,
  name: string,
  args: Record<string, unknown>
): Promise<ToolResult> {
  try {
    switch (name) {
      // Personas
      case "list_personas":
        return ok(await client.get<PersonaDto[]>("/persona"));
      case "get_persona":
        return ok(await client.get<PersonaDto>(`/persona/${args.id}`));
      case "create_persona": {
        const body: CreatePersonaInput = {
          personaName: args.personaName as string,
          description: args.description as string | undefined,
          voiceStyles: args.voiceStyles as string | undefined,
          howToRespond: args.howToRespond as string | undefined,
          typoPercent: (args.typoPercent as number) || 0,
          breakupLargeMessagePercent: (args.breakupLargeMessagePercent as number) || 0,
          responseTime: args.responseTime as string | undefined,
          responseDelay: (args.responseDelay as number) || 0,
          aiProviderPreferences: args.aiProviderPreferences as string[] | undefined,
          color: args.color as string | undefined,
        };
        return ok(await client.post("/persona", body));
      }
      case "update_persona": {
        const { id, ...rest } = args;
        const body: UpdatePersonaInput = {};
        for (const [k, v] of Object.entries(rest)) {
          if (v !== undefined) (body as Record<string, unknown>)[k] = v;
        }
        return ok(await client.put<PersonaDto>(`/persona/${id}`, body));
      }
      case "delete_persona":
        return ok(await client.delete(`/persona/${args.id}`));

      // FAQs
      case "list_faqs":
        return ok(
          await client.get<SmartFAQDto[]>("/smart-faq", {
            sourceId: args.sourceId,
            state: args.state,
            answered: args.answered,
          })
        );
      case "create_faq": {
        const body: CreateSmartFAQRequest = {
          sourceId: args.sourceId as string,
          question: args.question as string,
          answer: args.answer as string | undefined,
        };
        return ok(await client.post("/smart-faq", body));
      }
      case "delete_faq":
        return ok(await client.delete(`/smart-faq/${args.id}`));
      case "answer_faqs": {
        const body: AnswerMultipleFAQsRequest = {
          faQs: args.faqs as Array<{ id?: string; answer?: string }>,
        };
        return ok(await client.post<SmartFAQDto[]>("/smart-faq/answer", body));
      }
      case "followup_answered_faqs": {
        const body: AnsweredFAQFollowUpRequest = {
          faqId: args.faqId as string,
          leadIds: args.leadIds as string[],
        };
        return ok(await client.post("/smart-faq/answered-followup", body));
      }

      // Folders
      case "list_folders":
        return ok(await client.get<ListHierarchyResult[]>("/hierarchy"));
      case "get_folder":
        return ok(await client.get<ListHierarchyResult>(`/hierarchy/${args.id}`));
      case "create_folder": {
        const body: AddHierarchyInput = {
          name: args.name as string,
          parentId: args.parentId as string | undefined,
        };
        return ok(await client.post("/hierarchy", body));
      }
      case "update_folder": {
        const body: HierarchyInput = { name: args.name as string };
        return ok(await client.put(`/hierarchy/${args.id}`, body));
      }
      case "delete_folder":
        return ok(await client.delete(`/hierarchy/${args.id}`));

      // Notifications
      case "list_notifications":
        return ok(await client.get<NotificationDto[]>("/notifications"));
      case "update_notification": {
        const body: NotificationUpdateDto = { viewed: args.viewed as boolean };
        return ok(await client.put<NotificationDto>(`/notifications/${args.id}`, body));
      }
      case "delete_notification":
        return ok(await client.delete<NotificationDto>(`/notifications/${args.id}`));
      case "get_notification_forwarding":
        return ok(await client.get("/notifications/forwarding"));
      case "update_notification_forwarding": {
        const body: NotificationForwardingDto = {
          enabled: args.enabled as boolean,
          channelsEnabled: args.channelsEnabled as string[] | undefined,
          webhookEndpoint: args.webhookEndpoint as string | undefined,
        };
        return ok(await client.put("/notifications/forwarding", body));
      }

      // API Keys
      case "list_api_keys":
        return ok(await client.get<ApiKeyDTO[]>("/account/apiKey"));
      case "create_api_key": {
        const body: CreateApiKeyInput = { name: args.name as string };
        return ok(await client.post<CreateApiKeyOutput>("/account/apiKey", body));
      }
      case "delete_api_key":
        return ok(await client.delete(`/account/apiKey/${args.keyId}`));

      // Webhook
      case "send_webhook_event":
        return ok(
          await client.post(`/webhook/event/${args.sourceId}`, args.body)
        );

      // Live Demo
      case "list_live_demos":
        return ok(await client.get<LiveDemoDto[]>(`/bot-live-demo/${args.botId}`));
      case "create_live_demo": {
        const body: LiveDemoCreateDto = {
          name: args.name as string,
          mimicSourceId: args.mimicSourceId as string | undefined,
          active: (args.active as boolean) ?? true,
        };
        return ok(await client.post<LiveDemoDto>(`/bot-live-demo/${args.botId}`, body));
      }
      case "update_live_demo": {
        const body: LiveDemoCreateDto = {
          name: args.name as string | undefined,
          mimicSourceId: args.mimicSourceId as string | undefined,
          active: args.active as boolean | undefined,
        };
        return ok(
          await client.put<LiveDemoDto>(`/bot-live-demo/${args.botId}/${args.key}`, body)
        );
      }
      case "delete_live_demo":
        return ok(await client.delete(`/bot-live-demo/${args.botId}/${args.key}`));

      // Bot Source Variables
      case "get_source_variables":
        return ok(
          await client.get<BotVariableDto[]>(
            `/botVariables/${args.botId}/${args.sourceId}`
          )
        );
      case "update_source_variables":
        return ok(
          await client.post(
            `/botVariables/${args.botId}/${args.sourceId}`,
            args.variables as BotVariableUpdateInput[]
          )
        );

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