class Api::IntegrationsController < Api::BaseController
  before_action :find_service
  before_action :find_proxy
  before_action :authorize
  before_action :activate_submenu

  activate_menu :main_menu => :serviceadmin, :sidebar => :integration
  sublayout 'api/service'

  PLUGIN_LANGUAGES = %w(ruby java python nodejs php rest csharp).freeze

  def edit
    @latest_lua = current_account.proxy_logs.first
    @deploying =  ThreeScale::TimedValue.get(deploying_hosted_proxy_key)
    @ever_deployed_hosted = current_account.hosted_proxy_deployed_at.present?
  end

  def settings

  end

  def update
    if @service.using_proxy_pro?
      proxy_pro_update
    elsif current_account.provider_can_use?(:async_apicast_deploy)
      async_update
    elsif @proxy.save_and_deploy(proxy_params)
      flash[:notice] = flash_message(:update_success)
      update_onboarding_mapping_bubble

      if @proxy.send_api_test_request!
        onboarding.bubble_update('api')
        done_step(:api_sandbox_traffic) if ApiClassificationService.test(@proxy.api_backend).real_api?
        return redirect_to action: :edit, anchor: 'proxy'
      end
      render :edit

    else
      attrs = params.fetch(:proxy, {}).fetch(:proxy_rules_attributes,{})
      splitted = attrs.keys.group_by { |key| attrs[key]['_destroy'] == '1' }

      @marked_for_destroy = splitted[true]
      @marked_for_update = splitted[false]

      flash.now[:error] = flash_message(:update_error)
      @api_test_form_error = true

      render :edit
    end
  end

  def update_production
    @proxy.deploy_production
    ThreeScale::TimedValue.set(deploying_hosted_proxy_key, true, 5*60 )
    ThreeScale::Analytics.track(current_user, 'Hosted Proxy deployed')
    flash[:notice] = flash_message(:update_production_success)

    done_step(:apicast_gateway_deployed, final_step=true) if ApiClassificationService.test(@proxy.api_backend).real_api?
    onboarding.bubble_update('deployment')

    redirect_to action: :edit, anchor: 'proxy'
  end

  def update_onpremises_production
    if @proxy.update_attributes(proxy_params)
      flash[:notice] = flash_message(:update_onpremises_production_success)
      redirect_to action: :edit, anchor: 'production'
    else
      render :edit
    end
  end

  def promote_to_production
    if @proxy.deploy_production
      flash[:notice] = flash_message(:promote_to_production_success)
    else
      flash[:error] = flash_message(:promote_to_production_error)
    end
    redirect_to action: :show
  end

  def show
    respond_to do |format|
      format.html do
        @show_presenter = Api::IntegrationsShowPresenter.new(@proxy)
      end

      format.zip do
        onboarding.bubble_update('deployment')

        source = if provider_can_use?(:apicast_per_service)
                   Apicast::UserSource.new(current_user)
                 else
                   Apicast::ProviderSource.new(@service.account)
        end

        generator = Apicast::ZipGenerator.new(source)

        send_file generator.data,
                  type: 'application/zip',
                  disposition: 'attachment',
                  filename: 'proxy_configs.zip'
      end
    end
  end

  protected

  def flash_message(key)
    translate(key, scope: :api_integrations_controller, raise: Rails.env.test?)
  end

  def proxy_pro_update
    if @proxy.update_attributes(proxy_params)
      update_onboarding_mapping_bubble
      onboarding.bubble_update('api')
      flash[:notice] = flash_message(:proxy_pro_update_sucess)
      redirect_to action: :edit, anchor: 'proxy'
    else
      render :edit
    end
  end

  def async_update
    if (@deploy_id = @proxy.save_and_async_deploy(proxy_params, current_user))
      flash.now[:notice] = flash_message(:async_update_success)

      render :edit
    else
      attrs = params.fetch(:proxy, {}).fetch(:proxy_rules_attributes,{})
      splitted = attrs.keys.group_by { |key| attrs[key]['_destroy'] == '1' }

      @marked_for_destroy = splitted[true]
      @marked_for_update = splitted[false]

      flash.now[:error] = flash_message(:async_update_error)
      @api_test_form_error = true

      render :edit
    end
  end

  def find_proxy
    @proxy = @service.proxy
  end

  def authorize
    authorize! :manage, :plans
    authorize! :edit, @service
  end

  def proxy_params
    basic_fields = [
      :auth_app_id, :auth_app_key, :api_backend, :hostname_rewrite, :oauth_login_url,
      :secret_token, :credentials_location, :auth_user_key, :error_status_auth_failed,
      :error_headers_auth_failed, :error_auth_failed, :error_status_auth_missing,
      :error_headers_auth_missing, :error_auth_missing, :error_status_no_match,
      :error_headers_no_match, :error_no_match, :api_test_path,
      proxy_rules_attributes: [:_destroy, :id, :http_method, :pattern, :delta, :metric_id, :redirect_url]
    ]

    if Rails.application.config.three_scale.apicast_custom_url
      basic_fields << :endpoint
      basic_fields << :sandbox_endpoint
    end

    basic_fields << :endpoint if @service.using_proxy_pro? || @service.on_premise?
    params.require(:proxy).permit(*basic_fields)
  end

  def deploying_hosted_proxy_key
    "#{current_account.id}/deploying_hosted"
  end

  def update_onboarding_mapping_bubble
    onboarding.bubble_update('mapping') if proxy_rules_added_for_last_method_metric?
  end

  def proxy_rules_added_for_last_method_metric?
    @proxy.proxy_rules.size > 1
  end
end
