import { PipedriveClient, err } from "../client.js";
import type { ToolDefinition, ToolResult, Deal } from "../types.js";

export const tools: ToolDefinition[] = [
  {
    name: "pipedrive_deals_list",
    description: "List all deals with optional filters (status, stage_id, user_id, etc.)",
    inputSchema: {
      type: "object",
      properties: {
        filter_id: { type: "number", description: "ID of the filter to use" },
        stage_id: { type: "number", description: "Filter by pipeline stage" },
        status: { type: "string", description: "Filter by status: open, won, lost, deleted, all_not_deleted" },
        user_id: { type: "number", description: "Filter by owner user ID" },
        sort: { type: "string", description: "Field to sort by (e.g., 'add_time', 'update_time', 'value')" },
        start: { type: "number", description: "Pagination start (default 0)" },
        limit: { type: "number", description: "Items per page (default 100, max 500)" },
      },
    },
  },
  {
    name: "pipedrive_deal_get",
    description: "Get a single deal by ID with all details",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "number", description: "Deal ID" },
      },
      required: ["id"],
    },
  },
  {
    name: "pipedrive_deal_create",
    description: "Create a new deal",
    inputSchema: {
      type: "object",
      properties: {
        title: { type: "string", description: "Deal title" },
        value: { type: "number", description: "Deal value" },
        currency: { type: "string", description: "3-letter currency code (default USD)" },
        user_id: { type: "number", description: "Owner user ID" },
        person_id: { type: "number", description: "Associated person ID" },
        org_id: { type: "number", description: "Associated organization ID" },
        stage_id: { type: "number", description: "Pipeline stage ID" },
        status: { type: "string", description: "open, won, lost, deleted" },
        expected_close_date: { type: "string", description: "Expected close date (YYYY-MM-DD)" },
        probability: { type: "number", description: "Win probability (0-100)" },
        visible_to: { type: "string", description: "Visibility: 1, 3, 5, 7" },
      },
      required: ["title"],
    },
  },
  {
    name: "pipedrive_deal_update",
    description: "Update an existing deal",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "number", description: "Deal ID" },
        title: { type: "string" },
        value: { type: "number" },
        currency: { type: "string" },
        stage_id: { type: "number" },
        status: { type: "string" },
        person_id: { type: "number" },
        org_id: { type: "number" },
        expected_close_date: { type: "string" },
        probability: { type: "number" },
        lost_reason: { type: "string" },
      },
      required: ["id"],
    },
  },
  {
    name: "pipedrive_deal_delete",
    description: "Delete a deal",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "number", description: "Deal ID" },
      },
      required: ["id"],
    },
  },
  {
    name: "pipedrive_deals_search",
    description: "Search deals by term (searches title, notes, custom fields)",
    inputSchema: {
      type: "object",
      properties: {
        term: { type: "string", description: "Search term" },
        fields: { type: "string", description: "Fields to search (default: all)" },
        exact_match: { type: "boolean", description: "Exact match only" },
        include_fields: { type: "string", description: "Additional fields to include" },
        start: { type: "number" },
        limit: { type: "number" },
      },
      required: ["term"],
    },
  },
  {
    name: "pipedrive_deal_merge",
    description: "Merge two deals",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "number", description: "Deal ID to keep" },
        merge_with_id: { type: "number", description: "Deal ID to merge and delete" },
      },
      required: ["id", "merge_with_id"],
    },
  },
  {
    name: "pipedrive_deal_duplicate",
    description: "Duplicate a deal",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "number", description: "Deal ID to duplicate" },
      },
      required: ["id"],
    },
  },
  {
    name: "pipedrive_deal_activities",
    description: "List all activities for a deal",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "number", description: "Deal ID" },
        start: { type: "number" },
        limit: { type: "number" },
        done: { type: "number", description: "Filter by done status: 0 or 1" },
      },
      required: ["id"],
    },
  },
  {
    name: "pipedrive_deal_participants",
    description: "List all participants (persons) for a deal",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "number", description: "Deal ID" },
        start: { type: "number" },
        limit: { type: "number" },
      },
      required: ["id"],
    },
  },
  {
    name: "pipedrive_deal_followers",
    description: "List all followers for a deal",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "number", description: "Deal ID" },
      },
      required: ["id"],
    },
  },
  {
    name: "pipedrive_deal_add_follower",
    description: "Add a follower to a deal",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "number", description: "Deal ID" },
        user_id: { type: "number", description: "User ID to add as follower" },
      },
      required: ["id", "user_id"],
    },
  },
  {
    name: "pipedrive_deal_files",
    description: "List all files attached to a deal",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "number", description: "Deal ID" },
        start: { type: "number" },
        limit: { type: "number" },
      },
      required: ["id"],
    },
  },
  {
    name: "pipedrive_deal_add_product",
    description: "Attach a product to a deal",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "number", description: "Deal ID" },
        product_id: { type: "number", description: "Product ID" },
        item_price: { type: "number", description: "Price per item" },
        quantity: { type: "number", description: "Quantity" },
        discount_percentage: { type: "number" },
        duration: { type: "number" },
        product_variation_id: { type: "number" },
        comments: { type: "string" },
        enabled_flag: { type: "boolean" },
      },
      required: ["id", "product_id", "item_price", "quantity"],
    },
  },
  {
    name: "pipedrive_deal_update_product",
    description: "Update a product attached to a deal",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "number", description: "Deal ID" },
        product_attachment_id: { type: "number", description: "Product attachment ID" },
        item_price: { type: "number" },
        quantity: { type: "number" },
        discount_percentage: { type: "number" },
        comments: { type: "string" },
        enabled_flag: { type: "boolean" },
      },
      required: ["id", "product_attachment_id"],
    },
  },
  {
    name: "pipedrive_deal_remove_product",
    description: "Remove a product from a deal",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "number", description: "Deal ID" },
        product_attachment_id: { type: "number", description: "Product attachment ID" },
      },
      required: ["id", "product_attachment_id"],
    },
  },
  {
    name: "pipedrive_deal_flow",
    description: "List updates about a deal (flow/timeline)",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "number", description: "Deal ID" },
        start: { type: "number" },
        limit: { type: "number" },
      },
      required: ["id"],
    },
  },
];

