/**
 * Intercom Conversations Tools
 */

import { z } from 'zod';
import { Tool } from '@modelcontextprotocol/sdk/types.js';
import type { IntercomClient } from '../clients/intercom.js';

// Zod schemas
const CreateConversationSchema = z.object({
  from: z.object({
    type: z.enum(['user', 'lead', 'contact']),
    id: z.string().optional(),
    user_id: z.string().optional(),
    email: z.string().email().optional(),
  }),
  body: z.string(),
});

const ReplyConversationSchema = z.object({
  id: z.string(),
  message_type: z.enum(['comment', 'note']),
  type: z.enum(['admin', 'user']),
  admin_id: z.string().optional(),
  body: z.string(),
  attachment_urls: z.array(z.string().url()).optional(),
  created_at: z.number().optional(),
});

const SearchConversationsSchema = z.object({
  query: z.object({
    field: z.string().optional(),
    operator: z.string().optional(),
    value: z.union([z.string(), z.number(), z.boolean(), z.array(z.string())]).optional(),
  }).optional(),
  pagination: z.object({
    per_page: z.number().max(150).optional(),
    starting_after: z.string().optional(),
  }).optional(),
  sort: z.object({
    field: z.string(),
    order: z.enum(['asc', 'desc']),
  }).optional(),
});

const AssignConversationSchema = z.object({
  id: z.string(),
  assignee_type: z.enum(['admin', 'team']),
  assignee_id: z.string(),
  admin_id: z.string().optional(),
});

const TagConversationSchema = z.object({
  id: z.string(),
  tag_id: z.string(),
  admin_id: z.string(),
});

