# frozen_string_literal: true

require 'rails_helper'

RSpec.describe Staff::ActivityController do
  include_context 'mocked permissions'

  let(:permission) { 'staff_management' }
  let(:test_user_id) { '123' }
  let(:test_twitch_user) { Twitch::User.new(id: test_user_id) }
  let(:log) { { rails_params: { param_key: 'param_value' } } }

  describe 'index' do
    let(:action) { :index }
    let(:member_id) { 'my-member-id' }
    let(:params) { { member_id: member_id } }
    let(:activity_logs) { { items: [log] } }
    let(:activity_logs_params) { {} }
    let(:query_options) { ActionController::Parameters.new('member_id' => member_id) }

    shared_examples_for 'it loads activity logs' do
      it_behaves_like 'it returns a success response'

      it 'sets member' do
        expect(@controller.view_assigns['member']).to eq(member)
      end

      it 'sets logs' do
        expect(@controller.view_assigns['logs']).to eq(activity_logs[:items])
      end

      it 'sets rails_params_pretty' do
        logs = @controller.view_assigns['logs']
        pretty_params = JSON.parse(logs[0][:rails_params_pretty])
                            .each_with_object({}) do |(k, v), m|
          m[k.to_sym] = v
        end
        expect(pretty_params).to eq(log[:rails_params])
      end

      context 'if next is returned' do
        let(:activity_logs) do
          { items: [log], next: { my: 'next' } }
        end

        it 'sets next_params' do
          expect(@controller.view_assigns['next_params']).to eq(query_options
            .merge('continue' => JSON.generate(activity_logs[:next]))
            .permit(:search, :member_id, :continue))
        end
      end

      context 'if continue is sent' do
        let(:params) do
          {
          member_id: member_id,
          continue: JSON.generate({
            user_id: member_id,
            access_date: '08/09/2010'
          })
        }
        end
        let(:activity_logs_params) do
          { continue: {
          user_id: member_id,
          access_date: Time.new(2010, 9, 8)
        }}
        end

        it_behaves_like 'it returns a success response'
      end

      context 'if text_query is sent' do
        let(:text_query) { 'my-text-query' }
        let(:params) do
          {
          member_id: member_id,
          search: { text_query: text_query }
        }
        end
        let(:activity_logs_params) { { text_query: text_query } }
        let(:query_options) do
          ActionController::Parameters.new(
            'member_id' => member_id,
            'search' => { 'text_query' => text_query }
          )
        end

        it_behaves_like 'it returns a success response'

        context 'if next is returned' do
          let(:activity_logs) do
            { items: [log], next: { my: 'next' } }
          end

          it 'sets next_params' do
            expect(@controller.view_assigns['next_params']).to eq(query_options
              .merge('continue' => JSON.generate(activity_logs[:next]))
              .permit(:search, :member_id, :continue))
          end
        end
      end

      context 'if date_filters are sent' do
        let(:date) { Time.new(2018, 1, 2) }
        let(:date_serialized) { '01/02/2018' }

        [:before_date, :after_date].each do |filt|
          context "#{filt} sent" do
            let(:params) do
              {
              member_id: member_id,
              search: { filt.to_s => date_serialized }
            }
            end
            let(:activity_logs_params) { { filt => date } }

            it_behaves_like 'it returns a success response'
          end
        end
      end
    end

    context 'with permissions' do
      include_context 'an authorized user'

      before(:each) do
        allow(member).to receive(:activity_logs)
          .with(activity_logs_params)
          .and_return(activity_logs)

        allow(Staff::Member).to receive(:find)
          .with(member_id)
          .and_return(member)

        get action, params: params
      end

      context 'if user is found' do
        let(:member) { Staff::Member.from_attributes(id: member_id) }

        it_behaves_like 'it loads activity logs'
      end

      context 'if user is not found' do
        let(:member) { Staff::Member.from_errors(['not found']) }

        it_behaves_like 'it loads activity logs'

        it 'flashes an error' do
          expect(flash[:error]).to be_present
          expect(flash[:warning]).to be_present
        end
      end
    end

    context 'a user without appropriate permissions' do
      include_context 'an unauthorized user'

      it 'redirects the user and displays an error' do
        get action, params: { member_id: member_id }
      end
    end
  end
end