export async function handle(
  client: PipedriveClient,
  name: string,
  args: Record<string, unknown>
): Promise<ToolResult> {
  try {
    switch (name) {
      case "pipedrive_deals_list": {
        const params: Record<string, unknown> = {};
        if (args.filter_id) params.filter_id = args.filter_id;
        if (args.stage_id) params.stage_id = args.stage_id;
        if (args.status) params.status = args.status;
        if (args.user_id) params.user_id = args.user_id;
        if (args.sort) params.sort = args.sort;
        if (args.start !== undefined) params.start = args.start;
        if (args.limit !== undefined) params.limit = args.limit;

        const result = await client.get<{ success: boolean; data: Deal[] }>("/deals", params);
        const deals = result.data || [];
        return {
          content: [{
            type: "text",
            text: `Found ${deals.length} deals\n${deals.map((d) => `- [${d.id}] ${d.title} (${d.status}, value: ${d.value} ${d.currency})`).join("\n")}`,
          }],
        };
      }

      case "pipedrive_deal_get": {
        const result = await client.get<{ success: boolean; data: Deal }>(`/deals/${args.id}`);
        const deal = result.data;
        return {
          content: [{
            type: "text",
            text: `Deal: ${deal.title}\nID: ${deal.id}\nStatus: ${deal.status}\nValue: ${deal.value} ${deal.currency}\nStage ID: ${deal.stage_id}\nPerson ID: ${deal.person_id || "N/A"}\nOrg ID: ${deal.org_id || "N/A"}\nExpected close: ${deal.expected_close_date || "N/A"}\nProbability: ${deal.probability || 0}%`,
          }],
        };
      }

      case "pipedrive_deal_create": {
        const body: Record<string, unknown> = { title: args.title };
        if (args.value) body.value = args.value;
        if (args.currency) body.currency = args.currency;
        if (args.user_id) body.user_id = args.user_id;
        if (args.person_id) body.person_id = args.person_id;
        if (args.org_id) body.org_id = args.org_id;
        if (args.stage_id) body.stage_id = args.stage_id;
        if (args.status) body.status = args.status;
        if (args.expected_close_date) body.expected_close_date = args.expected_close_date;
        if (args.probability !== undefined) body.probability = args.probability;
        if (args.visible_to) body.visible_to = args.visible_to;

        const result = await client.post<{ success: boolean; data: Deal }>("/deals", body);
        const deal = result.data;
        return {
          content: [{
            type: "text",
            text: `Created deal: ${deal.title} (ID: ${deal.id})`,
          }],
        };
      }

      case "pipedrive_deal_update": {
        const { id, ...updateData } = args;
        const result = await client.put<{ success: boolean; data: Deal }>(`/deals/${id}`, updateData);
        const deal = result.data;
        return {
          content: [{
            type: "text",
            text: `Updated deal: ${deal.title} (ID: ${deal.id})`,
          }],
        };
      }

      case "pipedrive_deal_delete": {
        await client.delete(`/deals/${args.id}`);
        return {
          content: [{ type: "text", text: `Deleted deal ${args.id}` }],
        };
      }

      case "pipedrive_deals_search": {
        const params: Record<string, unknown> = { term: args.term };
        if (args.fields) params.fields = args.fields;
        if (args.exact_match !== undefined) params.exact_match = args.exact_match;
        if (args.include_fields) params.include_fields = args.include_fields;
        if (args.start !== undefined) params.start = args.start;
        if (args.limit !== undefined) params.limit = args.limit;

        const result = await client.get<{ success: boolean; data?: { items?: Array<{ item: Deal }> } }>("/deals/search", params);
        const items = result.data?.items || [];
        const deals = items.map((i) => i.item);
        return {
          content: [{
            type: "text",
            text: `Found ${deals.length} deals matching "${args.term}"\n${deals.map((d) => `- [${d.id}] ${d.title}`).join("\n")}`,
          }],
        };
      }

      case "pipedrive_deal_merge": {
        const result = await client.put<{ success: boolean; data: Deal }>(`/deals/${args.id}/merge`, { merge_with_id: args.merge_with_id });
        return {
          content: [{ type: "text", text: `Merged deal ${args.merge_with_id} into ${args.id}` }],
        };
      }

      case "pipedrive_deal_duplicate": {
        const result = await client.post<{ success: boolean; data: Deal }>(`/deals/${args.id}/duplicate`);
        const deal = result.data;
        return {
          content: [{ type: "text", text: `Duplicated deal ${args.id} → new deal ID: ${deal.id}` }],
        };
      }

      case "pipedrive_deal_activities": {
        const params: Record<string, unknown> = {};
        if (args.start !== undefined) params.start = args.start;
        if (args.limit !== undefined) params.limit = args.limit;
        if (args.done !== undefined) params.done = args.done;

        const result = await client.get<{ success: boolean; data: unknown[] }>(`/deals/${args.id}/activities`, params);
        const activities = result.data || [];
        return {
          content: [{ type: "text", text: `Found ${activities.length} activities for deal ${args.id}` }],
        };
      }

      case "pipedrive_deal_participants": {
        const params: Record<string, unknown> = {};
        if (args.start !== undefined) params.start = args.start;
        if (args.limit !== undefined) params.limit = args.limit;

        const result = await client.get<{ success: boolean; data: unknown[] }>(`/deals/${args.id}/participants`, params);
        const participants = result.data || [];
        return {
          content: [{ type: "text", text: `Found ${participants.length} participants for deal ${args.id}` }],
        };
      }

      case "pipedrive_deal_followers": {
        const result = await client.get<{ success: boolean; data: Array<{ id: number; user_id: number; add_time?: string }> }>(`/deals/${args.id}/followers`);
        const followers = result.data || [];
        return {
          content: [{ type: "text", text: `Deal ${args.id} has ${followers.length} followers: ${followers.map((f) => f.user_id).join(", ")}` }],
        };
      }

      case "pipedrive_deal_add_follower": {
        const result = await client.post(`/deals/${args.id}/followers`, { user_id: args.user_id });
        return {
          content: [{ type: "text", text: `Added user ${args.user_id} as follower to deal ${args.id}` }],
        };
      }

      case "pipedrive_deal_files": {
        const params: Record<string, unknown> = {};
        if (args.start !== undefined) params.start = args.start;
        if (args.limit !== undefined) params.limit = args.limit;

        const result = await client.get<{ success: boolean; data: unknown[] }>(`/deals/${args.id}/files`, params);
        const files = result.data || [];
        return {
          content: [{ type: "text", text: `Found ${files.length} files for deal ${args.id}` }],
        };
      }

      case "pipedrive_deal_add_product": {
        const { id, ...productData } = args;
        const result = await client.post(`/deals/${id}/products`, productData);
        return {
          content: [{ type: "text", text: `Added product ${args.product_id} to deal ${id}` }],
        };
      }

      case "pipedrive_deal_update_product": {
        const { id, product_attachment_id, ...updateData } = args;
        const result = await client.put(`/deals/${id}/products/${product_attachment_id}`, updateData);
        return {
          content: [{ type: "text", text: `Updated product attachment ${product_attachment_id} on deal ${id}` }],
        };
      }

      case "pipedrive_deal_remove_product": {
        await client.delete(`/deals/${args.id}/products/${args.product_attachment_id}`);
        return {
          content: [{ type: "text", text: `Removed product attachment ${args.product_attachment_id} from deal ${args.id}` }],
        };
      }

      case "pipedrive_deal_flow": {
        const params: Record<string, unknown> = {};
        if (args.start !== undefined) params.start = args.start;
        if (args.limit !== undefined) params.limit = args.limit;

        const result = await client.get<{ success: boolean; data: unknown[] }>(`/deals/${args.id}/flow`, params);
        const updates = result.data || [];
        return {
          content: [{ type: "text", text: `Found ${updates.length} timeline updates for deal ${args.id}` }],
        };
      }

      default:
        return {
          content: [{ type: "text", text: `Unknown tool: ${name}` }],
          isError: true,
        };
    }
  } catch (error) {
    return err(error);
  }
}
