require 'test_helper'

class PentestChallengeTest < ActiveSupport::TestCase
  def setup
    create(:active_game, start: 2.hours.ago, stop: 2.hours.from_now)
    @challenge = create(:pentest_challenge,
                  point_value: 500,
                  first_capture_point_bonus: 90,
                  initial_shares: 1000,
                  unsolved_increment_period: 2, # Hours
                  unsolved_increment_points: 250,
                  solved_decrement_period: 2, # Hours
                  solved_decrement_shares: 370,
                  defense_period: 2, # Hours
                  defense_points: 450,
                  flag_count: 0)
    @division = create(:division)
    @offensive_team = create(:team, division: @division)
    @defensive_team = create(:team, division: @division)
    @flag = create(:defense_flag, challenge: @challenge, team: @defensive_team)
  end

  # @flag.get_solved_challenge_for basically just proxies through to the pentest challenge
  # object so we test it here
  test 'get solved challenge for team returns the correct value' do

    assert_nil @flag.get_solved_challenge_for(@offensive_team)
    sc = create(:pentest_solved_challenge, team: @offensive_team, challenge: @challenge)
    assert_equal sc, @flag.reload.get_solved_challenge_for(@offensive_team)
  end

  # @flag.can_be_solved_by basically just proxies through to the pentest challenge
  # object so we test it here
  test 'can be solved by team returns the correct value' do
    assert_equal false, @flag.can_be_solved_by(@defensive_team), 'Team should not be able to solve their own defensive flag'
    assert_equal true, @flag.can_be_solved_by(@offensive_team), 'Teams should be able to solve a different teams flag'
    sc = create(:pentest_solved_challenge, team: @offensive_team, challenge: @challenge)
    assert_equal false, @flag.reload.can_be_solved_by(@offensive_team), 'Offensive team cannot solve another teams flag twice'
  end

  # First parameter to calc_shares is first_solve_time, second is current solve time
  test 'calc shares returns the correct value' do
    # If the first solve is 1 hour ago, the number of shares should decrease by 185
    # based on the challenge definition above, leaving us with 1000 - 185 = 815 shares
    assert_equal 815, @challenge.calc_shares(1.hour.ago, Time.now.utc).round
    # If the first solve is 2 hours ago, the number of shares should decrease by 185
    # based on the challenge definition above, leaving us with 1000 - 370 = 630 shares
    assert_equal 630, @challenge.calc_shares(2.hours.ago, Time.now.utc).round
  end

  # First parameter is start_time, second is first_solve time
  test 'calc point value returns the correct value' do
    # Passing in a 1 hour difference should give us 1 hour of unsolved_increment_points
    # which is worth 125 + the 500 points the challenge is worth.
    assert_equal 625, @challenge.calc_point_value(1.hour.ago, Time.now.utc).round
    # Passing in no difference should give us only the challenges initial point value
    assert_equal 500, @challenge.calc_point_value(Time.now.utc, Time.now.utc).round
  end

  test 'calc defensive points helper returns the correct value' do
    # Passing in 1 hour difference should give us 1 hour of defense_points, which is 225 points
    assert_equal 225, @challenge.calc_defensive_points_helper(1.hour.ago, Time.now.utc).round
    # Pass in no difference shoudl give us no defensive points
    assert_equal 0, @challenge.calc_defensive_points_helper(Time.now.utc, Time.now.utc).round
  end

  test 'pentest next challenge' do
    curr_chall = create_list(:pentest_challenge, 3).last
    create_list(:share_challenge, 3)
    next_chall = create_list(:pentest_challenge, 3).first
    assert_equal next_chall, curr_chall.next_challenge
  end
end
