require 'rails_helper'

# This spec was generated by rspec-rails when you ran the scaffold generator.
# It demonstrates how one might use RSpec to test the controller code that
# was generated by Rails when you ran the scaffold generator.
#
# It assumes that the implementation code is generated by the rails scaffold
# generator. If you are using any extension libraries to generate different
# controller code, this generated spec may or may not pass.
#
# It only uses APIs available in rails and/or rspec-rails. There are a number
# of tools you can use to make these specs even more expressive, but we're
# sticking to rails and rspec-rails APIs to keep things simple and stable.

RSpec.describe '/api/rounds', :no_transaction, type: :request do
  include StubRequestHelper

  describe 'GET /index' do
    let!(:round1) { create :round, :previous }
    let!(:round2) { create :round, :current }
    let!(:round3) { create :round, :next }

    let!(:team1) { create :team }
    let!(:team2) { create :team }

    let!(:player1) { create :player, team: team1 }
    let!(:player2) { create :player, team: team2 }

    let!(:fixture1) do
      create(
        :fixture,
        round: round1,
        home_team: team1,
        away_team: team2
      )
    end

    it 'renders a successful response' do
      api.get api_rounds_url

      expect(api.data).to contain_exactly(
        a_hash_including(
          'id' => round1.to_param,
          'name' => round1.name,
          'finished' => true,
          'data_checked' => true,
          'is_previous' => true,
          'is_current' => false,
          'is_next' => false,
        ),
        a_hash_including(
          'id' => round2.to_param,
          'name' => round2.name,
          'finished' => false,
          'data_checked' => false,
          'is_previous' => false,
          'is_current' => true,
          'is_next' => false
        ),
        a_hash_including(
          'id' => round3.to_param,
          'name' => round3.name,
          'finished' => false,
          'data_checked' => false,
          'is_previous' => false,
          'is_current' => false,
          'is_next' => true,
        ),
      )
    end
  end

  describe 'GET /show', :no_transaction do
    let(:first_round) { Round.first }

    before do
      stub_bootstrap_static_request

      Rounds::Populate.call
      Positions::Populate.call
      Teams::Populate.call
      Players::Populate.call

      stub_fixture_request

      Fixtures::Populate.call
    end

    include_examples 'not found', 'round'

    it 'renders a successful response' do
      api.get api_round_url(first_round)

      expect(api.data).to include(
        'id' => first_round.to_param,
        'is_current' => false,
        'is_next' => false,
        'is_previous' => false,
        'finished' => true,
        'data_checked' => true,
        'deadline_time' => '2021-08-13T17:30:00Z',
        'fixtures' => including(
          a_hash_including(
            'kickoff_time' => '2020-09-12T11:30:00Z',
            'minutes' => 90,
            'started' => true,
            'finished' => true,
            'away_team_score' => 3,
            'home_team_score' => 0,
            'home_team' => a_hash_including('short_name' => 'FUL'),
            'away_team' => a_hash_including('short_name' => 'ARS'),
            'stats' => contain_exactly(
              a_hash_including('identifier' => 'own_goals'),
              a_hash_including('identifier' => 'red_cards'),
              a_hash_including('identifier' => 'yellow_cards'),
              a_hash_including('identifier' => 'bonus'),
              a_hash_including('identifier' => 'penalties_saved'),
              a_hash_including('identifier' => 'penalties_missed'),
              a_hash_including('identifier' => 'saves'),
              {
                'away' => [
                  {
                    'value' => 1,
                    'player' => a_hash_including('last_name' => 'Aubameyang'),
                  },
                  {
                    'value' => 1,
                    'player' => a_hash_including('last_name' => 'Lacazette'),
                  },
                  {
                    'value' => 1,
                    'player' => a_hash_including('last_name' => 'Magalhães'),
                  },
                ],
                'home' => [],
                'identifier' => 'goals_scored',
                'display_order' => 1,
              },
              {
                'away' => [
                  {
                    'value' => 3,
                    'player' => a_hash_including('last_name' => 'Borges Da Silva'),
                  },
                ],
                'home' => [],
                'identifier' => 'assists',
                'display_order' => 2,
              },
            ),
          ),
        ),
      )
    end

    it 'caches against the request' do
      api.get api_round_url(first_round)

      expect(api.response).to have_http_status(:success)

      etag = api.response.headers['ETag']
      last_modified = api.response.headers['Last-Modified']

      get_request_with_caching(etag, last_modified)
      expect(api.response).to have_http_status(:not_modified)

      etag = api.response.headers['ETag']
      last_modified = api.response.headers['Last-Modified']

      first_round.update!(updated_at: 10.minutes.from_now)

      get_request_with_caching(etag, last_modified)
      expect(api.response).to have_http_status(:success)

      etag = api.response.headers['ETag']
      last_modified = api.response.headers['Last-Modified']

      first_round.fixtures.first.update!(updated_at: 20.minutes.from_now)

      get_request_with_caching(etag, last_modified)
      expect(api.response).to have_http_status(:success)
    end
  end

  private

  def get_request_with_caching(etag, last_modified)
    api.get api_round_url(first_round),
            headers: {
              'HTTP_IF_NONE_MATCH' => etag,
              'HTTP_IF_MODIFIED_SINCE' => last_modified,
            }
  end
end
