import { Tool } from '@modelcontextprotocol/sdk/types.js';
import { GHLApiClient } from '../clients/ghl-api-client.js';
import {
  CreateWhiteLabelIntegrationProviderDto,
  ListIntegrationProvidersResponse,
  IntegrationProvider,
  ListOrdersResponse,
  Order,
  CreateFulfillmentDto,
  CreateFulfillmentResponse,
  ListFulfillmentResponse,
  ListTransactionsResponse,
  Transaction,
  ListSubscriptionsResponse,
  Subscription,
  ListCouponsResponse,
  CreateCouponParams,
  UpdateCouponParams,
  DeleteCouponParams,
  CreateCouponResponse,
  DeleteCouponResponse,
  Coupon,
  CreateCustomProviderDto,
  CustomProvider,
  ConnectCustomProviderConfigDto,
  DeleteCustomProviderConfigDto,
  DeleteCustomProviderResponse,
  DisconnectCustomProviderResponse
} from '../types/ghl-types.js';

export class PaymentsTools {
  constructor(private client: GHLApiClient) {}

  getTools(): Tool[] {
    return [
      // Integration Provider Tools
      {
        name: 'create_whitelabel_integration_provider',
        description: 'Create a white-label integration provider for payments',
        inputSchema: {
          type: 'object',
          properties: {
            altId: {
              type: 'string',
              description: 'Location ID or company ID based on altType'
            },
            altType: {
              type: 'string',
              enum: ['location'],
              description: 'Alt Type'
            },
            uniqueName: {
              type: 'string',
              description: 'A unique name for the integration provider (lowercase, hyphens only)'
            },
            title: {
              type: 'string',
              description: 'The title or name of the integration provider'
            },
            provider: {
              type: 'string',
              enum: ['authorize-net', 'nmi'],
              description: 'The type of payment provider'
            },
            description: {
              type: 'string',
              description: 'A brief description of the integration provider'
            },
            imageUrl: {
              type: 'string',
              description: 'The URL to an image representing the integration provider'
            }
          },
          required: ['altId', 'altType', 'uniqueName', 'title', 'provider', 'description', 'imageUrl']
        }
      },
      {
        name: 'list_whitelabel_integration_providers',
        description: 'List white-label integration providers with optional pagination',
        inputSchema: {
          type: 'object',
          properties: {
            altId: {
              type: 'string',
              description: 'Location ID or company ID based on altType'
            },
            altType: {
              type: 'string',
              enum: ['location'],
              description: 'Alt Type'
            },
            limit: {
              type: 'number',
              description: 'Maximum number of items to return',
              default: 0
            },
            offset: {
              type: 'number',
              description: 'Starting index for pagination',
              default: 0
            }
          },
          required: ['altId', 'altType']
        }
      },

      // Order Tools
      {
        name: 'list_orders',
        description: 'List orders with optional filtering and pagination',
        inputSchema: {
          type: 'object',
          properties: {
            locationId: {
              type: 'string',
              description: 'Location ID (sub-account ID)'
            },
            altId: {
              type: 'string',
              description: 'Alt ID (unique identifier like location ID)'
            },
            altType: {
              type: 'string',
              description: 'Alt Type (type of identifier)'
            },
            status: {
              type: 'string',
              description: 'Order status filter'
            },
            paymentMode: {
              type: 'string',
              description: 'Mode of payment (live/test)'
            },
            startAt: {
              type: 'string',
              description: 'Starting date interval for orders (YYYY-MM-DD)'
            },
            endAt: {
              type: 'string',
              description: 'Ending date interval for orders (YYYY-MM-DD)'
            },
            search: {
              type: 'string',
              description: 'Search term for order name'
            },
            contactId: {
              type: 'string',
              description: 'Contact ID for filtering orders'
            },
            funnelProductIds: {
              type: 'string',
              description: 'Comma-separated funnel product IDs'
            },
            limit: {
              type: 'number',
              description: 'Maximum number of items per page',
              default: 10
            },
            offset: {
              type: 'number',
              description: 'Starting index for pagination',
              default: 0
            }
          },
          required: ['altId', 'altType']
        }
      },
      {
        name: 'get_order_by_id',
        description: 'Get a specific order by its ID',
        inputSchema: {
          type: 'object',
          properties: {
            orderId: {
              type: 'string',
              description: 'ID of the order to retrieve'
            },
            locationId: {
              type: 'string',
              description: 'Location ID (sub-account ID)'
            },
            altId: {
              type: 'string',
              description: 'Alt ID (unique identifier like location ID)'
            },
            altType: {
              type: 'string',
              description: 'Alt Type (type of identifier)'
            }
          },
          required: ['orderId', 'altId', 'altType']
        }
      },

      // Order Fulfillment Tools
      {
        name: 'create_order_fulfillment',
        description: 'Create a fulfillment for an order',
        inputSchema: {
          type: 'object',
          properties: {
            orderId: {
              type: 'string',
              description: 'ID of the order to fulfill'
            },
            altId: {
              type: 'string',
              description: 'Location ID or Agency ID'
            },
            altType: {
              type: 'string',
              enum: ['location'],
              description: 'Alt Type'
            },
            trackings: {
              type: 'array',
              description: 'Fulfillment tracking information',
              items: {
                type: 'object',
                properties: {
                  trackingNumber: {
                    type: 'string',
                    description: 'Tracking number from shipping carrier'
                  },
                  shippingCarrier: {
                    type: 'string',
                    description: 'Shipping carrier name'
                  },
                  trackingUrl: {
                    type: 'string',
                    description: 'Tracking URL'
                  }
                }
              }
            },
            items: {
              type: 'array',
              description: 'Items being fulfilled',
              items: {
                type: 'object',
                properties: {
                  priceId: {
                    type: 'string',
                    description: 'The ID of the product price'
                  },
                  qty: {
                    type: 'number',
                    description: 'Quantity of the item'
                  }
                },
                required: ['priceId', 'qty']
              }
            },
            notifyCustomer: {
              type: 'boolean',
              description: 'Whether to notify the customer'
            }
          },
          required: ['orderId', 'altId', 'altType', 'trackings', 'items', 'notifyCustomer']
        }
      },
      {
        name: 'list_order_fulfillments',
        description: 'List all fulfillments for an order',
        inputSchema: {
          type: 'object',
          properties: {
            orderId: {
              type: 'string',
              description: 'ID of the order'
            },
            altId: {
              type: 'string',
              description: 'Location ID or Agency ID'
            },
            altType: {
              type: 'string',
              enum: ['location'],
              description: 'Alt Type'
            }
          },
          required: ['orderId', 'altId', 'altType']
        }
      },

      // Transaction Tools
      {
        name: 'list_transactions',
        description: 'List transactions with optional filtering and pagination',
        inputSchema: {
          type: 'object',
          properties: {
            locationId: {
              type: 'string',
              description: 'Location ID (sub-account ID)'
            },
            altId: {
              type: 'string',
              description: 'Alt ID (unique identifier like location ID)'
            },
            altType: {
              type: 'string',
              description: 'Alt Type (type of identifier)'
            },
            paymentMode: {
              type: 'string',
              description: 'Mode of payment (live/test)'
            },
            startAt: {
              type: 'string',
              description: 'Starting date interval for transactions (YYYY-MM-DD)'
            },
            endAt: {
              type: 'string',
              description: 'Ending date interval for transactions (YYYY-MM-DD)'
            },
            entitySourceType: {
              type: 'string',
              description: 'Source of the transactions'
            },
            entitySourceSubType: {
              type: 'string',
              description: 'Source sub-type of the transactions'
            },
            search: {
              type: 'string',
              description: 'Search term for transaction name'
            },
            subscriptionId: {
              type: 'string',
              description: 'Subscription ID for filtering transactions'
            },
            entityId: {
              type: 'string',
              description: 'Entity ID for filtering transactions'
            },
            contactId: {
              type: 'string',
              description: 'Contact ID for filtering transactions'
            },
            limit: {
              type: 'number',
              description: 'Maximum number of items per page',
              default: 10
            },
            offset: {
              type: 'number',
              description: 'Starting index for pagination',
              default: 0
            }
          },
          required: ['altId', 'altType']
        }
      },
      {
        name: 'get_transaction_by_id',
        description: 'Get a specific transaction by its ID',
        inputSchema: {
          type: 'object',
          properties: {
            transactionId: {
              type: 'string',
              description: 'ID of the transaction to retrieve'
            },
            locationId: {
              type: 'string',
              description: 'Location ID (sub-account ID)'
            },
            altId: {
              type: 'string',
              description: 'Alt ID (unique identifier like location ID)'
            },
            altType: {
              type: 'string',
              description: 'Alt Type (type of identifier)'
            }
          },
          required: ['transactionId', 'altId', 'altType']
        }
      },

      // Subscription Tools
      {
        name: 'list_subscriptions',
        description: 'List subscriptions with optional filtering and pagination',
        inputSchema: {
          type: 'object',
          properties: {
            altId: {
              type: 'string',
              description: 'Alt ID (unique identifier like location ID)'
            },
            altType: {
              type: 'string',
              enum: ['location'],
              description: 'Alt Type'
            },
            entityId: {
              type: 'string',
              description: 'Entity ID for filtering subscriptions'
            },
            paymentMode: {
              type: 'string',
              description: 'Mode of payment (live/test)'
            },
            startAt: {
              type: 'string',
              description: 'Starting date interval for subscriptions (YYYY-MM-DD)'
            },
            endAt: {
              type: 'string',
              description: 'Ending date interval for subscriptions (YYYY-MM-DD)'
            },
            entitySourceType: {
              type: 'string',
              description: 'Source of the subscriptions'
            },
            search: {
              type: 'string',
              description: 'Search term for subscription name'
            },
            contactId: {
              type: 'string',
              description: 'Contact ID for the subscription'
            },
            id: {
              type: 'string',
              description: 'Subscription ID for filtering'
            },
            limit: {
              type: 'number',
              description: 'Maximum number of items per page',
              default: 10
            },
            offset: {
              type: 'number',
              description: 'Starting index for pagination',
              default: 0
            }
          },
          required: ['altId', 'altType']
        }
      },
      {
        name: 'get_subscription_by_id',
        description: 'Get a specific subscription by its ID',
        inputSchema: {
          type: 'object',
          properties: {
            subscriptionId: {
              type: 'string',
              description: 'ID of the subscription to retrieve'
            },
            altId: {
              type: 'string',
              description: 'Alt ID (unique identifier like location ID)'
            },
            altType: {
              type: 'string',
              enum: ['location'],
              description: 'Alt Type'
            }
          },
          required: ['subscriptionId', 'altId', 'altType']
        }
      },

      // Coupon Tools
      {
        name: 'list_coupons',
        description: 'List all coupons for a location with optional filtering',
        inputSchema: {
          type: 'object',
          properties: {
            altId: {
              type: 'string',
              description: 'Location ID'
            },
            altType: {
              type: 'string',
              enum: ['location'],
              description: 'Alt Type'
            },
            limit: {
              type: 'number',
              description: 'Maximum number of coupons to return',
              default: 100
            },
            offset: {
              type: 'number',
              description: 'Number of coupons to skip for pagination',
              default: 0
            },
            status: {
              type: 'string',
              enum: ['scheduled', 'active', 'expired'],
              description: 'Filter coupons by status'
            },
            search: {
              type: 'string',
              description: 'Search term to filter coupons by name or code'
            }
          },
          required: ['altId', 'altType']
        }
      },
      {
        name: 'create_coupon',
        description: 'Create a new promotional coupon',
        inputSchema: {
          type: 'object',
          properties: {
            altId: {
              type: 'string',
              description: 'Location ID'
            },
            altType: {
              type: 'string',
              enum: ['location'],
              description: 'Alt Type'
            },
            name: {
              type: 'string',
              description: 'Coupon name'
            },
            code: {
              type: 'string',
              description: 'Coupon code'
            },
            discountType: {
              type: 'string',
              enum: ['percentage', 'amount'],
              description: 'Type of discount'
            },
            discountValue: {
              type: 'number',
              description: 'Discount value'
            },
            startDate: {
              type: 'string',
              description: 'Start date in YYYY-MM-DDTHH:mm:ssZ format'
            },
            endDate: {
              type: 'string',
              description: 'End date in YYYY-MM-DDTHH:mm:ssZ format'
            },
            usageLimit: {
              type: 'number',
              description: 'Maximum number of times coupon can be used'
            },
            productIds: {
              type: 'array',
              description: 'Product IDs that the coupon applies to',
              items: {
                type: 'string'
              }
            },
            applyToFuturePayments: {
              type: 'boolean',
              description: 'Whether coupon applies to future subscription payments',
              default: true
            },
            applyToFuturePaymentsConfig: {
              type: 'object',
              description: 'Configuration for future payments application',
              properties: {
                type: {
                  type: 'string',
                  enum: ['forever', 'fixed'],
                  description: 'Type of future payments config'
                },
                duration: {
                  type: 'number',
                  description: 'Duration for fixed type'
                },
                durationType: {
                  type: 'string',
                  enum: ['months'],
                  description: 'Duration type'
                }
              },
              required: ['type']
            },
            limitPerCustomer: {
              type: 'boolean',
              description: 'Whether to limit coupon to once per customer',
              default: false
            }
          },
          required: ['altId', 'altType', 'name', 'code', 'discountType', 'discountValue', 'startDate']
        }
      },
      {
        name: 'update_coupon',
        description: 'Update an existing coupon',
        inputSchema: {
          type: 'object',
          properties: {
            id: {
              type: 'string',
              description: 'Coupon ID'
            },
            altId: {
              type: 'string',
              description: 'Location ID'
            },
            altType: {
              type: 'string',
              enum: ['location'],
              description: 'Alt Type'
            },
            name: {
              type: 'string',
              description: 'Coupon name'
            },
            code: {
              type: 'string',
              description: 'Coupon code'
            },
            discountType: {
              type: 'string',
              enum: ['percentage', 'amount'],
              description: 'Type of discount'
            },
            discountValue: {
              type: 'number',
              description: 'Discount value'
            },
            startDate: {
              type: 'string',
              description: 'Start date in YYYY-MM-DDTHH:mm:ssZ format'
            },
            endDate: {
              type: 'string',
              description: 'End date in YYYY-MM-DDTHH:mm:ssZ format'
            },
            usageLimit: {
              type: 'number',
              description: 'Maximum number of times coupon can be used'
            },
            productIds: {
              type: 'array',
              description: 'Product IDs that the coupon applies to',
              items: {
                type: 'string'
              }
            },
            applyToFuturePayments: {
              type: 'boolean',
              description: 'Whether coupon applies to future subscription payments'
            },
            applyToFuturePaymentsConfig: {
              type: 'object',
              description: 'Configuration for future payments application',
              properties: {
                type: {
                  type: 'string',
                  enum: ['forever', 'fixed'],
                  description: 'Type of future payments config'
                },
                duration: {
                  type: 'number',
                  description: 'Duration for fixed type'
                },
                durationType: {
                  type: 'string',
                  enum: ['months'],
                  description: 'Duration type'
                }
              },
              required: ['type']
            },
            limitPerCustomer: {
              type: 'boolean',
              description: 'Whether to limit coupon to once per customer'
            }
          },
          required: ['id', 'altId', 'altType', 'name', 'code', 'discountType', 'discountValue', 'startDate']
        }
      },
      {
        name: 'delete_coupon',
        description: 'Delete a coupon permanently',
        inputSchema: {
          type: 'object',
          properties: {
            altId: {
              type: 'string',
              description: 'Location ID'
            },
            altType: {
              type: 'string',
              enum: ['location'],
              description: 'Alt Type'
            },
            id: {
              type: 'string',
              description: 'Coupon ID'
            }
          },
          required: ['altId', 'altType', 'id']
        }
      },
      {
        name: 'get_coupon',
        description: 'Get coupon details by ID or code',
        inputSchema: {
          type: 'object',
          properties: {
            altId: {
              type: 'string',
              description: 'Location ID'
            },
            altType: {
              type: 'string',
              enum: ['location'],
              description: 'Alt Type'
            },
            id: {
              type: 'string',
              description: 'Coupon ID'
            },
            code: {
              type: 'string',
              description: 'Coupon code'
            }
          },
          required: ['altId', 'altType', 'id', 'code']
        }
      },

      // Custom Provider Tools
      {
        name: 'create_custom_provider_integration',
        description: 'Create a new custom payment provider integration',
        inputSchema: {
          type: 'object',
          properties: {
            locationId: {
              type: 'string',
              description: 'Location ID'
            },
            name: {
              type: 'string',
              description: 'Name of the custom provider'
            },
            description: {
              type: 'string',
              description: 'Description of the payment gateway'
            },
            paymentsUrl: {
              type: 'string',
              description: 'URL to load in iframe for payment session'
            },
            queryUrl: {
              type: 'string',
              description: 'URL for querying payment events'
            },
            imageUrl: {
              type: 'string',
              description: 'Public image URL for the payment gateway logo'
            }
          },
          required: ['locationId', 'name', 'description', 'paymentsUrl', 'queryUrl', 'imageUrl']
        }
      },
      {
        name: 'delete_custom_provider_integration',
        description: 'Delete an existing custom payment provider integration',
        inputSchema: {
          type: 'object',
          properties: {
            locationId: {
              type: 'string',
              description: 'Location ID'
            }
          },
          required: ['locationId']
        }
      },
      {
        name: 'get_custom_provider_config',
        description: 'Fetch existing payment config for a location',
        inputSchema: {
          type: 'object',
          properties: {
            locationId: {
              type: 'string',
              description: 'Location ID'
            }
          },
          required: ['locationId']
        }
      },
      {
        name: 'create_custom_provider_config',
        description: 'Create new payment config for a location',
        inputSchema: {
          type: 'object',
          properties: {
            locationId: {
              type: 'string',
              description: 'Location ID'
            },
            live: {
              type: 'object',
              description: 'Live payment configuration',
              properties: {
                apiKey: {
                  type: 'string',
                  description: 'API key for live payments'
                },
                publishableKey: {
                  type: 'string',
                  description: 'Publishable key for live payments'
                }
              },
              required: ['apiKey', 'publishableKey']
            },
            test: {
              type: 'object',
              description: 'Test payment configuration',
              properties: {
                apiKey: {
                  type: 'string',
                  description: 'API key for test payments'
                },
                publishableKey: {
                  type: 'string',
                  description: 'Publishable key for test payments'
                }
              },
              required: ['apiKey', 'publishableKey']
            }
          },
          required: ['locationId', 'live', 'test']
        }
      },
      {
        name: 'disconnect_custom_provider_config',
        description: 'Disconnect existing payment config for a location',
        inputSchema: {
          type: 'object',
          properties: {
            locationId: {
              type: 'string',
              description: 'Location ID'
            },
            liveMode: {
              type: 'boolean',
              description: 'Whether to disconnect live or test mode config'
            }
          },
          required: ['locationId', 'liveMode']
        }
      }
    ];
  }

