/**
 * Campaign and Campaign Member management tools
 */

import type { SalesforceClient } from '../clients/salesforce.js';
import type { Campaign, CampaignMember } from '../types/index.js';

export function getTools(client: SalesforceClient) {
  return [
    {
      name: 'sf_list_campaigns',
      description: 'List campaigns with optional filters. Returns up to 200 campaigns by default.',
      inputSchema: {
        type: 'object',
        properties: {
          limit: {
            type: 'number',
            description: 'Maximum number of campaigns to return (default: 200)',
            default: 200,
          },
          offset: {
            type: 'number',
            description: 'Number of records to skip (for pagination)',
          },
          orderBy: {
            type: 'string',
            description: 'Field to sort by (e.g., "Name ASC", "StartDate DESC")',
            default: 'Name ASC',
          },
          isActive: {
            type: 'boolean',
            description: 'Filter by active status',
          },
          type: {
            type: 'string',
            description: 'Filter by campaign type',
          },
          status: {
            type: 'string',
            description: 'Filter by campaign status',
          },
        },
      },
      handler: async (args: {
        limit?: number;
        offset?: number;
        orderBy?: string;
        isActive?: boolean;
        type?: string;
        status?: string;
      }) => {
        const conditions: string[] = [];
        if (args.isActive !== undefined) conditions.push(`IsActive = ${args.isActive}`);
        if (args.type) conditions.push(`Type = '${args.type}'`);
        if (args.status) conditions.push(`Status = '${args.status}'`);

        const soql = client.buildSOQL({
          select: ['Id', 'Name', 'Type', 'Status', 'StartDate', 'EndDate', 'IsActive', 'BudgetedCost', 'ActualCost', 'ExpectedRevenue', 'NumberOfLeads', 'NumberOfContacts', 'Owner.Name', 'CreatedDate'],
          from: 'Campaign',
          where: conditions.length > 0 ? conditions.join(' AND ') : undefined,
          orderBy: args.orderBy || 'Name ASC',
          limit: args.limit || 200,
          offset: args.offset,
        });

        const result = await client.query<Campaign>(soql);
        return {
          totalSize: result.totalSize,
          records: result.records,
          hasMore: !result.done,
        };
      },
    },

    {
      name: 'sf_get_campaign',
      description: 'Get detailed information about a specific campaign by ID',
      inputSchema: {
        type: 'object',
        properties: {
          campaignId: {
            type: 'string',
            description: 'The Salesforce ID of the campaign (15 or 18 characters)',
          },
        },
        required: ['campaignId'],
      },
      handler: async (args: { campaignId: string }) => {
        const campaign = await client.getRecord<Campaign>('Campaign', args.campaignId);
        return campaign;
      },
    },

    {
      name: 'sf_create_campaign',
      description: 'Create a new campaign',
      inputSchema: {
        type: 'object',
        properties: {
          name: {
            type: 'string',
            description: 'Campaign name (required)',
          },
          type: {
            type: 'string',
            description: 'Campaign type (e.g., "Email", "Webinar", "Conference")',
          },
          status: {
            type: 'string',
            description: 'Campaign status (e.g., "Planned", "In Progress", "Completed")',
          },
          startDate: {
            type: 'string',
            description: 'Start date in YYYY-MM-DD format',
          },
          endDate: {
            type: 'string',
            description: 'End date in YYYY-MM-DD format',
          },
          description: {
            type: 'string',
            description: 'Campaign description',
          },
          isActive: {
            type: 'boolean',
            description: 'Whether the campaign is active',
          },
          budgetedCost: {
            type: 'number',
            description: 'Budgeted cost',
          },
          actualCost: {
            type: 'number',
            description: 'Actual cost',
          },
          expectedRevenue: {
            type: 'number',
            description: 'Expected revenue',
          },
        },
        required: ['name'],
      },
      handler: async (args: {
        name: string;
        type?: string;
        status?: string;
        startDate?: string;
        endDate?: string;
        description?: string;
        isActive?: boolean;
        budgetedCost?: number;
        actualCost?: number;
        expectedRevenue?: number;
      }) => {
        const campaignData: Partial<Campaign> = {
          Name: args.name,
          Type: args.type,
          Status: args.status,
          StartDate: args.startDate,
          EndDate: args.endDate,
          Description: args.description,
          IsActive: args.isActive,
          BudgetedCost: args.budgetedCost,
          ActualCost: args.actualCost,
          ExpectedRevenue: args.expectedRevenue,
        };

        const result = await client.createRecord('Campaign', campaignData);
        return result;
      },
    },

    {
      name: 'sf_update_campaign',
      description: 'Update an existing campaign',
      inputSchema: {
        type: 'object',
        properties: {
          campaignId: {
            type: 'string',
            description: 'The Salesforce ID of the campaign to update',
          },
          name: { type: 'string' },
          type: { type: 'string' },
          status: { type: 'string' },
          startDate: { type: 'string', description: 'Start date in YYYY-MM-DD format' },
          endDate: { type: 'string', description: 'End date in YYYY-MM-DD format' },
          description: { type: 'string' },
          isActive: { type: 'boolean' },
          budgetedCost: { type: 'number' },
          actualCost: { type: 'number' },
          expectedRevenue: { type: 'number' },
        },
        required: ['campaignId'],
      },
      handler: async (args: {
        campaignId: string;
        name?: string;
        type?: string;
        status?: string;
        startDate?: string;
        endDate?: string;
        description?: string;
        isActive?: boolean;
        budgetedCost?: number;
        actualCost?: number;
        expectedRevenue?: number;
      }) => {
        const { campaignId, ...updates } = args;
        const campaignData: Partial<Campaign> = {
          Name: updates.name,
          Type: updates.type,
          Status: updates.status,
          StartDate: updates.startDate,
          EndDate: updates.endDate,
          Description: updates.description,
          IsActive: updates.isActive,
          BudgetedCost: updates.budgetedCost,
          ActualCost: updates.actualCost,
          ExpectedRevenue: updates.expectedRevenue,
        };

        // Remove undefined values
        Object.keys(campaignData).forEach((key) => {
          if (campaignData[key as keyof Campaign] === undefined) {
            delete campaignData[key as keyof Campaign];
          }
        });

        await client.updateRecord('Campaign', campaignId, campaignData);
        return { success: true, id: campaignId };
      },
    },

    {
      name: 'sf_add_campaign_member',
      description: 'Add a lead or contact to a campaign as a campaign member',
      inputSchema: {
        type: 'object',
        properties: {
          campaignId: {
            type: 'string',
            description: 'The Salesforce ID of the campaign',
          },
          leadId: {
            type: 'string',
            description: 'The Lead ID (either leadId or contactId is required)',
          },
          contactId: {
            type: 'string',
            description: 'The Contact ID (either leadId or contactId is required)',
          },
          status: {
            type: 'string',
            description: 'Member status (e.g., "Sent", "Responded")',
          },
        },
        required: ['campaignId'],
      },
      handler: async (args: {
        campaignId: string;
        leadId?: string;
        contactId?: string;
        status?: string;
      }) => {
        if (!args.leadId && !args.contactId) {
          throw new Error('Either leadId or contactId must be provided');
        }

        const memberData: Partial<CampaignMember> = {
          CampaignId: args.campaignId as any,
          LeadId: args.leadId as any,
          ContactId: args.contactId as any,
          Status: args.status,
        };

        const result = await client.createRecord('CampaignMember', memberData);
        return result;
      },
    },

    {
      name: 'sf_list_campaign_members',
      description: 'List members of a specific campaign',
      inputSchema: {
        type: 'object',
        properties: {
          campaignId: {
            type: 'string',
            description: 'The Salesforce ID of the campaign',
          },
          limit: {
            type: 'number',
            description: 'Maximum number of members to return',
            default: 200,
          },
        },
        required: ['campaignId'],
      },
      handler: async (args: { campaignId: string; limit?: number }) => {
        const soql = client.buildSOQL({
          select: ['Id', 'CampaignId', 'LeadId', 'ContactId', 'Status', 'HasResponded', 'FirstRespondedDate', 'Lead.Name', 'Contact.Name'],
          from: 'CampaignMember',
          where: `CampaignId = '${args.campaignId}'`,
          limit: args.limit || 200,
        });

        const result = await client.query<CampaignMember>(soql);
        return result.records;
      },
    },

    {
      name: 'sf_get_campaign_stats',
      description: 'Get statistics for a specific campaign',
      inputSchema: {
        type: 'object',
        properties: {
          campaignId: {
            type: 'string',
            description: 'The Salesforce ID of the campaign',
          },
        },
        required: ['campaignId'],
      },
      handler: async (args: { campaignId: string }) => {
        // Get campaign data
        const campaign = await client.getRecord<Campaign>('Campaign', args.campaignId, [
          'Id',
          'Name',
          'NumberOfLeads',
          'NumberOfConvertedLeads',
          'NumberOfContacts',
          'NumberOfOpportunities',
          'BudgetedCost',
          'ActualCost',
          'ExpectedRevenue',
        ]);

        // Get member count with responses
        const memberStatsSOQL = `
          SELECT COUNT(Id) total,
                 COUNT_DISTINCT(CASE WHEN HasResponded = true THEN Id END) responded
          FROM CampaignMember
          WHERE CampaignId = '${args.campaignId}'
        `;

        const memberStats = await client.query(memberStatsSOQL);

        return {
          campaign: {
            id: campaign.Id,
            name: campaign.Name,
          },
          leads: {
            total: campaign.NumberOfLeads || 0,
            converted: campaign.NumberOfConvertedLeads || 0,
          },
          contacts: campaign.NumberOfContacts || 0,
          opportunities: campaign.NumberOfOpportunities || 0,
          members: memberStats.records[0] || { total: 0, responded: 0 },
          budget: {
            budgeted: campaign.BudgetedCost || 0,
            actual: campaign.ActualCost || 0,
          },
          expectedRevenue: campaign.ExpectedRevenue || 0,
        };
      },
    },
  ];
}
