import { z } from 'zod'
import { createIntegrationTool } from '../../../tool'
import type { Tool } from '../../../../types'
import { EmailSchema } from '../../../../../../../platform/utils/validation'

/**
 * Create Instantly send reply tool
 *
 * Sends a reply to an email thread maintaining proper threading.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that sends email replies via Instantly
 *
 * @example
 * const sendReply = createInstantlySendReplyTool('instantly-elevasis')
 */
export function createInstantlySendReplyTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'instantly_send_reply',
    description: `Send a reply to an email thread via Instantly.ai

USE CASES:
- Send a personalized reply to a prospect who responded to your outreach campaign
- Maintain email threading for organized conversations
- Schedule replies for future delivery

REQUIRED PARAMETERS:
- eaccount: Email account that will send the reply (must be connected to workspace)
- reply_to_uuid: UUID of the email you are replying to (from webhook payload)
- subject: Subject line of the reply (typically "Re: Original Subject")
- body: Email body (must provide either text or html)

OPTIONAL PARAMETERS:
- timestamp: ISO timestamp to schedule reply for future

EXAMPLE:
{
  "eaccount": "alex@elevasis.com",
  "reply_to_uuid": "123e4567-e89b-12d3-a456-426614174000",
  "subject": "Re: Automate your client acquisition",
  "body": {
    "text": "Thanks for your interest! Here's my calendar: https://calendly.com/..."
  }
}

OUTPUT:
{
  "success": true,
  "email_id": "email-abc123",
  "thread_id": "thread-xyz789",
  "sent_at": "2025-12-22T14:30:00Z"
}`,

    inputSchema: z.object({
      eaccount: z.string().describe('Email account that will send the reply (must be connected to workspace)'),
      reply_to_uuid: z.string().describe('UUID of the email you are replying to (from webhook payload)'),
      subject: z.string().describe('Subject line of the reply (typically "Re: Original Subject")'),
      body: z
        .object({
          text: z.string().optional().describe('Plain text email body'),
          html: z.string().optional().describe('HTML email body')
        })
        .refine((data) => data.text || data.html, {
          message: 'Must provide either text or html body'
        }),
      timestamp: z.string().optional().describe('ISO timestamp to schedule reply for future (optional)')
    }),

    outputSchema: z.object({
      success: z.boolean().describe('Whether reply was sent successfully'),
      email_id: z.string().describe('ID of the sent email'),
      thread_id: z.string().describe('Thread ID for conversation tracking'),
      sent_at: z.string().describe('Timestamp when email was sent')
    }),

    integration: 'instantly' as const,
    method: 'sendReply' as const,
    credentialName
  })
}

/**
 * Create Instantly remove from subsequence tool
 *
 * Removes a lead from a campaign sequence to stop further outreach.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that removes leads from campaigns
 *
 * @example
 * const removeFromCampaign = createInstantlyRemoveFromSubsequenceTool('instantly-elevasis')
 */
export function createInstantlyRemoveFromSubsequenceTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'instantly_remove_from_subsequence',
    description: `Remove a lead from an Instantly campaign subsequence

USE CASES:
- Stop a lead from receiving further emails in a campaign
- Use after positive reply, hard-no, or disqualification
- Prevent over-emailing engaged prospects

REQUIRED PARAMETERS:
- lead_email: Email address of the lead to remove
- campaign_id: Campaign ID to remove lead from

EXAMPLE:
{
  "lead_email": "prospect@agency.com",
  "campaign_id": "campaign-123"
}

OUTPUT:
{
  "success": true,
  "lead_email": "prospect@agency.com",
  "campaign_id": "campaign-123"
}`,

    inputSchema: z.object({
      lead_email: EmailSchema.describe('Email address of the lead to remove'),
      campaign_id: z.string().describe('Campaign ID to remove lead from')
    }),

    outputSchema: z.object({
      success: z.boolean().describe('Whether removal was successful'),
      lead_email: z.string().describe('Email of the removed lead'),
      campaign_id: z.string().describe('Campaign ID lead was removed from')
    }),

    integration: 'instantly' as const,
    method: 'removeFromSubsequence' as const,
    credentialName
  })
}

/**
 * Create Instantly get emails tool
 *
 * Fetches email data from Instantly workspace with optional filtering and pagination.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that retrieves email data
 */
export function createInstantlyGetEmailsTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'instantly_get_emails',
    description: `Get emails from Instantly workspace

USE CASES:
- Fetch a specific email by ID for reply processing
- Retrieve full email threads by thread ID
- Filter emails by campaign, lead, or type
- List recent emails with cursor pagination

OPTIONAL PARAMETERS:
- email_id: Specific email ID to fetch (returns single email)
- search: Email address OR "thread:{thread_id}" for thread retrieval
- campaign_id: Filter by campaign UUID
- lead: Filter by lead email address
- email_type: Filter by type (received, sent, manual)
- eaccount: Filter by sending account (comma-separated)
- sort_order: Sort by creation date (asc, desc; default: desc)
- preview_only: Return preview only (lighter response)
- is_unread: Filter by unread status
- limit: Items per page (1-100)
- starting_after: Cursor for pagination (from next_starting_after in previous response)

EXAMPLE (Single Email):
{
  "email_id": "email-abc123"
}

EXAMPLE (Thread Retrieval):
{
  "search": "thread:019a449c-f57a-73b2-91b5-75537ca85008",
  "sort_order": "asc",
  "limit": 50
}

EXAMPLE (Lead Emails in Campaign):
{
  "lead": "jondoe@example.com",
  "campaign_id": "019a449c-f57a-73b2-91b5-754f1fca9f44",
  "sort_order": "asc"
}

OUTPUT:
{
  "emails": [...email data...],
  "total_count": 3,
  "next_starting_after": "cursor-token-or-undefined"
}`,

    inputSchema: z.object({
      email_id: z.string().optional().describe('Specific email ID to fetch'),
      search: z
        .string()
        .optional()
        .describe('Search query: email address or "thread:{thread_id}" for thread retrieval'),
      campaign_id: z.string().optional().describe('Filter by campaign UUID'),
      lead: z.string().optional().describe('Filter by lead email address'),
      email_type: z.enum(['received', 'sent', 'manual']).optional().describe('Filter by email type'),
      eaccount: z.string().optional().describe('Filter by sending account (comma-separated)'),
      sort_order: z.enum(['asc', 'desc']).optional().describe('Sort order by creation date (default: desc)'),
      preview_only: z.boolean().optional().describe('Return preview only (lighter response)'),
      is_unread: z.boolean().optional().describe('Filter by unread status'),
      limit: z.number().min(1).max(100).optional().describe('Items per page (1-100)'),
      starting_after: z.string().optional().describe('Cursor for pagination (from next_starting_after)')
    }),

    outputSchema: z.object({
      emails: z.array(z.unknown()).describe('Array of email data'),
      total_count: z.number().describe('Count of emails returned'),
      next_starting_after: z.string().optional().describe('Cursor for next page (undefined = no more)')
    }),

    integration: 'instantly' as const,
    method: 'getEmails' as const,
    credentialName
  })
}

/**
 * Create Instantly update interest status tool
 *
 * Updates the interest status of a lead, which can stop email sequences,
 * mark leads as interested, or reset to default status.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that updates lead interest status
 *
 * @example
 * const updateStatus = createInstantlyUpdateInterestStatusTool('instantly-elevasis')
 */
export function createInstantlyUpdateInterestStatusTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'instantly_update_interest_status',
    description: `Update interest status of a lead in Instantly

USE CASES:
- Stop email sequence for leads who reply with "unsubscribe" or "not interested" (set interest_value: -1)
- Mark engaged leads as interested for prioritization (set interest_value: 1)
- Reset lead status back to default (set interest_value: 0)
- Comply with opt-out requests to protect sender reputation

INTEREST VALUES:
- 1: Interested - Marks lead as interested
- 0: Lead (default) - Resets to default status
- -1: Not Interested - STOPS sequence (no more emails sent)

REQUIRED PARAMETERS:
- lead_email: Email address of the lead
- interest_value: Status value (1, 0, or -1)

OPTIONAL PARAMETERS:
- campaign_id: Limit status update to specific campaign (UUID)
- disable_auto_interest: Disable AI auto-tagging for this lead

EXAMPLE (Stop Sequence):
{
  "lead_email": "prospect@agency.com",
  "interest_value": -1
}

EXAMPLE (Mark Interested in Specific Campaign):
{
  "lead_email": "prospect@agency.com",
  "interest_value": 1,
  "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
}

OUTPUT:
{
  "success": true,
  "lead_email": "prospect@agency.com"
}`,

    inputSchema: z.object({
      lead_email: EmailSchema.describe('Email address of the lead'),
      interest_value: z
        .number()
        .int()
        .min(-1)
        .max(1)
        .describe('Interest status: 1 (interested), 0 (default), -1 (not interested - stops sequence)'),
      campaign_id: z.string().optional().describe('Campaign ID to limit status update to (UUID)'),
      disable_auto_interest: z.boolean().optional().describe('Disable AI auto-tagging for this lead')
    }),

    outputSchema: z.object({
      success: z.boolean().describe('Whether status update was successful'),
      lead_email: z.string().describe('Email of the updated lead')
    }),

    integration: 'instantly' as const,
    method: 'updateInterestStatus' as const,
    credentialName
  })
}

/**
 * Create Instantly add to campaign tool
 *
 * Adds leads to an Instantly campaign to begin the email sequence.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that adds leads to a campaign
 *
 * @example
 * const addToCampaign = createInstantlyAddToCampaignTool('instantly-elevasis')
 */
export function createInstantlyAddToCampaignTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'instantly_add_to_campaign',
    description: `Add leads to an Instantly campaign

USE CASES:
- Add interested leads to a follow-up campaign after initial outreach
- Start a drip sequence for leads who requested more information
- Enroll new leads into automated nurture campaigns

REQUIRED PARAMETERS:
- campaign_id: UUID of the Instantly campaign to add leads to
- leads: Array of lead objects (at least one required)

LEAD OBJECT FIELDS:
- email: (required) Email address of the lead
- first_name: (optional) First name for personalization
- last_name: (optional) Last name for personalization
- company_name: (optional) Company name for personalization

IMPORTANT: When leads are added, they begin receiving the campaign sequence immediately.
"Day 0" starts at the moment of addition.

EXAMPLE:
{
  "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
  "leads": [
    {
      "email": "prospect@agency.com",
      "first_name": "John",
      "last_name": "Smith",
      "company_name": "Acme Agency"
    }
  ]
}

OUTPUT:
{
  "success": true,
  "added_count": 1,
  "errors": null
}`,

    inputSchema: z.object({
      campaign_id: z.string().describe('UUID of the Instantly campaign to add leads to'),
      leads: z
        .array(
          z.object({
            email: EmailSchema.describe('Email address of the lead'),
            first_name: z.string().optional().describe('First name for personalization'),
            last_name: z.string().optional().describe('Last name for personalization'),
            company_name: z.string().optional().describe('Company name for personalization')
          })
        )
        .min(1)
        .describe('Array of leads to add (at least one required)')
    }),

    outputSchema: z.object({
      success: z.boolean().describe('Whether leads were added successfully'),
      added_count: z.number().describe('Number of leads successfully added'),
      errors: z.array(z.string()).optional().describe('Array of error messages if any failures occurred')
    }),

    integration: 'instantly' as const,
    method: 'addToCampaign' as const,
    credentialName
  })
}

/**
 * Create Instantly list campaigns tool
 *
 * Lists all campaigns in the workspace with optional filtering and pagination.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that lists Instantly campaigns
 *
 * @example
 * const listCampaigns = createInstantlyListCampaignsTool('instantly-elevasis')
 */
export function createInstantlyListCampaignsTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'instantly_list_campaigns',
    description: `List all campaigns in the Instantly workspace

USE CASES:
- Discover available campaigns before adding leads or fetching analytics
- Filter campaigns by status to find active or paused campaigns
- Search campaigns by name to locate a specific campaign ID
- Paginate through large campaign lists using cursor-based pagination

OPTIONAL PARAMETERS:
- limit: Number of campaigns to return per page (default: 10)
- starting_after: Cursor from previous response for pagination
- status: Filter by campaign status (e.g. "active", "paused", "completed")
- search: Search term to filter campaigns by name

EXAMPLE (List Active Campaigns):
{
  "status": "active",
  "limit": 20
}

EXAMPLE (Search by Name):
{
  "search": "cold outreach Q1"
}

OUTPUT:
{
  "campaigns": [
    {
      "id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
      "name": "Cold Outreach Q1",
      "status": "active",
      "created_at": "2025-01-15T09:00:00Z"
    }
  ],
  "next_starting_after": "cursor-token"
}`,

    inputSchema: z.object({
      limit: z.number().min(1).max(100).optional().describe('Number of campaigns per page (default: 10)'),
      starting_after: z
        .string()
        .optional()
        .describe('Cursor for pagination (from next_starting_after in previous response)'),
      status: z.string().optional().describe('Filter by campaign status (e.g. "active", "paused", "completed")'),
      search: z.string().optional().describe('Search term to filter campaigns by name')
    }),

    outputSchema: z.object({
      campaigns: z
        .array(
          z.object({
            id: z.string().describe('Campaign UUID'),
            name: z.string().describe('Campaign name'),
            status: z.string().describe('Campaign status'),
            created_at: z.string().describe('Campaign creation timestamp')
          })
        )
        .describe('Array of campaigns'),
      next_starting_after: z.string().optional().describe('Cursor for next page (undefined = no more pages)')
    }),

    integration: 'instantly' as const,
    method: 'listCampaigns' as const,
    credentialName
  })
}

/**
 * Create Instantly get campaign tool
 *
 * Fetches full details for a single campaign including sequences and configuration.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that retrieves a single Instantly campaign
 *
 * @example
 * const getCampaign = createInstantlyGetCampaignTool('instantly-elevasis')
 */
export function createInstantlyGetCampaignTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'instantly_get_campaign',
    description: `Get full details of a specific Instantly campaign

USE CASES:
- Inspect campaign sequences and step configurations before modifying
- Verify campaign status before activating or pausing
- Retrieve sending settings such as daily limits and reply handling
- Confirm the campaign name and metadata before referencing in reports

REQUIRED PARAMETERS:
- campaign_id: UUID of the campaign to retrieve

EXAMPLE:
{
  "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
}

OUTPUT:
{
  "id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
  "name": "Cold Outreach Q1",
  "status": "active",
  "sequences": [...],
  "created_at": "2025-01-15T09:00:00Z"
}`,

    inputSchema: z.object({
      campaign_id: z.string().describe('UUID of the campaign to retrieve')
    }),

    outputSchema: z.object({
      id: z.string().describe('Campaign UUID'),
      name: z.string().describe('Campaign name'),
      status: z.string().describe('Campaign status'),
      sequences: z.array(z.unknown()).describe('Campaign sequence steps'),
      created_at: z.string().describe('Campaign creation timestamp')
    }),

    integration: 'instantly' as const,
    method: 'getCampaign' as const,
    credentialName
  })
}

/**
 * Create Instantly update campaign tool
 *
 * Partially updates a campaign's fields such as name, sequences, or sending limits.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that updates an Instantly campaign
 *
 * @example
 * const updateCampaign = createInstantlyUpdateCampaignTool('instantly-elevasis')
 */
export function createInstantlyUpdateCampaignTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'instantly_update_campaign',
    description: `Update fields on an existing Instantly campaign

USE CASES:
- Rename a campaign to reflect updated targeting or messaging
- Adjust the daily sending limit to control volume
- Replace or edit campaign sequences and email steps
- Toggle stop-on-reply to pause the sequence when a lead responds

REQUIRED PARAMETERS:
- campaign_id: UUID of the campaign to update

OPTIONAL PARAMETERS (at least one must be provided):
- name: New campaign name
- sequences: Full replacement of campaign sequences (array of step objects)
- daily_limit: Maximum emails to send per day
- stop_on_reply: Whether to stop sending when a lead replies (true/false)

EXAMPLE (Rename and Adjust Limit):
{
  "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
  "name": "Cold Outreach Q2",
  "daily_limit": 50
}

OUTPUT:
{
  "success": true,
  "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
}`,

    inputSchema: z.object({
      campaign_id: z.string().describe('UUID of the campaign to update'),
      name: z.string().optional().describe('New campaign name'),
      sequences: z.array(z.unknown()).optional().describe('Replacement campaign sequences (array of step objects)'),
      daily_limit: z.number().int().min(1).optional().describe('Maximum emails to send per day'),
      stop_on_reply: z.boolean().optional().describe('Whether to stop the sequence when a lead replies')
    }),

    outputSchema: z.object({
      success: z.boolean().describe('Whether the update was successful'),
      campaign_id: z.string().describe('UUID of the updated campaign')
    }),

    integration: 'instantly' as const,
    method: 'updateCampaign' as const,
    credentialName
  })
}

/**
 * Create Instantly pause campaign tool
 *
 * Pauses an active campaign to stop email sends until reactivated.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that pauses an Instantly campaign
 *
 * @example
 * const pauseCampaign = createInstantlyPauseCampaignTool('instantly-elevasis')
 */
export function createInstantlyPauseCampaignTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'instantly_pause_campaign',
    description: `Pause an active Instantly campaign

USE CASES:
- Temporarily halt outreach while reviewing campaign performance
- Pause before making sequence edits to avoid sending stale content
- Stop sends during public holidays or blackout periods
- Hold sends when a domain reputation issue is detected

REQUIRED PARAMETERS:
- campaign_id: UUID of the campaign to pause

EXAMPLE:
{
  "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
}

OUTPUT:
{
  "success": true,
  "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
}`,

    inputSchema: z.object({
      campaign_id: z.string().describe('UUID of the campaign to pause')
    }),

    outputSchema: z.object({
      success: z.boolean().describe('Whether the campaign was paused successfully'),
      campaign_id: z.string().describe('UUID of the paused campaign')
    }),

    integration: 'instantly' as const,
    method: 'pauseCampaign' as const,
    credentialName
  })
}

/**
 * Create Instantly delete campaign tool
 *
 * Permanently deletes a campaign and all associated data.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that deletes an Instantly campaign
 *
 * @example
 * const deleteCampaign = createInstantlyDeleteCampaignTool('instantly-elevasis')
 */
export function createInstantlyDeleteCampaignTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'instantly_delete_campaign',
    description: `Permanently delete an Instantly campaign

USE CASES:
- Clean up test or draft campaigns after diagnostic runs
- Remove campaigns that are no longer needed
- Delete accidentally created campaigns

REQUIRED PARAMETERS:
- campaign_id: UUID of the campaign to delete

EXAMPLE:
{
  "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
}

OUTPUT:
{
  "success": true,
  "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
}`,

    inputSchema: z.object({
      campaign_id: z.string().describe('UUID of the campaign to delete')
    }),

    outputSchema: z.object({
      success: z.boolean().describe('Whether the campaign was deleted successfully'),
      campaign_id: z.string().describe('UUID of the deleted campaign')
    }),

    integration: 'instantly' as const,
    method: 'deleteCampaign' as const,
    credentialName
  })
}

/**
 * Create Instantly activate campaign tool
 *
 * Activates or resumes a paused or draft campaign to begin sending.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that activates an Instantly campaign
 *
 * @example
 * const activateCampaign = createInstantlyActivateCampaignTool('instantly-elevasis')
 */
export function createInstantlyActivateCampaignTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'instantly_activate_campaign',
    description: `Activate or resume an Instantly campaign

USE CASES:
- Launch a newly created campaign to begin sending to enrolled leads
- Resume a paused campaign after completing edits or reviews
- Re-activate a campaign after resolving domain reputation issues
- Start scheduled outreach at the beginning of a new period

REQUIRED PARAMETERS:
- campaign_id: UUID of the campaign to activate

EXAMPLE:
{
  "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
}

OUTPUT:
{
  "success": true,
  "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
}`,

    inputSchema: z.object({
      campaign_id: z.string().describe('UUID of the campaign to activate')
    }),

    outputSchema: z.object({
      success: z.boolean().describe('Whether the campaign was activated successfully'),
      campaign_id: z.string().describe('UUID of the activated campaign')
    }),

    integration: 'instantly' as const,
    method: 'activateCampaign' as const,
    credentialName
  })
}

/**
 * Create Instantly get campaign analytics tool
 *
 * Retrieves aggregate engagement statistics for a campaign.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that fetches campaign-level analytics
 *
 * @example
 * const getAnalytics = createInstantlyGetCampaignAnalyticsTool('instantly-elevasis')
 */
export function createInstantlyGetCampaignAnalyticsTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'instantly_get_campaign_analytics',
    description: `Get aggregate analytics for an Instantly campaign

USE CASES:
- Review overall campaign performance including open rate, reply rate, and bounce rate
- Compare send volume against replies to evaluate outreach effectiveness
- Monitor unsubscribes to maintain sender reputation
- Scope analytics to a date range for period-specific reporting

REQUIRED PARAMETERS:
- campaign_id: UUID of the campaign

OPTIONAL PARAMETERS:
- start_date: ISO date string to filter analytics from (e.g. "2025-01-01")
- end_date: ISO date string to filter analytics to (e.g. "2025-03-31")

EXAMPLE:
{
  "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
  "start_date": "2025-01-01",
  "end_date": "2025-03-31"
}

OUTPUT:
{
  "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
  "sent": 450,
  "opened": 180,
  "unique_opened": 160,
  "replied": 35,
  "unique_replied": 30,
  "bounced": 5,
  "unsubscribed": 2
}`,

    inputSchema: z.object({
      campaign_id: z.string().describe('UUID of the campaign to fetch analytics for'),
      start_date: z.string().optional().describe('Start date for analytics range (ISO date string, e.g. "2025-01-01")'),
      end_date: z.string().optional().describe('End date for analytics range (ISO date string, e.g. "2025-03-31")')
    }),

    outputSchema: z.object({
      campaign_id: z.string().describe('Campaign UUID'),
      sent: z.number().describe('Total emails sent'),
      opened: z.number().describe('Total open events'),
      unique_opened: z.number().describe('Unique leads who opened'),
      replied: z.number().describe('Total reply events'),
      unique_replied: z.number().describe('Unique leads who replied'),
      bounced: z.number().describe('Total bounced emails'),
      unsubscribed: z.number().describe('Total unsubscribes')
    }),

    integration: 'instantly' as const,
    method: 'getCampaignAnalytics' as const,
    credentialName
  })
}

/**
 * Create Instantly get step analytics tool
 *
 * Retrieves per-step and per-variant analytics for a campaign sequence.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that fetches step-level analytics
 *
 * @example
 * const getStepAnalytics = createInstantlyGetStepAnalyticsTool('instantly-elevasis')
 */
export function createInstantlyGetStepAnalyticsTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'instantly_get_step_analytics',
    description: `Get per-step and per-variant analytics for an Instantly campaign

USE CASES:
- Identify which sequence step has the highest reply rate
- Compare A/B subject line variants to determine the winning version
- Diagnose a drop-off point where prospects stop engaging
- Optimize multi-step sequences based on step-level performance data

REQUIRED PARAMETERS:
- campaign_id: UUID of the campaign

EXAMPLE:
{
  "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43"
}

OUTPUT:
{
  "steps": [
    {
      "step": "1",
      "variant": "A",
      "sent": 200,
      "opened": 90,
      "unique_opened": 80,
      "replies": 20,
      "unique_replies": 18
    },
    {
      "step": "2",
      "variant": "A",
      "sent": 160,
      "opened": 55,
      "unique_opened": 50,
      "replies": 10,
      "unique_replies": 9
    }
  ]
}`,

    inputSchema: z.object({
      campaign_id: z.string().describe('UUID of the campaign to fetch step analytics for')
    }),

    outputSchema: z.object({
      steps: z
        .array(
          z.object({
            step: z.string().describe('Step number in the sequence'),
            variant: z.string().describe('Variant label (e.g. "A", "B")'),
            sent: z.number().describe('Emails sent for this step/variant'),
            opened: z.number().describe('Total open events'),
            unique_opened: z.number().describe('Unique leads who opened'),
            replies: z.number().describe('Total reply events'),
            unique_replies: z.number().describe('Unique leads who replied')
          })
        )
        .describe('Per-step, per-variant analytics entries')
    }),

    integration: 'instantly' as const,
    method: 'getStepAnalytics' as const,
    credentialName
  })
}

/**
 * Create Instantly bulk add leads tool
 *
 * Adds up to 1000 leads to a campaign in a single request.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that bulk-uploads leads to an Instantly campaign
 *
 * @example
 * const bulkAddLeads = createInstantlyBulkAddLeadsTool('instantly-elevasis')
 */
export function createInstantlyBulkAddLeadsTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'instantly_bulk_add_leads',
    description: `Bulk upload up to 1000 leads to an Instantly campaign

USE CASES:
- Import a large list of qualified prospects into a campaign at once
- Enroll leads exported from a CRM or enrichment tool into outreach
- Upload leads with custom variables for deep personalization
- Add leads with website and company data for context-aware sequences

REQUIRED PARAMETERS:
- campaign_id: UUID of the campaign to add leads to
- leads: Array of lead objects (1–1000 leads)

LEAD OBJECT FIELDS:
- email: (required) Email address of the lead
- first_name: (optional) First name for personalization
- last_name: (optional) Last name for personalization
- company_name: (optional) Company name for personalization
- website: (optional) Company website URL
- custom_variables: (optional) Key-value map of custom merge fields

EXAMPLE:
{
  "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
  "leads": [
    {
      "email": "ceo@agency.com",
      "first_name": "Sarah",
      "last_name": "Chen",
      "company_name": "Growth Agency",
      "website": "https://growthagency.com",
      "custom_variables": { "pain_point": "manual lead gen" }
    }
  ]
}

OUTPUT:
{
  "success": true,
  "added_count": 1,
  "failed_count": 0
}`,

    inputSchema: z.object({
      campaign_id: z.string().describe('UUID of the campaign to add leads to'),
      leads: z
        .array(
          z.object({
            email: EmailSchema.describe('Email address of the lead'),
            first_name: z.string().optional().describe('First name for personalization'),
            last_name: z.string().optional().describe('Last name for personalization'),
            company_name: z.string().optional().describe('Company name for personalization'),
            website: z.string().optional().describe('Company website URL'),
            custom_variables: z
              .record(z.string(), z.string())
              .optional()
              .describe('Key-value map of custom merge field values')
          })
        )
        .min(1)
        .max(1000)
        .describe('Array of leads to upload (1–1000)')
    }),

    outputSchema: z.object({
      success: z.boolean().describe('True if all leads were added without errors'),
      added_count: z.number().describe('Number of leads successfully added'),
      failed_count: z.number().describe('Number of leads that failed to add'),
      errors: z
        .array(
          z.object({
            email: z.string().describe('Email of the lead that failed'),
            error: z.string().describe('Error message for this lead')
          })
        )
        .optional()
        .describe('Per-lead error details when failures occurred')
    }),

    integration: 'instantly' as const,
    method: 'bulkAddLeads' as const,
    credentialName
  })
}

/**
 * Create Instantly get account health tool
 *
 * Lists email sending accounts with warmup status and health scores.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that retrieves account health data
 *
 * @example
 * const getAccountHealth = createInstantlyGetAccountHealthTool('instantly-elevasis')
 */
export function createInstantlyGetAccountHealthTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'instantly_get_account_health',
    description: `List email accounts with health status and warmup information

USE CASES:
- Audit all connected sending accounts before launching a campaign
- Identify accounts with low health scores that may cause deliverability issues
- Verify warmup status to ensure accounts are ready for full sending volume
- Monitor account portfolio health as part of regular sender hygiene checks

OPTIONAL PARAMETERS:
- limit: Number of accounts to return per page
- starting_after: Cursor from previous response for pagination

EXAMPLE:
{
  "limit": 20
}

OUTPUT:
{
  "accounts": [
    {
      "id": "acct-abc123",
      "email": "alex@elevasis.com",
      "status": "active",
      "warmup_enabled": true,
      "health_score": 92
    }
  ],
  "next_starting_after": "cursor-token"
}`,

    inputSchema: z.object({
      limit: z.number().min(1).max(100).optional().describe('Number of accounts per page'),
      starting_after: z
        .string()
        .optional()
        .describe('Cursor for pagination (from next_starting_after in previous response)')
    }),

    outputSchema: z.object({
      accounts: z
        .array(
          z.object({
            id: z.string().describe('Account ID'),
            email: z.string().describe('Sending email address'),
            status: z.string().describe('Account status'),
            warmup_enabled: z.boolean().describe('Whether warmup is active for this account'),
            health_score: z.number().optional().describe('Health score (0–100)')
          })
        )
        .describe('Array of sending accounts with health data'),
      next_starting_after: z.string().optional().describe('Cursor for next page (undefined = no more pages)')
    }),

    integration: 'instantly' as const,
    method: 'getAccountHealth' as const,
    credentialName
  })
}

/**
 * Create Instantly create campaign tool
 *
 * Creates a new campaign in Instantly with optional sequences and sending configuration.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that creates a new Instantly campaign
 *
 * @example
 * const createCampaign = createInstantlyCreateCampaignTool('instantly-elevasis')
 */
export function createInstantlyCreateCampaignTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'instantly_create_campaign',
    description: `Create a new Instantly campaign

USE CASES:
- Set up a new cold outreach campaign with custom sequences
- Create a campaign with predefined email steps and A/B variants
- Configure sending limits and reply handling at creation time
- Prepare a campaign shell to be populated with leads and activated later

REQUIRED PARAMETERS:
- name: Display name of the new campaign

OPTIONAL PARAMETERS:
- sequences: Array of sequence objects with email steps and optional A/B variants
- email_list: Array of sending account emails to use for the campaign
- daily_limit: Maximum emails to send per day
- stop_on_reply: Whether to stop the sequence when a lead replies
- stop_on_auto_reply: Whether to stop on auto-replies
- track_opens: Whether to track email opens
- track_clicks: Whether to track link clicks
- text_only: Whether to send text-only emails (no HTML)

EXAMPLE (Simple Campaign):
{
  "name": "Cold Outreach Q2 2025",
  "daily_limit": 50,
  "stop_on_reply": true
}

EXAMPLE (Campaign with Sequence):
{
  "name": "Agency Outreach",
  "sequences": [
    {
      "steps": [
        {
          "subject": "Quick question about {{company_name}}",
          "body": "Hi {{first_name}}, I noticed..."
        },
        {
          "subject": "Following up",
          "body": "Hi {{first_name}}, just wanted to circle back..."
        }
      ]
    }
  ],
  "daily_limit": 30,
  "stop_on_reply": true
}

OUTPUT:
{
  "success": true,
  "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
  "name": "Cold Outreach Q2 2025"
}`,

    inputSchema: z.object({
      name: z.string().describe('Display name of the new campaign'),
      sequences: z
        .array(
          z.object({
            steps: z.array(
              z.object({
                subject: z.string().describe('Email subject line for this step'),
                body: z.string().describe('Email body for this step'),
                variants: z
                  .array(
                    z.object({
                      subject: z.string().describe('A/B variant subject line'),
                      body: z.string().describe('A/B variant body')
                    })
                  )
                  .optional()
                  .describe('A/B test variants for this step')
              })
            )
          })
        )
        .optional()
        .describe('Campaign sequences with email steps'),
      email_list: z.array(z.string()).optional().describe('Sending account emails to use for the campaign'),
      daily_limit: z.number().int().min(1).optional().describe('Maximum emails to send per day'),
      stop_on_reply: z.boolean().optional().describe('Whether to stop the sequence when a lead replies'),
      stop_on_auto_reply: z.boolean().optional().describe('Whether to stop the sequence on auto-replies'),
      track_opens: z.boolean().optional().describe('Whether to track email opens'),
      track_clicks: z.boolean().optional().describe('Whether to track link clicks'),
      text_only: z.boolean().optional().describe('Whether to send text-only emails (no HTML)')
    }),

    outputSchema: z.object({
      success: z.boolean().describe('Whether the campaign was created successfully'),
      campaign_id: z.string().describe('UUID of the newly created campaign'),
      name: z.string().describe('Name of the created campaign')
    }),

    integration: 'instantly' as const,
    method: 'createCampaign' as const,
    credentialName
  })
}

