/* eslint-disable n8n-nodes-base/node-filename-against-convention */

import {
  IExecuteFunctions,
  ILoadOptionsFunctions,
  INodeExecutionData,
  INodeType,
  INodeTypeDescription,
  NodeOperationError,
} from 'n8n-workflow';

import {
  contactOperations,
  contactFields,
  handleContactOperations,

  companyOperations,
  companyFields,
  handleCompanyOperations,

  opportunityOperations,
  opportunityFields,
  handleOpportunityOperations,

  // customFieldOperations,
  // customFieldFields,
  // handleCustomFieldOperations,
} from '@src/resources';
import { GoHighLevelManager } from '@src/utils/gohighlevel';

export class GoHighLevelV2 implements INodeType {
  description: INodeTypeDescription = {
    displayName: 'GoHighLevel V2',
    name: 'goHighLevelV2',
    icon: 'file:gohighlevel.svg',
    group: ['transform'],
    version: 1,
    subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
    description: 'Consume GoHighLevel V2 API',
    defaults: {
      name: 'GoHighLevel V2',
    },
    inputs: ['main'],
    outputs: ['main'],
    credentials: [
      {
        name: 'goHighLevelOAuth2Api',
        required: true,
      },
    ],
    requestDefaults: {
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
        'Version': '2021-07-28',
      },
    },
    properties: [
      {
        displayName: 'Resource',
        name: 'resource',
        type: 'options',
        noDataExpression: true,
        options: [
          {
            name: 'Contact',
            value: 'contact',
          },
          {
            name: 'Company',
            value: 'company',
          },
          {
            name: 'Opportunity',
            value: 'opportunity',
          },
          {
            name: 'Custom Field',
            value: 'customField',
          },
          // {
          //   name: 'Form',
          //   value: 'form',
          // },
          // {
          //   name: 'Funnel',
          //   value: 'funnel',
          // },
          // {
          //   name: 'Redirect',
          //   value: 'redirect',
          // },
          // {
          //   name: 'Conversation',
          //   value: 'conversation',
          // },
          // {
          //   name: 'Message',
          //   value: 'message',
          // },
        ],
        default: 'contact',
      },
      // Contact Resource
      ...contactOperations,
      ...contactFields,
      // Company Resource
      ...companyOperations,
      ...companyFields,
      // Opportunity Resource
      ...opportunityOperations,
      ...opportunityFields,
      // // Custom Field Resource
      // ...customFieldOperations,
      // ...customFieldFields,
      // // Form Resource
      // ...formOperations,
      // ...formFields,
      // // Funnel Resource
      // ...funnelOperations,
      // ...funnelFields,
      // // Redirect Resource
      // ...redirectOperations,
      // ...redirectFields,
      // // Conversation Resource
      // ...conversationOperations,
      // ...conversationFields,
      // // Message Resource
      // ...messageOperations,
      // ...messageFields,
    ],
  };

  methods = {
    loadOptions: {
      async getCustomFields(this: ILoadOptionsFunctions) {
        const GHLEngine = await GoHighLevelManager.getInstance(this);

        const customFields = await GHLEngine.getCustomFields();

        return customFields.map((field) => ({
          name: field.name,
          value: field.id || '',
        }))
      },
      async getOpportunityCustomFields(this: ILoadOptionsFunctions) {
        const GHLEngine = await GoHighLevelManager.getInstance(this);

        const customFields = await GHLEngine.getCustomFields('opportunity');

        return customFields.map((field) => ({
          name: field.name,
          value: field.id || '',
        }))
      },
      async getContactCustomFields(this: ILoadOptionsFunctions) {
        const GHLEngine = await GoHighLevelManager.getInstance(this);

        const customFields = await GHLEngine.getCustomFields('contact');

        return customFields.map((field) => ({
          name: field.name,
          value: field.id || '',
        }))
      },
    },
  };

  async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
    const items = this.getInputData();
    const returnData: INodeExecutionData[] = [];
    const resource = this.getNodeParameter('resource', 0) as string;
    const operation = this.getNodeParameter('operation', 0) as string;

    for (let i = 0; i < items.length; i++) {
      try {
        let responseData;

        switch (resource) {
          case 'contact':
            responseData = await handleContactOperations.call(this, operation, i);
            break;

          case 'company':
            responseData = await handleCompanyOperations.call(this, operation, i);
            break;

          case 'opportunity':
            responseData = await handleOpportunityOperations.call(this, operation, i);
            break;

          // case 'customField':
          //   responseData = await handleCustomFieldOperations.call(this, operation, i);
          //   break;

          // case 'form':
          //   responseData = await handleFormOperations.call(this, operation, i);
          //   break;

          // case 'funnel':
          //   responseData = await handleFunnelOperations.call(this, operation, i);
          //   break;

          // case 'redirect':
          //   responseData = await handleRedirectOperations.call(this, operation, i);
          //   break;

          // case 'conversation':
          //   responseData = await handleConversationOperations.call(this, operation, i);
          //   break;

          // case 'message':
          //   responseData = await handleMessageOperations.call(this, operation, i);
          //   break;

          default:
            throw new NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`);
        }

        if (Array.isArray(responseData)) {
          returnData.push.apply(returnData, responseData.map(item => ({ json: item })));
        } else {
          returnData.push({ json: responseData });
        }
      } catch (error: any) {
        if (this.continueOnFail()) {
          returnData.push({ json: { error: error.message } });
          continue;
        }
        throw error;
      }
    }

    return [returnData];
  }
}