// Tool definitions
export function getTools(client: IntercomClient): Array<{
  definition: Tool;
  handler: (args: Record<string, unknown>) => Promise<unknown>;
}> {
  return [
    {
      definition: {
        name: 'intercom_list_conversations',
        description: 'List all conversations with cursor-based pagination.',
        inputSchema: {
          type: 'object',
          properties: {
            per_page: {
              type: 'number',
              description: 'Number of results per page (max 150)',
              maximum: 150,
            },
            starting_after: {
              type: 'string',
              description: 'Cursor for pagination',
            },
          },
        },
      },
      handler: async (args) => {
        const params = args as { per_page?: number; starting_after?: string };
        return client.listConversations(params);
      },
    },

    {
      definition: {
        name: 'intercom_get_conversation',
        description: 'Retrieve a specific conversation by ID. Includes all conversation parts (messages, notes, assignments).',
        inputSchema: {
          type: 'object',
          properties: {
            id: {
              type: 'string',
              description: 'Conversation ID',
            },
          },
          required: ['id'],
        },
      },
      handler: async (args) => {
        const { id } = args as { id: string };
        return client.getConversation(id as any);
      },
    },

    {
      definition: {
        name: 'intercom_create_conversation',
        description: 'Create a new conversation on behalf of a user, lead, or contact.',
        inputSchema: {
          type: 'object',
          properties: {
            from: {
              type: 'object',
              description: 'Sender information',
              properties: {
                type: {
                  type: 'string',
                  enum: ['user', 'lead', 'contact'],
                  description: 'Sender type',
                },
                id: {
                  type: 'string',
                  description: 'Contact/user/lead ID (if type is contact)',
                },
                user_id: {
                  type: 'string',
                  description: 'External user ID',
                },
                email: {
                  type: 'string',
                  description: 'Email address',
                },
              },
              required: ['type'],
            },
            body: {
              type: 'string',
              description: 'Message body',
            },
          },
          required: ['from', 'body'],
        },
      },
      handler: async (args) => {
        const data = CreateConversationSchema.parse(args);
        return client.createConversation(data as any);
      },
    },

    {
      definition: {
        name: 'intercom_search_conversations',
        description: 'Search conversations using filters. Supports queries on state, assignee, contact, tags, etc.',
        inputSchema: {
          type: 'object',
          properties: {
            query: {
              type: 'object',
              description: 'Filter object',
              properties: {
                field: {
                  type: 'string',
                  description: 'Field to filter on (e.g., state, assignee_id, contact_ids)',
                },
                operator: {
                  type: 'string',
                  enum: ['=', '!=', 'IN', 'NIN', '>', '<', '>=', '<='],
                },
                value: {
                  description: 'Value to filter by',
                },
              },
            },
            pagination: {
              type: 'object',
              properties: {
                per_page: { type: 'number', maximum: 150 },
                starting_after: { type: 'string' },
              },
            },
            sort: {
              type: 'object',
              properties: {
                field: { type: 'string' },
                order: { type: 'string', enum: ['asc', 'desc'] },
              },
              required: ['field', 'order'],
            },
          },
        },
      },
      handler: async (args) => {
        const data = SearchConversationsSchema.parse(args);
        return client.searchConversations(data as any);
      },
    },

    {
      definition: {
        name: 'intercom_reply_conversation',
        description: 'Reply to a conversation with a comment (visible to user) or note (internal only).',
        inputSchema: {
          type: 'object',
          properties: {
            id: {
              type: 'string',
              description: 'Conversation ID',
            },
            message_type: {
              type: 'string',
              enum: ['comment', 'note'],
              description: 'Type of reply - comment (user sees) or note (internal)',
            },
            type: {
              type: 'string',
              enum: ['admin', 'user'],
              description: 'Who is replying',
            },
            admin_id: {
              type: 'string',
              description: 'Admin ID (required if type is admin)',
            },
            body: {
              type: 'string',
              description: 'Reply body text',
            },
            attachment_urls: {
              type: 'array',
              items: { type: 'string' },
              description: 'Array of attachment URLs',
            },
            created_at: {
              type: 'number',
              description: 'Unix timestamp (optional, defaults to now)',
            },
          },
          required: ['id', 'message_type', 'type', 'body'],
        },
      },
      handler: async (args) => {
        const { id, ...replyData } = ReplyConversationSchema.parse(args);
        return client.replyToConversation(id as any, replyData as any);
      },
    },

    {
      definition: {
        name: 'intercom_assign_conversation',
        description: 'Assign a conversation to an admin or team.',
        inputSchema: {
          type: 'object',
          properties: {
            id: {
              type: 'string',
              description: 'Conversation ID',
            },
            assignee_type: {
              type: 'string',
              enum: ['admin', 'team'],
              description: 'Type of assignee',
            },
            assignee_id: {
              type: 'string',
              description: 'Admin or Team ID',
            },
            admin_id: {
              type: 'string',
              description: 'Admin making the assignment (optional)',
            },
          },
          required: ['id', 'assignee_type', 'assignee_id'],
        },
      },
      handler: async (args) => {
        const { id, assignee_type, assignee_id, admin_id } = AssignConversationSchema.parse(args);
        return client.assignConversation(id as any, {
          type: assignee_type as any,
          id: assignee_id as any,
          admin_id: admin_id as any,
        });
      },
    },

    {
      definition: {
        name: 'intercom_close_conversation',
        description: 'Close a conversation.',
        inputSchema: {
          type: 'object',
          properties: {
            id: {
              type: 'string',
              description: 'Conversation ID',
            },
            admin_id: {
              type: 'string',
              description: 'Admin ID closing the conversation',
            },
          },
          required: ['id', 'admin_id'],
        },
      },
      handler: async (args) => {
        const { id, admin_id } = args as { id: string; admin_id: string };
        return client.closeConversation(id as any, admin_id as any);
      },
    },

    {
      definition: {
        name: 'intercom_open_conversation',
        description: 'Reopen a closed conversation.',
        inputSchema: {
          type: 'object',
          properties: {
            id: {
              type: 'string',
              description: 'Conversation ID',
            },
            admin_id: {
              type: 'string',
              description: 'Admin ID opening the conversation',
            },
          },
          required: ['id', 'admin_id'],
        },
      },
      handler: async (args) => {
        const { id, admin_id } = args as { id: string; admin_id: string };
        return client.openConversation(id as any, admin_id as any);
      },
    },

    {
      definition: {
        name: 'intercom_snooze_conversation',
        description: 'Snooze a conversation until a specific time.',
        inputSchema: {
          type: 'object',
          properties: {
            id: {
              type: 'string',
              description: 'Conversation ID',
            },
            snoozed_until: {
              type: 'number',
              description: 'Unix timestamp when conversation should be unsnoozed',
            },
          },
          required: ['id', 'snoozed_until'],
        },
      },
      handler: async (args) => {
        const { id, snoozed_until } = args as { id: string; snoozed_until: number };
        return client.snoozeConversation(id as any, snoozed_until);
      },
    },

    {
      definition: {
        name: 'intercom_tag_conversation',
        description: 'Add a tag to a conversation.',
        inputSchema: {
          type: 'object',
          properties: {
            id: {
              type: 'string',
              description: 'Conversation ID',
            },
            tag_id: {
              type: 'string',
              description: 'Tag ID to add',
            },
            admin_id: {
              type: 'string',
              description: 'Admin ID applying the tag',
            },
          },
          required: ['id', 'tag_id', 'admin_id'],
        },
      },
      handler: async (args) => {
        const { id, tag_id, admin_id } = TagConversationSchema.parse(args);
        return client.attachTagToConversation(id as any, tag_id as any, admin_id as any);
      },
    },

    {
      definition: {
        name: 'intercom_untag_conversation',
        description: 'Remove a tag from a conversation.',
        inputSchema: {
          type: 'object',
          properties: {
            id: {
              type: 'string',
              description: 'Conversation ID',
            },
            tag_id: {
              type: 'string',
              description: 'Tag ID to remove',
            },
            admin_id: {
              type: 'string',
              description: 'Admin ID removing the tag',
            },
          },
          required: ['id', 'tag_id', 'admin_id'],
        },
      },
      handler: async (args) => {
        const { id, tag_id, admin_id } = TagConversationSchema.parse(args);
        return client.detachTagFromConversation(id as any, tag_id as any, admin_id as any);
      },
    },
  ];
}