/**
 * Create Instantly create inbox test tool
 *
 * Initiates an inbox placement test to diagnose deliverability for a sending account.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that creates an Instantly inbox placement test
 *
 * @example
 * const createInboxTest = createInstantlyCreateInboxTestTool('instantly-elevasis')
 */
export function createInstantlyCreateInboxTestTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'instantly_create_inbox_test',
    description: `Create an inbox placement test for an Instantly sending account

USE CASES:
- Verify deliverability before launching a high-volume campaign
- Diagnose spam filtering issues on a specific sending account
- Test whether custom subject lines land in inbox or spam
- Monitor placement across Gmail, Outlook, and other major providers

REQUIRED PARAMETERS:
- email_account: The sending account to test (must be connected to workspace)

OPTIONAL PARAMETERS:
- subject: Custom subject line to use in the test email
- body: Custom body text to use in the test email

EXAMPLE:
{
  "email_account": "alex@elevasis.com",
  "subject": "Quick question about your agency",
  "body": "Hi, I wanted to reach out about..."
}

OUTPUT:
{
  "success": true,
  "test_id": "test-abc123",
  "status": "pending"
}`,

    inputSchema: z.object({
      email_account: z.string().describe('Sending account email address to test (must be connected to workspace)'),
      subject: z.string().optional().describe('Custom subject line for the test email'),
      body: z.string().optional().describe('Custom body text for the test email')
    }),

    outputSchema: z.object({
      success: z.boolean().describe('Whether the test was created successfully'),
      test_id: z.string().describe('Unique ID of the inbox placement test'),
      status: z.string().describe('Initial test status (e.g. "pending")')
    }),

    integration: 'instantly' as const,
    method: 'createInboxTest' as const,
    credentialName
  })
}

/**
 * Create Instantly get daily campaign analytics tool
 *
 * Retrieves day-by-day engagement breakdown for campaigns.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that fetches daily campaign analytics
 *
 * @example
 * const getDailyAnalytics = createInstantlyGetDailyCampaignAnalyticsTool('instantly-elevasis')
 */
export function createInstantlyGetDailyCampaignAnalyticsTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'instantly_get_daily_campaign_analytics',
    description: `Get day-by-day analytics breakdown for Instantly campaigns

USE CASES:
- Analyze send and open trends over a date range to identify patterns
- Spot peak engagement days to optimize future send scheduling
- Compare daily click and reply volumes across a campaign period
- Get cross-campaign aggregate metrics when no campaign_id is specified

OPTIONAL PARAMETERS:
- campaign_id: Filter analytics to a specific campaign UUID (omit for all campaigns)
- start_date: Start of date range (ISO date, e.g. "2025-01-01")
- end_date: End of date range (ISO date, e.g. "2025-03-31")

EXAMPLE (Single Campaign):
{
  "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
  "start_date": "2025-01-01",
  "end_date": "2025-01-31"
}

EXAMPLE (All Campaigns):
{
  "start_date": "2025-01-01",
  "end_date": "2025-01-31"
}

OUTPUT:
{
  "data": [
    {
      "date": "2025-01-15",
      "sent": 120,
      "opened": 48,
      "unique_opened": 42,
      "replied": 8,
      "unique_replied": 7,
      "bounced": 1,
      "clicks": 12,
      "unique_clicks": 10
    }
  ]
}`,

    inputSchema: z.object({
      campaign_id: z.string().optional().describe('Campaign UUID to filter analytics (omit to get all campaigns)'),
      start_date: z.string().optional().describe('Start of date range (ISO date, e.g. "2025-01-01")'),
      end_date: z.string().optional().describe('End of date range (ISO date, e.g. "2025-03-31")')
    }),

    outputSchema: z.object({
      data: z
        .array(
          z.object({
            date: z.string().describe('Date (YYYY-MM-DD)'),
            sent: z.number().describe('Emails sent on this date'),
            opened: z.number().describe('Total open events'),
            unique_opened: z.number().describe('Unique leads who opened'),
            replied: z.number().describe('Total reply events'),
            unique_replied: z.number().describe('Unique leads who replied'),
            bounced: z.number().describe('Emails bounced'),
            clicks: z.number().describe('Total link click events'),
            unique_clicks: z.number().describe('Unique leads who clicked')
          })
        )
        .describe('Array of daily analytics entries')
    }),

    integration: 'instantly' as const,
    method: 'getDailyCampaignAnalytics' as const,
    credentialName
  })
}