  async handleToolCall(name: string, args: any): Promise<any> {
    switch (name) {
      // Integration Provider Handlers
      case 'create_whitelabel_integration_provider':
        return this.client.createWhiteLabelIntegrationProvider(args as CreateWhiteLabelIntegrationProviderDto);

      case 'list_whitelabel_integration_providers':
        return this.client.listWhiteLabelIntegrationProviders(args);

      // Order Handlers
      case 'list_orders':
        return this.client.listOrders(args);

      case 'get_order_by_id':
        return this.client.getOrderById(args.orderId, args);

      // Order Fulfillment Handlers
      case 'create_order_fulfillment':
        const { orderId, ...fulfillmentData } = args;
        return this.client.createOrderFulfillment(orderId, fulfillmentData as CreateFulfillmentDto);

      case 'list_order_fulfillments':
        return this.client.listOrderFulfillments(args.orderId, args);

      // Transaction Handlers
      case 'list_transactions':
        return this.client.listTransactions(args);

      case 'get_transaction_by_id':
        return this.client.getTransactionById(args.transactionId, args);

      // Subscription Handlers
      case 'list_subscriptions':
        return this.client.listSubscriptions(args);

      case 'get_subscription_by_id':
        return this.client.getSubscriptionById(args.subscriptionId, args);

      // Coupon Handlers
      case 'list_coupons':
        return this.client.listCoupons(args);

      case 'create_coupon':
        return this.client.createCoupon(args as CreateCouponParams);

      case 'update_coupon':
        return this.client.updateCoupon(args as UpdateCouponParams);

      case 'delete_coupon':
        return this.client.deleteCoupon(args as DeleteCouponParams);

      case 'get_coupon':
        return this.client.getCoupon(args);

      // Custom Provider Handlers
      case 'create_custom_provider_integration':
        const { locationId: createLocationId, ...createProviderData } = args;
        return this.client.createCustomProviderIntegration(createLocationId, createProviderData as CreateCustomProviderDto);

      case 'delete_custom_provider_integration':
        return this.client.deleteCustomProviderIntegration(args.locationId);

      case 'get_custom_provider_config':
        return this.client.getCustomProviderConfig(args.locationId);

      case 'create_custom_provider_config':
        const { locationId: configLocationId, ...configData } = args;
        return this.client.createCustomProviderConfig(configLocationId, configData as ConnectCustomProviderConfigDto);

      case 'disconnect_custom_provider_config':
        const { locationId: disconnectLocationId, ...disconnectData } = args;
        return this.client.disconnectCustomProviderConfig(disconnectLocationId, disconnectData as DeleteCustomProviderConfigDto);

      default:
        throw new Error(`Unknown tool: ${name}`);
    }
  }
} 