import { Tool } from '@modelcontextprotocol/sdk/types.js';
import { GHLApiClient } from '../clients/ghl-api-client.js';
import {
  MCPCreateAssociationParams,
  MCPUpdateAssociationParams,
  MCPGetAllAssociationsParams,
  MCPGetAssociationByIdParams,
  MCPGetAssociationByKeyParams,
  MCPGetAssociationByObjectKeyParams,
  MCPDeleteAssociationParams,
  MCPCreateRelationParams,
  MCPGetRelationsByRecordParams,
  MCPDeleteRelationParams
} from '../types/ghl-types.js';

export class AssociationTools {
  constructor(private apiClient: GHLApiClient) {}

  getTools(): Tool[] {
    return [
      // Association Management Tools
      {
        name: 'ghl_get_all_associations',
        description: 'Get all associations for a sub-account/location with pagination. Returns system-defined and user-defined associations.',
        inputSchema: {
          type: 'object',
          properties: {
            locationId: {
              type: 'string',
              description: 'GoHighLevel location ID (will use default if not provided)'
            },
            skip: {
              type: 'number',
              description: 'Number of records to skip for pagination',
              default: 0
            },
            limit: {
              type: 'number',
              description: 'Maximum number of records to return (max 100)',
              default: 20
            }
          }
        }
      },
      {
        name: 'ghl_create_association',
        description: 'Create a new association that defines relationship types between entities like contacts, custom objects, and opportunities.',
        inputSchema: {
          type: 'object',
          properties: {
            locationId: {
              type: 'string',
              description: 'GoHighLevel location ID (will use default if not provided)'
            },
            key: {
              type: 'string',
              description: 'Unique key for the association (e.g., "student_teacher")'
            },
            firstObjectLabel: {
              description: 'Label for the first object in the association (e.g., "student")'
            },
            firstObjectKey: {
              description: 'Key for the first object (e.g., "custom_objects.children")'
            },
            secondObjectLabel: {
              description: 'Label for the second object in the association (e.g., "teacher")'
            },
            secondObjectKey: {
              description: 'Key for the second object (e.g., "contact")'
            }
          },
          required: ['key', 'firstObjectLabel', 'firstObjectKey', 'secondObjectLabel', 'secondObjectKey']
        }
      },
      {
        name: 'ghl_get_association_by_id',
        description: 'Get a specific association by its ID. Works for both system-defined and user-defined associations.',
        inputSchema: {
          type: 'object',
          properties: {
            associationId: {
              type: 'string',
              description: 'The ID of the association to retrieve'
            }
          },
          required: ['associationId']
        }
      },
      {
        name: 'ghl_update_association',
        description: 'Update the labels of an existing association. Only user-defined associations can be updated.',
        inputSchema: {
          type: 'object',
          properties: {
            associationId: {
              type: 'string',
              description: 'The ID of the association to update'
            },
            firstObjectLabel: {
              description: 'New label for the first object in the association'
            },
            secondObjectLabel: {
              description: 'New label for the second object in the association'
            }
          },
          required: ['associationId', 'firstObjectLabel', 'secondObjectLabel']
        }
      },
      {
        name: 'ghl_delete_association',
        description: 'Delete a user-defined association. This will also delete all relations created with this association.',
        inputSchema: {
          type: 'object',
          properties: {
            associationId: {
              type: 'string',
              description: 'The ID of the association to delete'
            }
          },
          required: ['associationId']
        }
      },
      {
        name: 'ghl_get_association_by_key',
        description: 'Get an association by its key name. Useful for finding both standard and user-defined associations.',
        inputSchema: {
          type: 'object',
          properties: {
            keyName: {
              type: 'string',
              description: 'The key name of the association to retrieve'
            },
            locationId: {
              type: 'string',
              description: 'GoHighLevel location ID (will use default if not provided)'
            }
          },
          required: ['keyName']
        }
      },
      {
        name: 'ghl_get_association_by_object_key',
        description: 'Get associations by object keys like contacts, custom objects, and opportunities.',
        inputSchema: {
          type: 'object',
          properties: {
            objectKey: {
              type: 'string',
              description: 'The object key to search for (e.g., "custom_objects.car", "contact", "opportunity")'
            },
            locationId: {
              type: 'string',
              description: 'GoHighLevel location ID (optional)'
            }
          },
          required: ['objectKey']
        }
      },
      // Relation Management Tools
      {
        name: 'ghl_create_relation',
        description: 'Create a relation between two entities using an existing association. Links specific records together.',
        inputSchema: {
          type: 'object',
          properties: {
            locationId: {
              type: 'string',
              description: 'GoHighLevel location ID (will use default if not provided)'
            },
            associationId: {
              type: 'string',
              description: 'The ID of the association to use for this relation'
            },
            firstRecordId: {
              type: 'string',
              description: 'ID of the first record (e.g., contact ID if contact is first object in association)'
            },
            secondRecordId: {
              type: 'string',
              description: 'ID of the second record (e.g., custom object record ID if custom object is second object)'
            }
          },
          required: ['associationId', 'firstRecordId', 'secondRecordId']
        }
      },
      {
        name: 'ghl_get_relations_by_record',
        description: 'Get all relations for a specific record ID with pagination and optional filtering by association IDs.',
        inputSchema: {
          type: 'object',
          properties: {
            recordId: {
              type: 'string',
              description: 'The record ID to get relations for'
            },
            locationId: {
              type: 'string',
              description: 'GoHighLevel location ID (will use default if not provided)'
            },
            skip: {
              type: 'number',
              description: 'Number of records to skip for pagination',
              default: 0
            },
            limit: {
              type: 'number',
              description: 'Maximum number of records to return',
              default: 20
            },
            associationIds: {
              type: 'array',
              items: {
                type: 'string'
              },
              description: 'Optional array of association IDs to filter relations'
            }
          },
          required: ['recordId']
        }
      },
      {
        name: 'ghl_delete_relation',
        description: 'Delete a specific relation between two entities.',
        inputSchema: {
          type: 'object',
          properties: {
            relationId: {
              type: 'string',
              description: 'The ID of the relation to delete'
            },
            locationId: {
              type: 'string',
              description: 'GoHighLevel location ID (will use default if not provided)'
            }
          },
          required: ['relationId']
        }
      }
    ];
  }