/**
 * Create Instantly list leads tool
 *
 * Lists leads with optional filtering by campaign or email and cursor pagination.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that lists Instantly leads
 *
 * @example
 * const listLeads = createInstantlyListLeadsTool('instantly-elevasis')
 */
export function createInstantlyListLeadsTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'instantly_list_leads',
    description: `List leads in Instantly with optional filtering and pagination

USE CASES:
- Retrieve all leads enrolled in a specific campaign for auditing
- Look up a specific lead by email address to check their status
- Paginate through a large lead list using cursor-based pagination
- Review lead metadata including status, timestamps, and campaign assignment

OPTIONAL PARAMETERS:
- campaign_id: Filter leads by campaign UUID
- email: Filter by specific lead email address
- limit: Number of leads per page
- starting_after: Cursor from previous response for pagination

NOTE: This uses a POST endpoint per Instantly API design (complex filter arguments).

EXAMPLE (Campaign Leads):
{
  "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
  "limit": 50
}

EXAMPLE (Single Lead Lookup):
{
  "email": "prospect@agency.com"
}

OUTPUT:
{
  "items": [
    {
      "id": "lead-abc123",
      "email": "prospect@agency.com",
      "first_name": "John",
      "last_name": "Smith",
      "company_name": "Acme Agency",
      "status": "active",
      "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
      "timestamp_created": "2025-01-15T09:00:00Z"
    }
  ],
  "next_starting_after": "cursor-token"
}`,

    inputSchema: z.object({
      campaign_id: z.string().optional().describe('Filter leads by campaign UUID'),
      email: z.string().optional().describe('Filter by specific lead email address'),
      limit: z.number().min(1).max(100).optional().describe('Number of leads per page'),
      starting_after: z
        .string()
        .optional()
        .describe('Cursor for pagination (from next_starting_after in previous response)')
    }),

    outputSchema: z.object({
      items: z
        .array(
          z.object({
            id: z.string().describe('Lead ID'),
            email: z.string().describe('Lead email address'),
            first_name: z.string().optional().describe('Lead first name'),
            last_name: z.string().optional().describe('Lead last name'),
            company_name: z.string().optional().describe('Lead company name'),
            status: z.string().describe('Lead status in campaign'),
            campaign_id: z.string().optional().describe('Campaign this lead belongs to'),
            timestamp_created: z.string().optional().describe('Lead creation timestamp')
          })
        )
        .describe('Array of leads'),
      next_starting_after: z.string().optional().describe('Cursor for next page (undefined = no more pages)')
    }),

    integration: 'instantly' as const,
    method: 'listLeads' as const,
    credentialName
  })
}

/**
 * Create Instantly bulk delete leads tool
 *
 * Deletes leads in bulk by IDs, campaign, or list with an optional limit.
 *
 * @param credentialName - Name of credential in credentials table
 * @returns Tool that bulk-deletes Instantly leads
 *
 * @example
 * const bulkDeleteLeads = createInstantlyBulkDeleteLeadsTool('instantly-elevasis')
 */
export function createInstantlyBulkDeleteLeadsTool(credentialName: string): Tool {
  return createIntegrationTool({
    name: 'instantly_bulk_delete_leads',
    description: `Bulk delete leads from Instantly by IDs, campaign, or list

USE CASES:
- Remove a batch of disqualified leads from a campaign at once
- Clean up leads from a completed campaign before archiving
- Delete leads from a specific list to maintain database hygiene
- Remove a set of specific leads by their IDs after a data audit

OPTIONAL PARAMETERS (at least one filter recommended):
- ids: Array of specific lead IDs to delete
- campaign_id: Delete all leads from this campaign
- list_id: Delete all leads from this list
- limit: Maximum number of leads to delete in this operation (1-10000)

EXAMPLE (Delete by IDs):
{
  "ids": ["lead-abc123", "lead-def456"]
}

EXAMPLE (Delete from Campaign):
{
  "campaign_id": "019bb2e9-5d96-7f1d-9bc1-c0ef73001b43",
  "limit": 100
}

OUTPUT:
{
  "deleted_count": 42
}`,

    inputSchema: z.object({
      ids: z.array(z.string()).optional().describe('Specific lead IDs to delete'),
      campaign_id: z.string().optional().describe('Delete leads from this campaign'),
      list_id: z.string().optional().describe('Delete leads from this list'),
      limit: z.number().int().min(1).optional().describe('Maximum number of leads to delete')
    }),

    outputSchema: z.object({
      deleted_count: z.number().describe('Number of leads deleted')
    }),

    integration: 'instantly' as const,
    method: 'bulkDeleteLeads' as const,
    credentialName
  })
}
