require 'test_helper'

class Logic::RollingUpdatesTest < ActiveSupport::TestCase

  setup do
    Logic::RollingUpdates.stubs(:enabled? => true)
    System::ErrorReporting.expects(:report_error).never
  end

  def test_forum
    account = FactoryGirl.build_stubbed(:simple_account)

    Logic::RollingUpdates::Features::Yaml.stubs(:config).returns({ forum: true })
    assert account.provider_can_use?(:forum)

    Logic::RollingUpdates::Features::Yaml.stubs(:config).returns({ forum: false })
    refute account.provider_can_use?(:forum)
  end

  def test_cms_api
    account = FactoryGirl.build_stubbed(:simple_account)

    Logic::RollingUpdates::Provider.stub_const(:THREESCALERS, [account.id]) do
      assert account.provider_can_use?(:cms_api)
      assert account.provider_can_use?('cms_api')
    end
  end

  def test_feature
    assert Logic::RollingUpdates.feature(:service_permissions)

    assert_raise Logic::RollingUpdates::UnknownFeatureError do
      Logic::RollingUpdates.feature(:unknown_feature)
    end
  end

  def test_enterprise
    account = FactoryGirl.build_stubbed(:simple_account)
    plan    = FactoryGirl.build_stubbed(:simple_application_plan, system_name: 'alex')

    account.expects(:bought_plan).returns(plan).at_least_once
    account.expects(:has_bought_cinstance?).returns(true).at_least_once

    refute account.provider_can_use?(:service_permissions)

    plan.system_name = 'superplan_enterprise_superplan'

    assert account.provider_can_use?(:service_permissions)
  end

  test "Provider: provider_can_use? returns false if you're not in the list" do
    provider = Account.new
    refute provider.provider_can_use?(:instant_bill_plan_change)
  end


  test "Provider: provider_can_use? raise error for unkown features" do
    Rails.configuration.three_scale.rolling_updates.stubs(raise_error_unknown_features: true)

    provider = Account.new

    assert_raise Logic::RollingUpdates::UnknownFeatureError  do
      provider.provider_can_use?(:foobar)
    end
  end

  test "Provider: provider_can_use? return false for unkown features" do
    Rails.configuration.three_scale.rolling_updates.stubs(raise_error_unknown_features: false)
    System::ErrorReporting.expects(:report_error).never

    provider = Account.new
    refute provider.provider_can_use?(:foobar)
  end


  test "Controller: provider_can_use? return true if username is 3scaleadmin" do
    controller_instance = mocked_controller

    user = User.new(username: "3scaleadmin")
    controller_instance.expects(:current_user).returns(user).once

    assert controller_instance.send(:provider_can_use?, :whathever)
  end

  test "Controller: provider_can_use? delegate to current_account" do
    controller_instance = mocked_controller

    user = User.new
    controller_instance.expects(:current_user).returns(user).once

    provider = Account.new
    provider.expects(:provider_can_use?).with(:whathever)
    controller_instance.expects(:current_account).returns(provider).once

    controller_instance.send(:provider_can_use?, :whathever)
  end

  test 'provider can use duplicate_user_key feature' do
    Logic::RollingUpdates::Provider.stub_const(:DUPLICATE_USER_KEY, [1, 3]) do
      provider_1, provider_2 = Account.new, Account.new

      provider_1.stubs(:id).returns(1)
      provider_2.stubs(:id).returns(2)

      assert provider_1.provider_can_use?(:duplicate_user_key)
      refute provider_2.provider_can_use?(:duplicate_user_key)
    end
  end


  test 'provider_can_use? with features defined on yaml config' do
    Logic::RollingUpdates::Features::Yaml.stubs(:config).returns(
        {old_charts: true, cubert_request_logs: false}
    )

    provider = Account.new

    assert provider.provider_can_use?(:old_charts)
    refute provider.provider_can_use?(:cubert_request_logs)
  end

  test 'provider_can_use? raises error for unknown yaml config' do
    Logic::RollingUpdates::Features::Yaml.stubs(:config).returns({old_charts: 'foo'})

    provider = Account.new

    assert_raise Logic::RollingUpdates::UnknownFeatureConfigError  do
      provider.provider_can_use?(:old_charts)
    end
  end

  class NewFeature < Logic::RollingUpdates::Features::Base
    def missing_config
      true
    end
  end

  test 'custom feature configuration' do
    Logic::RollingUpdates::Features::Base.any_instance.stubs(:yaml_config).returns({custom_feature: nil})

    provider = Account.new

    assert NewFeature.new(provider).enabled?, true
  end

  test 'when there is no yml config it should call feature missing_config' do
    Rails.configuration.three_scale.rolling_updates.stubs(features: nil)

    provider = Account.new

    NewFeature.any_instance.expects(:missing_config).returns(true).at_least_once
    assert NewFeature.new(provider).enabled?, true
  end

  test 'async apicast deploy' do
    provider = Account.new

    refute provider.rolling_update(:async_apicast_deploy).missing_config
  end

  test 'require cc on signup' do
    provider = Account.new

    refute provider.rolling_update(:require_cc_on_signup).missing_config
  end

  test 'old charts' do
    provider = Account.new

    refute provider.rolling_update(:old_charts).missing_config
  end

  private

  def mocked_controller
    controller_class = Class.new do
      def self.helper_method(*); end
      include Logic::RollingUpdates::Controller
    end

    controller_class.new
  end
end
