/**
 * Generic custom object CRUD tools
 */

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

export function getTools(client: SalesforceClient) {
  return [
    {
      name: 'sf_describe_object',
      description: 'Describe any SObject (standard or custom) to get field metadata',
      inputSchema: {
        type: 'object',
        properties: {
          objectName: {
            type: 'string',
            description: 'Name of the SObject (e.g., "Account", "MyCustomObject__c")',
          },
        },
        required: ['objectName'],
      },
      handler: async (args: { objectName: string }) => {
        const describe = await client.describe(args.objectName);
        return {
          name: describe.name,
          label: describe.label,
          labelPlural: describe.labelPlural,
          custom: describe.custom,
          createable: describe.createable,
          updateable: describe.updateable,
          deletable: describe.deletable,
          queryable: describe.queryable,
          fields: describe.fields.map(f => ({
            name: f.name,
            label: f.label,
            type: f.type,
            length: f.length,
            createable: f.createable,
            updateable: f.updateable,
            nillable: f.nillable,
            picklistValues: f.picklistValues,
            referenceTo: f.referenceTo,
          })),
          childRelationships: describe.childRelationships,
        };
      },
    },

    {
      name: 'sf_list_custom_objects',
      description: 'List all custom objects in the org',
      inputSchema: {
        type: 'object',
        properties: {
          limit: {
            type: 'number',
            description: 'Maximum number of custom objects to return',
            default: 100,
          },
        },
      },
      handler: async (args: { limit?: number }) => {
        // Query EntityDefinition for custom objects
        const soql = client.buildSOQL({
          select: ['QualifiedApiName', 'Label', 'PluralLabel', 'IsCustomizable', 'IsQueryable'],
          from: 'EntityDefinition',
          where: 'IsCustomizable = true AND QualifiedApiName LIKE \'%__c\'',
          orderBy: 'QualifiedApiName ASC',
          limit: args.limit || 100,
        });

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

    {
      name: 'sf_get_custom_record',
      description: 'Get a record from any custom object by ID',
      inputSchema: {
        type: 'object',
        properties: {
          objectName: {
            type: 'string',
            description: 'Name of the custom object (e.g., "MyCustomObject__c")',
          },
          recordId: {
            type: 'string',
            description: 'The Salesforce ID of the record',
          },
          fields: {
            type: 'array',
            description: 'Optional: specific fields to retrieve',
            items: { type: 'string' },
          },
        },
        required: ['objectName', 'recordId'],
      },
      handler: async (args: { objectName: string; recordId: string; fields?: string[] }) => {
        const record = await client.getRecord<CustomSObject>(
          args.objectName,
          args.recordId,
          args.fields
        );
        return record;
      },
    },

    {
      name: 'sf_list_custom_records',
      description: 'List records from any custom object',
      inputSchema: {
        type: 'object',
        properties: {
          objectName: {
            type: 'string',
            description: 'Name of the custom object (e.g., "MyCustomObject__c")',
          },
          fields: {
            type: 'array',
            description: 'Fields to retrieve (defaults to Id, Name, CreatedDate)',
            items: { type: 'string' },
          },
          whereClause: {
            type: 'string',
            description: 'Optional WHERE clause for filtering',
          },
          orderBy: {
            type: 'string',
            description: 'Field to sort by (default: CreatedDate DESC)',
          },
          limit: {
            type: 'number',
            description: 'Maximum number of records to return',
            default: 200,
          },
          offset: {
            type: 'number',
            description: 'Number of records to skip (for pagination)',
          },
        },
        required: ['objectName'],
      },
      handler: async (args: {
        objectName: string;
        fields?: string[];
        whereClause?: string;
        orderBy?: string;
        limit?: number;
        offset?: number;
      }) => {
        const fields = args.fields || ['Id', 'Name', 'CreatedDate', 'LastModifiedDate'];
        
        const soql = client.buildSOQL({
          select: fields,
          from: args.objectName,
          where: args.whereClause,
          orderBy: args.orderBy || 'CreatedDate DESC',
          limit: args.limit || 200,
          offset: args.offset,
        });

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

    {
      name: 'sf_create_custom_record',
      description: 'Create a new record in any custom object',
      inputSchema: {
        type: 'object',
        properties: {
          objectName: {
            type: 'string',
            description: 'Name of the custom object (e.g., "MyCustomObject__c")',
          },
          fields: {
            type: 'object',
            description: 'Field values as key-value pairs (e.g., {"Name": "Test", "CustomField__c": "Value"})',
          },
        },
        required: ['objectName', 'fields'],
      },
      handler: async (args: { objectName: string; fields: Record<string, unknown> }) => {
        const result = await client.createRecord(args.objectName, args.fields);
        return result;
      },
    },

    {
      name: 'sf_update_custom_record',
      description: 'Update an existing record in any custom object',
      inputSchema: {
        type: 'object',
        properties: {
          objectName: {
            type: 'string',
            description: 'Name of the custom object (e.g., "MyCustomObject__c")',
          },
          recordId: {
            type: 'string',
            description: 'The Salesforce ID of the record to update',
          },
          fields: {
            type: 'object',
            description: 'Field values to update as key-value pairs',
          },
        },
        required: ['objectName', 'recordId', 'fields'],
      },
      handler: async (args: {
        objectName: string;
        recordId: string;
        fields: Record<string, unknown>;
      }) => {
        await client.updateRecord(args.objectName, args.recordId, args.fields);
        return { success: true, id: args.recordId };
      },
    },

    {
      name: 'sf_delete_custom_record',
      description: 'Delete a record from any custom object',
      inputSchema: {
        type: 'object',
        properties: {
          objectName: {
            type: 'string',
            description: 'Name of the custom object (e.g., "MyCustomObject__c")',
          },
          recordId: {
            type: 'string',
            description: 'The Salesforce ID of the record to delete',
          },
        },
        required: ['objectName', 'recordId'],
      },
      handler: async (args: { objectName: string; recordId: string }) => {
        await client.deleteRecord(args.objectName, args.recordId);
        return { success: true, id: args.recordId };
      },
    },
  ];
}
