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

export const tools: ToolDefinition[] = [
  {
    name: "pipedrive_persons_list",
    description: "List all persons with optional filters",
    inputSchema: {
      type: "object",
      properties: {
        filter_id: { type: "number", description: "ID of the filter to use" },
        user_id: { type: "number", description: "Filter by owner user ID" },
        org_id: { type: "number", description: "Filter by organization ID" },
        sort: { type: "string", description: "Field to sort by" },
        start: { type: "number" },
        limit: { type: "number" },
      },
    },
  },
  {
    name: "pipedrive_person_get",
    description: "Get a single person by ID",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "number", description: "Person ID" },
      },
      required: ["id"],
    },
  },
  {
    name: "pipedrive_person_create",
    description: "Create a new person",
    inputSchema: {
      type: "object",
      properties: {
        name: { type: "string", description: "Person name" },
        email: { type: "string", description: "Email address" },
        phone: { type: "string", description: "Phone number" },
        org_id: { type: "number", description: "Organization ID" },
        owner_id: { type: "number", description: "Owner user ID" },
        visible_to: { type: "string", description: "Visibility: 1, 3, 5, 7" },
      },
      required: ["name"],
    },
  },
  {
    name: "pipedrive_person_update",
    description: "Update an existing person",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "number", description: "Person ID" },
        name: { type: "string" },
        email: { type: "string" },
        phone: { type: "string" },
        org_id: { type: "number" },
        owner_id: { type: "number" },
      },
      required: ["id"],
    },
  },
  {
    name: "pipedrive_person_delete",
    description: "Delete a person",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "number", description: "Person ID" },
      },
      required: ["id"],
    },
  },
  {
    name: "pipedrive_persons_search",
    description: "Search persons by term",
    inputSchema: {
      type: "object",
      properties: {
        term: { type: "string", description: "Search term" },
        fields: { type: "string" },
        exact_match: { type: "boolean" },
        start: { type: "number" },
        limit: { type: "number" },
      },
      required: ["term"],
    },
  },
  {
    name: "pipedrive_person_merge",
    description: "Merge two persons",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "number", description: "Person ID to keep" },
        merge_with_id: { type: "number", description: "Person ID to merge and delete" },
      },
      required: ["id", "merge_with_id"],
    },
  },
  {
    name: "pipedrive_person_deals",
    description: "List all deals for a person",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "number", description: "Person ID" },
        start: { type: "number" },
        limit: { type: "number" },
        status: { type: "string", description: "Filter by deal status" },
      },
      required: ["id"],
    },
  },
  {
    name: "pipedrive_person_activities",
    description: "List all activities for a person",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "number", description: "Person ID" },
        start: { type: "number" },
        limit: { type: "number" },
      },
      required: ["id"],
    },
  },
  {
    name: "pipedrive_person_files",
    description: "List all files for a person",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "number", description: "Person ID" },
        start: { type: "number" },
        limit: { type: "number" },
      },
      required: ["id"],
    },
  },
  {
    name: "pipedrive_person_followers",
    description: "List all followers for a person",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "number", description: "Person ID" },
      },
      required: ["id"],
    },
  },
];

export async function handle(
  client: PipedriveClient,
  name: string,
  args: Record<string, unknown>
): Promise<ToolResult> {
  try {
    switch (name) {
      case "pipedrive_persons_list": {
        const params: Record<string, unknown> = {};
        if (args.filter_id) params.filter_id = args.filter_id;
        if (args.user_id) params.user_id = args.user_id;
        if (args.org_id) params.org_id = args.org_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: Person[] }>("/persons", params);
        const persons = result.data || [];
        return {
          content: [{
            type: "text",
            text: `Found ${persons.length} persons\n${persons.map((p) => `- [${p.id}] ${p.name} (${p.email?.[0]?.value || "no email"})`).join("\n")}`,
          }],
        };
      }

      case "pipedrive_person_get": {
        const result = await client.get<{ success: boolean; data: Person }>(`/persons/${args.id}`);
        const person = result.data;
        const email = person.email?.[0]?.value || "N/A";
        const phone = person.phone?.[0]?.value || "N/A";
        return {
          content: [{
            type: "text",
            text: `Person: ${person.name}\nID: ${person.id}\nEmail: ${email}\nPhone: ${phone}\nOrg ID: ${person.org_id || "N/A"}\nOwner ID: ${person.owner_id || "N/A"}`,
          }],
        };
      }

      case "pipedrive_person_create": {
        const body: Record<string, unknown> = { name: args.name };
        if (args.email) body.email = [{ value: args.email, primary: true }];
        if (args.phone) body.phone = [{ value: args.phone, primary: true }];
        if (args.org_id) body.org_id = args.org_id;
        if (args.owner_id) body.owner_id = args.owner_id;
        if (args.visible_to) body.visible_to = args.visible_to;

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

      case "pipedrive_person_update": {
        const { id, email, phone, ...updateData } = args;
        const body: Record<string, unknown> = { ...updateData };
        if (email) body.email = [{ value: email, primary: true }];
        if (phone) body.phone = [{ value: phone, primary: true }];

        const result = await client.put<{ success: boolean; data: Person }>(`/persons/${id}`, body);
        const person = result.data;
        return {
          content: [{
            type: "text",
            text: `Updated person: ${person.name} (ID: ${person.id})`,
          }],
        };
      }

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

      case "pipedrive_persons_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.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: Person }> } }>("/persons/search", params);
        const items = result.data?.items || [];
        const persons = items.map((i) => i.item);
        return {
          content: [{
            type: "text",
            text: `Found ${persons.length} persons matching "${args.term}"\n${persons.map((p) => `- [${p.id}] ${p.name}`).join("\n")}`,
          }],
        };
      }

      case "pipedrive_person_merge": {
        await client.put(`/persons/${args.id}/merge`, { merge_with_id: args.merge_with_id });
        return {
          content: [{ type: "text", text: `Merged person ${args.merge_with_id} into ${args.id}` }],
        };
      }

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

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

      case "pipedrive_person_activities": {
        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[] }>(`/persons/${args.id}/activities`, params);
        const activities = result.data || [];
        return {
          content: [{ type: "text", text: `Found ${activities.length} activities for person ${args.id}` }],
        };
      }

      case "pipedrive_person_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[] }>(`/persons/${args.id}/files`, params);
        const files = result.data || [];
        return {
          content: [{ type: "text", text: `Found ${files.length} files for person ${args.id}` }],
        };
      }

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

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