  async executeAssociationTool(name: string, args: any): Promise<any> {
    try {
      switch (name) {
        case 'ghl_get_all_associations': {
          const params: MCPGetAllAssociationsParams = args;
          const result = await this.apiClient.getAssociations({
            locationId: params.locationId || '',
            skip: params.skip || 0,
            limit: params.limit || 20
          });
          return {
            success: true,
            data: result.data,
            message: `Retrieved ${result.data?.associations?.length || 0} associations`
          };
        }

        case 'ghl_create_association': {
          const params: MCPCreateAssociationParams = args;
          const result = await this.apiClient.createAssociation({
            locationId: params.locationId || '',
            key: params.key,
            firstObjectLabel: params.firstObjectLabel,
            firstObjectKey: params.firstObjectKey,
            secondObjectLabel: params.secondObjectLabel,
            secondObjectKey: params.secondObjectKey
          });
          return {
            success: true,
            data: result.data,
            message: `Association '${params.key}' created successfully`
          };
        }

        case 'ghl_get_association_by_id': {
          const params: MCPGetAssociationByIdParams = args;
          const result = await this.apiClient.getAssociationById(params.associationId);
          return {
            success: true,
            data: result.data,
            message: `Association retrieved successfully`
          };
        }

        case 'ghl_update_association': {
          const params: MCPUpdateAssociationParams = args;
          const result = await this.apiClient.updateAssociation(params.associationId, {
            firstObjectLabel: params.firstObjectLabel,
            secondObjectLabel: params.secondObjectLabel
          });
          return {
            success: true,
            data: result.data,
            message: `Association updated successfully`
          };
        }

        case 'ghl_delete_association': {
          const params: MCPDeleteAssociationParams = args;
          const result = await this.apiClient.deleteAssociation(params.associationId);
          return {
            success: true,
            data: result.data,
            message: `Association deleted successfully`
          };
        }

        case 'ghl_get_association_by_key': {
          const params: MCPGetAssociationByKeyParams = args;
          const result = await this.apiClient.getAssociationByKey({
            keyName: params.keyName,
            locationId: params.locationId || ''
          });
          return {
            success: true,
            data: result.data,
            message: `Association with key '${params.keyName}' retrieved successfully`
          };
        }

        case 'ghl_get_association_by_object_key': {
          const params: MCPGetAssociationByObjectKeyParams = args;
          const result = await this.apiClient.getAssociationByObjectKey({
            objectKey: params.objectKey,
            locationId: params.locationId
          });
          return {
            success: true,
            data: result.data,
            message: `Association with object key '${params.objectKey}' retrieved successfully`
          };
        }

        case 'ghl_create_relation': {
          const params: MCPCreateRelationParams = args;
          const result = await this.apiClient.createRelation({
            locationId: params.locationId || '',
            associationId: params.associationId,
            firstRecordId: params.firstRecordId,
            secondRecordId: params.secondRecordId
          });
          return {
            success: true,
            data: result.data,
            message: `Relation created successfully between records`
          };
        }

        case 'ghl_get_relations_by_record': {
          const params: MCPGetRelationsByRecordParams = args;
          const result = await this.apiClient.getRelationsByRecord({
            recordId: params.recordId,
            locationId: params.locationId || '',
            skip: params.skip || 0,
            limit: params.limit || 20,
            associationIds: params.associationIds
          });
          return {
            success: true,
            data: result.data,
            message: `Retrieved ${result.data?.relations?.length || 0} relations for record`
          };
        }

        case 'ghl_delete_relation': {
          const params: MCPDeleteRelationParams = args;
          const result = await this.apiClient.deleteRelation({
            relationId: params.relationId,
            locationId: params.locationId || ''
          });
          return {
            success: true,
            data: result.data,
            message: `Relation deleted successfully`
          };
        }

        default:
          throw new Error(`Unknown association tool: ${name}`);
      }
    } catch (error) {
      return {
        success: false,
        error: error instanceof Error ? error.message : String(error),
        message: `Failed to execute ${name}`
      };
    }
  }
} 