/**
 * Opportunity management tools
 */

import type { SalesforceClient } from '../clients/salesforce.js';
import type { Opportunity } from '../types/index.js';

export function getTools(client: SalesforceClient) {
  return [
    {
      name: 'sf_list_opportunities',
      description: 'List opportunities with optional filters. Returns up to 200 opportunities by default.',
      inputSchema: {
        type: 'object',
        properties: {
          limit: {
            type: 'number',
            description: 'Maximum number of opportunities 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., "CloseDate ASC", "Amount DESC")',
            default: 'CloseDate ASC',
          },
          stageName: {
            type: 'string',
            description: 'Filter by stage name (e.g., "Prospecting", "Closed Won")',
          },
          accountId: {
            type: 'string',
            description: 'Filter by account ID',
          },
          isClosed: {
            type: 'boolean',
            description: 'Filter by closed status',
          },
          isWon: {
            type: 'boolean',
            description: 'Filter by won status',
          },
        },
      },
      handler: async (args: {
        limit?: number;
        offset?: number;
        orderBy?: string;
        stageName?: string;
        accountId?: string;
        isClosed?: boolean;
        isWon?: boolean;
      }) => {
        const conditions: string[] = [];
        if (args.stageName) conditions.push(`StageName = '${args.stageName}'`);
        if (args.accountId) conditions.push(`AccountId = '${args.accountId}'`);
        if (args.isClosed !== undefined) conditions.push(`IsClosed = ${args.isClosed}`);
        if (args.isWon !== undefined) conditions.push(`IsWon = ${args.isWon}`);

        const soql = client.buildSOQL({
          select: ['Id', 'Name', 'Account.Name', 'StageName', 'CloseDate', 'Amount', 'Probability', 'Type', 'LeadSource', 'IsClosed', 'IsWon', 'Owner.Name', 'CreatedDate'],
          from: 'Opportunity',
          where: conditions.length > 0 ? conditions.join(' AND ') : undefined,
          orderBy: args.orderBy || 'CloseDate ASC',
          limit: args.limit || 200,
          offset: args.offset,
        });

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

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

    {
      name: 'sf_create_opportunity',
      description: 'Create a new opportunity',
      inputSchema: {
        type: 'object',
        properties: {
          name: {
            type: 'string',
            description: 'Opportunity name (required)',
          },
          stageName: {
            type: 'string',
            description: 'Stage name (required, e.g., "Prospecting", "Qualification")',
          },
          closeDate: {
            type: 'string',
            description: 'Close date in YYYY-MM-DD format (required)',
          },
          accountId: {
            type: 'string',
            description: 'Associated account ID',
          },
          amount: {
            type: 'number',
            description: 'Opportunity amount',
          },
          probability: {
            type: 'number',
            description: 'Probability percentage (0-100)',
          },
          type: {
            type: 'string',
            description: 'Opportunity type (e.g., "New Business", "Existing Business")',
          },
          leadSource: {
            type: 'string',
            description: 'Lead source',
          },
          description: {
            type: 'string',
            description: 'Opportunity description',
          },
        },
        required: ['name', 'stageName', 'closeDate'],
      },
      handler: async (args: {
        name: string;
        stageName: string;
        closeDate: string;
        accountId?: string;
        amount?: number;
        probability?: number;
        type?: string;
        leadSource?: string;
        description?: string;
      }) => {
        const opportunityData: Partial<Opportunity> = {
          Name: args.name,
          StageName: args.stageName,
          CloseDate: args.closeDate,
          AccountId: args.accountId as any,
          Amount: args.amount,
          Probability: args.probability,
          Type: args.type,
          LeadSource: args.leadSource,
          Description: args.description,
        };

        const result = await client.createRecord('Opportunity', opportunityData);
        return result;
      },
    },

    {
      name: 'sf_update_opportunity',
      description: 'Update an existing opportunity',
      inputSchema: {
        type: 'object',
        properties: {
          opportunityId: {
            type: 'string',
            description: 'The Salesforce ID of the opportunity to update',
          },
          name: { type: 'string' },
          stageName: { type: 'string' },
          closeDate: { type: 'string', description: 'Close date in YYYY-MM-DD format' },
          accountId: { type: 'string' },
          amount: { type: 'number' },
          probability: { type: 'number' },
          type: { type: 'string' },
          leadSource: { type: 'string' },
          description: { type: 'string' },
        },
        required: ['opportunityId'],
      },
      handler: async (args: {
        opportunityId: string;
        name?: string;
        stageName?: string;
        closeDate?: string;
        accountId?: string;
        amount?: number;
        probability?: number;
        type?: string;
        leadSource?: string;
        description?: string;
      }) => {
        const { opportunityId, ...updates } = args;
        const opportunityData: Partial<Opportunity> = {
          Name: updates.name,
          StageName: updates.stageName,
          CloseDate: updates.closeDate,
          AccountId: updates.accountId as any,
          Amount: updates.amount,
          Probability: updates.probability,
          Type: updates.type,
          LeadSource: updates.leadSource,
          Description: updates.description,
        };

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

        await client.updateRecord('Opportunity', opportunityId, opportunityData);
        return { success: true, id: opportunityId };
      },
    },

    {
      name: 'sf_delete_opportunity',
      description: 'Delete an opportunity by ID',
      inputSchema: {
        type: 'object',
        properties: {
          opportunityId: {
            type: 'string',
            description: 'The Salesforce ID of the opportunity to delete',
          },
        },
        required: ['opportunityId'],
      },
      handler: async (args: { opportunityId: string }) => {
        await client.deleteRecord('Opportunity', args.opportunityId);
        return { success: true, id: args.opportunityId };
      },
    },

    {
      name: 'sf_search_opportunities',
      description: 'Search opportunities using SOQL with flexible criteria',
      inputSchema: {
        type: 'object',
        properties: {
          searchText: {
            type: 'string',
            description: 'Text to search in Name field',
          },
          whereClause: {
            type: 'string',
            description: 'Custom WHERE clause (e.g., "Amount > 100000")',
          },
          limit: {
            type: 'number',
            description: 'Maximum number of results',
            default: 100,
          },
        },
      },
      handler: async (args: { searchText?: string; whereClause?: string; limit?: number }) => {
        let where = args.whereClause;
        
        if (args.searchText) {
          const searchCondition = `Name LIKE '%${args.searchText}%'`;
          where = where ? `${searchCondition} AND (${where})` : searchCondition;
        }

        const soql = client.buildSOQL({
          select: ['Id', 'Name', 'Account.Name', 'StageName', 'CloseDate', 'Amount', 'Probability', 'IsClosed', 'IsWon'],
          from: 'Opportunity',
          where,
          orderBy: 'CloseDate ASC',
          limit: args.limit || 100,
        });

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

    {
      name: 'sf_find_opportunities_by_stage',
      description: 'Find opportunities by stage name',
      inputSchema: {
        type: 'object',
        properties: {
          stageName: {
            type: 'string',
            description: 'Stage name to filter by',
          },
          limit: {
            type: 'number',
            description: 'Maximum number of results',
            default: 100,
          },
        },
        required: ['stageName'],
      },
      handler: async (args: { stageName: string; limit?: number }) => {
        const soql = client.buildSOQL({
          select: ['Id', 'Name', 'Account.Name', 'StageName', 'CloseDate', 'Amount', 'Probability', 'Owner.Name'],
          from: 'Opportunity',
          where: `StageName = '${args.stageName}'`,
          orderBy: 'CloseDate ASC',
          limit: args.limit || 100,
        });

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

    {
      name: 'sf_find_opportunities_by_amount',
      description: 'Find opportunities by amount range',
      inputSchema: {
        type: 'object',
        properties: {
          minAmount: {
            type: 'number',
            description: 'Minimum opportunity amount',
          },
          maxAmount: {
            type: 'number',
            description: 'Maximum opportunity amount',
          },
          limit: {
            type: 'number',
            description: 'Maximum number of results',
            default: 100,
          },
        },
      },
      handler: async (args: { minAmount?: number; maxAmount?: number; limit?: number }) => {
        const conditions: string[] = [];
        if (args.minAmount !== undefined) conditions.push(`Amount >= ${args.minAmount}`);
        if (args.maxAmount !== undefined) conditions.push(`Amount <= ${args.maxAmount}`);

        const soql = client.buildSOQL({
          select: ['Id', 'Name', 'Account.Name', 'StageName', 'CloseDate', 'Amount', 'Probability', 'Owner.Name'],
          from: 'Opportunity',
          where: conditions.length > 0 ? conditions.join(' AND ') : undefined,
          orderBy: 'Amount DESC',
          limit: args.limit || 100,
        });

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