# frozen_string_literal: true

require_relative 'bootstrap'
require 'minitest/autorun'
require 'pry'

class WeightedRedirectTest < Minitest::Test
  @@protocols = %i[http https].freeze
  @@twitch = @@protocols.map { |protocol| [protocol, Twitch::Web.create(protocol)] }.to_h

  def teardown
    sleep 0.5
  end

  def expected_weight(auth = false)
    return DEFAULT_REDIRECT_CRITERIA unless auth
    AUTHENITCATED_REDIRECT_CRITERIA
  end

  def bucket(id)
    id % 100
  end

  def bucket_in_redirect?(id, auth: false)
    bucket(id) < (expected_weight(auth) * 100)
  end

  # def test_no_weighted_redirect_logged_in
  #   200.times do
  #     res = @@twitch[:https].get('/') do |req|
  #       req.headers['Cookie'] = 'api_token=1234'
  #     end
  #     assert_equal 200, res.status
  #     sleep 0.5
  #   end
  # end

  # def test_weighted_redirect_anonymous
  #   count = { redirected: 0, not_redirected: 0, total: 0 }
  #   WRT_ITERATIONS.times do
  #     res = @@twitch[:https].get('/') do |req|
  #       binding.pry
  #       # req.headers['Cookie'] = ''
  #     end
  #     assert_includes [200, 302], res.status, "Unexpected HTTP status code: #{res.status} (#{res.headers['location']})"
  #     assert_includes res.headers['set-cookie'], 'twilight_beta_id', 'Response cookie is missing twilight_beta_id'
  #     binding.pry
  #     if res.status == 302
  #       count[:redirected] += 1
  #       count[:total] += 1
  #       assert_equal res.headers['location'], 'https://go.twitch.tv/'
  #     elsif res.status == 200
  #       count[:not_redirected] += 1
  #       count[:total] += 1
  #     end
  #     sleep 0.5
  #   end
  #   redirect_rate = (count[:redirected].to_f / count[:total]).round(2)
  #   expected_delta = expected_weight / 2 < MAX_DELTA ? (expected_weight / 2).round(3) : MAX_DELTA
  #   assert_in_delta redirect_rate, expected_weight, expected_delta,
  #     "Redirect rate of #{redirect_rate} is not within #{expected_delta} of expected rate #{expected_weight}"
  # end

  # def test_weighted_redirect_logged_in
  #   count = { redirected: 0, not_redirected: 0, total: 0 }
  #   WRT_ITERATIONS.times do
  #     res = @@twitch[:https].get('/') do |req|
  #       binding.pry
  #       # req.headers['Cookie'] = ''
  #     end
  #     assert_includes [200, 302], res.status, "Unexpected HTTP status code: #{res.status} (#{res.headers['location']})"
  #     assert_includes res.headers['set-cookie'], 'twilight_beta_id', 'Response cookie is missing twilight_beta_id'
  #     binding.pry
  #     if res.status == 302
  #       count[:redirected] += 1
  #       count[:total] += 1
  #       assert_equal res.headers['location'], 'https://go.twitch.tv/'
  #     elsif res.status == 200
  #       count[:not_redirected] += 1
  #       count[:total] += 1
  #     end
  #     sleep 0.5
  #   end
  #   redirect_rate = (count[:redirected].to_f / count[:total]).round(2)
  #   expected_delta = expected_weight / 2 < MAX_DELTA ? (expected_weight / 2).round(3) : MAX_DELTA
  #   assert_in_delta redirect_rate, expected_weight, expected_delta,
  #     "Redirect rate of #{redirect_rate} is not within #{expected_delta} of expected rate #{expected_weight}"
  # end

  def test_force_redirect_with_device_id_anonymous
    count = { redirected: 0, not_redirected: 0, total: 0 }
    (1..100).each do |i|
      res = @@twitch[:https].get('/') do |req|
        req.headers['Cookie'] = "twilight_beta_id=#{i}"
      end

      assert_includes [200, 302], res.status, "Unexpected HTTP status code: #{res.status} (#{res.headers['location']})"

      if res.status == 302
        assert bucket_in_redirect?(i), "Expected twilight_beta_id=#{i}, bucket #{bucket(i)} to not redirect (#{i} < #{expected_weight * 100})"
        assert_equal res.headers['location'], 'https://go.twitch.tv/'
        count[:redirected] += 1
        count[:total] += 1
      elsif res.status == 200
        assert !bucket_in_redirect?(i), "Expected twilight_beta_id=#{i}, bucket #{bucket(i)} to redirect (#{i} >= #{expected_weight * 100})"
        count[:not_redirected] += 1
        count[:total] += 1
      end
      sleep 0.5
    end
    redirect_rate = (count[:redirected].to_f / count[:total]).round(2)
    assert_equal expected_weight, redirect_rate,
      "Redirect rate of #{redirect_rate} is not equal to expected rate #{expected_weight}"
  end

  def test_force_redirect_with_device_id_logged_in
    count = { redirected: 0, not_redirected: 0, total: 0 }
    (1..100).each do |i|
      res = @@twitch[:https].get('/') do |req|
        req.headers['Cookie'] = "api_token=1234; twilight_beta_id=#{i}"
      end

      assert_includes [200, 302], res.status, "Unexpected HTTP status code: #{res.status} (#{res.headers['location']})"

      if res.status == 302
        assert bucket_in_redirect?(i, auth: true), "Expected twilight_beta_id=#{i}, bucket #{bucket(i)} to not redirect (#{i} < #{expected_weight(true) * 100})"
        assert_equal res.headers['location'], 'https://go.twitch.tv/'
        count[:redirected] += 1
        count[:total] += 1
      elsif res.status == 200
        assert !bucket_in_redirect?(i, auth: true), "Expected twilight_beta_id=#{i}, bucket #{bucket(i)} to redirect (#{i} >= #{expected_weight(true) * 100})"
        count[:not_redirected] += 1
        count[:total] += 1
      end
      sleep 0.5
    end
    redirect_rate = (count[:redirected].to_f / count[:total]).round(2)
    assert_equal expected_weight(true), redirect_rate,
      "Redirect rate of #{redirect_rate} is not equal to expected rate #{expected_weight(true)}"
  end
end
