# frozen_string_literal: true

module ErpIntegration
  # Use the `Configuration` class to configure the ERP Integration gem. Use
  # an initializer in your project configure the ERP Integration gem.
  #
  # @example
  #   ```ruby
  #     # config/initializers/erp_integration.rb
  #     ErpIntegration.configure do |config|
  #       config.fulfil_api_key = "..."
  #     end
  #   ```
  class Configuration
    # The `fulfil_api_key` is used by the `FulfilClient` to authorize the
    # requests to the Fulfil API endpoints.
    # @return [String] The API key for Fulfil.
    attr_accessor :fulfil_api_key

    # The `fulfil_merchant_id` is used by the `FulfilClient` to connect to
    # the right Fulfil API endpoints.
    # @return [String] The merchant ID for Fulfil.
    attr_accessor :fulfil_merchant_id

    # Allows configuring an adapter for the `BillOfMaterial` resource. When
    # none is configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the bill_of_material.
    attr_writer :bill_of_material_adapter

    # Allows configuring an adapter for the `BillOfMaterialInput` resource. When
    # none is configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the Bill of Material's input.
    attr_writer :bill_of_material_input_adapter

    # Allows configuring an adapter for the `BillOfMaterialOutput` resource. When
    # none is configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the bill_of_material.
    attr_writer :bill_of_material_output_adapter

    # Allows configuring an adapter for the `Country` resource. When
    # none is configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the country.
    attr_writer :country_adapter

    # Allows configuring an adapter for the `ChannelListing` resource. When
    # none is configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the channel_listing.
    attr_writer :channel_listing_adapter

    # Allows configuring an adapter for the `CustomerShipment` resource. When
    # none is configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the customer shipment.
    attr_writer :customer_shipment_adapter

    # Allows configuring an adapter for the `CustomerShipmentReturn` resource. When
    # none is configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the customer shipment.
    attr_writer :customer_shipment_return_adapter

    # Allows configuring an adapter for the `InternalShipment` resource.
    # When none is configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the internal shipment.
    attr_writer :internal_shipment_adapter

    # Allows configuring an adapter for the `Location` resource. When
    # none is configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the location.
    attr_writer :location_adapter

    # Allows configuring an adapter for the `Product` resource. When none is
    # configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the products.
    attr_writer :product_adapter

    # Allows configuring an adapter for the `ProductCategory` resource. When none is
    # configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the product category.
    attr_writer :product_category_adapter

    # Allows configuring an adapter for the `ProductTemplate` resource. When none is
    # configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the product templates.
    attr_writer :product_template_adapter

    # Allows configuring an adapter for the `ProductionOrder` resource. When
    # none is configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the production_order.
    attr_writer :production_order_adapter

    # Allows configuring an adapter for the `PurchaseOrder` resource. When none is
    # configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the purchase orders.
    attr_writer :purchase_order_adapter

    # Allows configuring an adapter for the `PurchaseOrderLine` resource. When
    # none is configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the purchase order lines.
    attr_writer :purchase_order_line_adapter

    # Allows configuring an adapter for the `PurchaseRequest` resource. When
    # none is configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the purchase request.
    attr_writer :purchase_request_adapter

    # Allows configuring an adapter for the `SalesOrder` resource. When none is
    # configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the sales orders
    attr_writer :sales_order_adapter

    # Allows configuring an adapter for the `SalesOrderLine` resource. When none is
    # configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the order lines.
    attr_writer :sales_order_line_adapter

    # Allows configuring an adapter for the `SalesReturnReason` resource. When none is
    # configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the order lines.
    attr_writer :sales_return_reason_adapter

    # Allows configuring an adapter for the `SupplierShipment` resource. When
    # none is configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the supplier shipment.
    attr_writer :supplier_shipment_adapter

    # Allows configuring an adapter for the `StockBinTransfer` resource. When
    # none is configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the stock bin transfer.
    attr_writer :stock_bin_transfer_adapter

    # Allows configuring an adapter for the `StockMove` resource. When
    # none is configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the stock move.
    attr_writer :stock_move_adapter

    # Allows configuring an adapter for the `Task` resource. When
    # none is configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the task.
    attr_writer :task_adapter

    # Allows configuring an adapter for the `TrackingNumber` resource. When
    # none is configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the tracking number.
    attr_writer :tracking_number_adapter

    # Allows configuring an adapter for the `GiftCard` resource. When
    # none is configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the tracking number.
    attr_writer :gift_card_adapter

    # Allows configuring an adapter for the `SaleLineOption` resource. When
    # none is configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the tracking number.
    attr_writer :sales_line_option_adapter

    # Allows configuring an adapter for the `ProductOption` resource. When
    # none is configured, it will default to Fulfil.
    # @return [Symbol] The configured adapter for the tracking number.
    attr_writer :product_option_adapter

    # Logger that will be used for HTTP operations on Client
    # @return [Logger] The configured logger
    attr_accessor :logger

    def initialize(**options)
      options.each_pair do |key, value|
        public_send("#{key}=", value) if respond_to?("#{key}=")
      end
    end

    def carrier_adapter
      @carrier_adapter || :fulfil
    end

    def carrier_service_adapter
      @carrier_service_adapter || :fulfil
    end

    def bill_of_material_adapter
      @bill_of_material_adapter || :fulfil
    end

    def bill_of_material_input_adapter
      @bill_of_material_input_adapter || :fulfil
    end

    def bill_of_material_output_adapter
      @bill_of_material_output_adapter || :fulfil
    end

    def box_type_adapter
      @box_type_adapter || :fulfil
    end

    def country_adapter
      @country_adapter || :fulfil
    end

    def channel_listing_adapter
      @channel_listing_adapter || :fulfil
    end

    def customer_shipment_adapter
      @customer_shipment_adapter || :fulfil
    end

    def customer_shipment_return_adapter
      @customer_shipment_return_adapter || :fulfil
    end

    def internal_shipment_adapter
      @internal_shipment_adapter || :fulfil
    end

    def location_adapter
      @location_adapter || :fulfil
    end

    def product_adapter
      @product_adapter || :fulfil
    end

    def product_category_adapter
      @product_category_adapter || :fulfil
    end

    def product_template_adapter
      @product_template_adapter || :fulfil
    end

    def production_order_adapter
      @production_order_adapter || :fulfil
    end

    def purchase_order_adapter
      @purchase_order_adapter || :fulfil
    end

    def purchase_order_line_adapter
      @purchase_order_line_adapter || :fulfil
    end

    def purchase_request_adapter
      @purchase_request_adapter || :fulfil
    end

    def sales_order_line_adapter
      @sales_order_line_adapter || :fulfil
    end

    def sales_order_adapter
      @sales_order_adapter || :fulfil
    end

    def sales_return_reason_adapter
      @sales_return_reason_adapter || :fulfil
    end

    def supplier_shipment_adapter
      @supplier_shipment_adapter || :fulfil
    end

    def stock_bin_transfer_adapter
      @stock_bin_transfer_adapter || :fulfil
    end

    def stock_move_adapter
      @stock_move_adapter || :fulfil
    end

    def task_adapter
      @task_adapter || :fulfil
    end

    def tracking_number_adapter
      @tracking_number_adapter || :fulfil
    end

    def webhook_adapter
      @webhook_adapter || :fulfil
    end

    def gift_card_adapter
      @gift_card_adapter || :fulfil
    end

    def sales_line_option_adapter
      @sales_line_option_adapter || :fulfil
    end

    def product_option_adapter
      @product_option_adapter || :fulfil
    end
  end

  # Returns ERP Integration's configuration.
  # @return [ErpIntegration::Configuration] ERP Integration's configuration
  def self.config
    @config ||= Configuration.new
  end

  # Allows setting a new configuration for the ERP Integration gem.
  # @return [ErpIntegration::Configuration] ERP Integration's new configuration
  def self.config=(configuration)
    raise BadConfiguration unless configuration.is_a?(Configuration)

    @config = configuration
  end

  # Allows modifying ERP Integration's configuration.
  #
  # @example
  #   ErpIntegration.configure do |config|
  #     config.some_api_key = "..."
  #   end
  #
  def self.configure
    yield(config)
  end
end