require 'rails_helper'

describe Twitch::TeamMembershipsController do
  include_context 'mocked permissions'

  let(:user) { Twitch::User.new(id: 123, login: 'kappa') }

  describe '#create' do
    let(:permission) { 'manage_twitch_teams' }

    let(:team) do
      Twitch::Team.new(
        id: '1',
        name: 'staff'
      )
    end

    context 'without authorization' do
      include_context 'an unauthorized user'

      before { post :create, params: { team_name: team.name } }

      it_behaves_like 'it redirects the user and displays an error'
    end

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

      let(:channel) { Twitch::User.new(id: 9000, login: 'twitchoffice') }

      let(:params) do
        {
          channel_login: channel.login,
          membership: {
            revenue_revealed: 'true',
            stats_revealed: 'false'
          },
          team_name: team.name
        }
      end

      context 'when the team is not found' do
        before do
          allow(Twitch::Team).to receive(:find_by_name).with(team.name).and_return(nil)

          post :create, params: params
        end

        it_behaves_like 'it redirects the user and displays an error'
      end

      context 'when the team is found' do
        before do
          allow(Twitch::Team).to receive(:find_by_name).with(team.name).and_return(team)
        end

        context 'when the to-be team member is not found by login' do
          before do
            allow(Twitch::User).to receive(:find_by_login).with(channel.login).and_return(nil)

            post :create, params: params
          end

          it 'redirects the user and displays an error' do
            expect(response.code).to eq('302')
            expect(flash[:error]).to include('not found')
          end
        end

        context 'when the to-be team member is suspended' do
          before do
            channel.dmca_violation = true
            allow(Twitch::User).to receive(:find_by_login).with(channel.login).and_return(channel)

            post :create, params: params
          end

          it 'redirects the user and displays an error' do
            expect(response.code).to eq('302')
            expect(flash[:error]).to include('not allowed')
          end
        end

        context 'when the to-be team member is ok!' do
          before do
            allow(Twitch::User).to receive(:find_by_login).with(channel.login).and_return(channel)
          end

          context 'when saving the new membership fails' do
            before do
              allow_any_instance_of(Faraday::Connection).to receive(:run_request).and_return(
                double(
                  success?: false,
                  status: 500,
                  body: {
                    'message' => '🔥!'
                  }
                )
              )
            end

            it 'raises an exception' do
              expect { post :create, params: params }.to raise_error(RuntimeError)
            end
          end

          context 'when saving the new membership succeeds' do
            before do
              allow_any_instance_of(Faraday::Connection)
                .to receive(:run_request) { |_, method| expect(method).to eq(:post) }
                .and_return(
                  double(success?: true)
                )

              post :create, params: params
            end

            it_behaves_like 'it redirects the user and displays a success message'
          end
        end
      end
    end
  end

  describe '#destroy' do
    let(:permission) { 'manage_twitch_teams' }

    let(:membership) do
      Twitch::TeamMembership.new(
        team_id: '1',
        channel_id: user.id.to_s,
        revenue_revealed: false,
        stats_revealed: true
      )
    end

    context 'without authorization' do
      include_context 'an unauthorized user'

      before { delete :destroy, params: { slug: membership.slug } }

      it_behaves_like 'it redirects the user and displays an error'
    end

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

      context 'when the team membership is not found' do
        before do
          allow(Twitch::TeamMembership).to receive(:find_by_slug).with(membership.slug).and_return(nil)

          delete :destroy, params: { slug: membership.slug }
        end

        it_behaves_like 'it redirects the user and displays an error'
      end

      context 'when the team membership is found' do
        before do
          allow(Twitch::TeamMembership).to receive(:find_by_slug).with(membership.slug).and_return(membership)
        end

        context 'when destroying the membership fails' do
          before do
            allow_any_instance_of(Faraday::Connection).to receive(:run_request).and_return(
              double(
                success?: false,
                status: 500
              )
            )
          end

          it 'raises an error' do
            expect { delete :destroy, params: { slug: membership.slug } }.to raise_error(RuntimeError)
          end
        end

        context 'when destroying the membership succeeds' do
          before do
            allow_any_instance_of(Faraday::Connection)
              .to receive(:run_request) { |_, method| expect(method).to eq(:delete) }
              .and_return(
                double(success?: true)
              )

            delete :destroy, params: { slug: membership.slug }
          end

          it 'redirects the user and displays a notice' do
            expect(response.code).to eq('302')
            expect(flash[:notice]).to be_present
          end
        end
      end
    end
  end
end
