require "rails_helper"

RSpec.describe Subscriptions::TicketProductsController do
  include_context "mocked permissions"

  let(:permission) { "ticket_products" }

  describe "#index" do
    describe "permissions" do
      context "a user with appropriate permissions" do
        include_context "an authorized user"
        include_context 'it creates any tracking call'

        before do
          allow(Subscriptions::TicketProduct).to receive(:search).and_return([])

          get :index
        end

        it_behaves_like "it returns a success response"
      end

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

        before do
          get :index
        end

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

  describe "#show" do
    let(:ticket_product_id) { 12345 }
    let(:emote_group_id) { "56789" }
    let(:emote) do
      {
        "group_id" => emote_group_id,
      }
    end

    let(:ticket_product) { double(persisted?: true, emoticon_set: {"id" => emote_group_id})}

    describe "permissions" do
      context "a user with appropriate permissions" do
        include_context "an authorized user"

        before do
          allow(Subscriptions::TicketProduct).to receive(:find).once
            .with(ticket_product_id.to_s).and_return(ticket_product)
          allow(Mako::Emote).to receive(:get_emoticons_by_group).once
            .with(emote_group_id).and_return([emote])

          get :show, params: { id: ticket_product_id }
        end

        it_behaves_like "it returns a success response"
      end

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

        before do
          get :show, params: { id: ticket_product_id }
        end

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

  describe "#create_additional_tiers" do
    context "a user with appropriate permissions" do
      include_context "an authorized user"

      # params
      let(:ticket_product_id) { "12345" }
      let(:tier3_product_id) { "12347" }
      let(:channel_id) { "321" }
      let(:params) do
        {
          ticket_product_id: ticket_product_id,
          channel_id: channel_id,
        }
      end

      # verifying doubles
      let(:success) do
        instance_double("ActionResource::Response", success?: true, body: { "message" => "created products 12346 #{tier3_product_id}"})
      end
      let(:failure) do
        instance_double("ActionResource::Response", success?: false)
      end

      # set up relationships
      before(:each) do
        allow(Subscriptions::TicketProduct).to receive(:find)
          .once
          .with(ticket_product_id).and_return(double(id: ticket_product_id, channel_id: channel_id))
      end

      let(:call) do
        post :create_additional_tiers, params: params
      end

      context "successfully creates additional tiers" do
        before do
          allow(Subscriptions::TicketProduct).to receive(:create_additional_tiers).once.with(ticket_product_id).and_return(success)
          allow(Substwirp::AdminSubscription).to receive(:grant_admin_subscription).once.with(channel_id, tier3_product_id)
          call
        end

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

      context "successfully creates additional tiers but fails grant admin sub" do
        before do
          allow(Subscriptions::TicketProduct).to receive(:create_additional_tiers).once.with(ticket_product_id).and_return(success)
          allow(Substwirp::AdminSubscription).to receive(:grant_admin_subscription).once.with(channel_id, tier3_product_id).and_raise("failure")
          call
        end

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

  describe "#grant_admin_sub" do
    context "a user with appropriate permissions" do
      include_context "an authorized user"

      # params
      let(:ticket_product_id) { "12345" }
      let(:user) { 'test_user' }
      let(:user_id) { 123 }
      let(:params) do
        {
          ticket_product_id: ticket_product_id,
          subscriptions_ticket_product: {
            subber: user
          }
        }
      end

      # verifying doubles
      let(:ticket_product) do
        instance_double("Subscriptions::TicketProduct")
      end
      let(:success) do
        instance_double("ActionResource::Response", success?: true)
      end
      let(:failure) do
        instance_double("ActionResource::Response", success?: false)
      end

      # set up relationships
      before(:each) do
        allow(Subscriptions::TicketProduct).to receive(:find)
          .once
          .with(ticket_product_id).and_return(ticket_product)
      end

      # dry
      let(:call) do
        post :grant_admin_sub, params: params
      end

      context "successfully grants an admin channel sub" do
        include_context "it creates any tracking call"

        before do
          expect(Twitch::User).to receive(:find_by_login).once.with(user).and_return(double(id: user_id))
          allow(Substwirp::AdminSubscription).to receive(:grant_admin_subscription).once.with(user_id.to_s, ticket_product_id)
          call
        end

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

      context "fails to find user id" do

        before do
          expect(Twitch::User).to receive(:find_by_login).once.with(user).and_return(nil)
          call
        end

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

      context "fails to grant an admin sub" do

        before do
          expect(Twitch::User).to receive(:find_by_login).once.with(user).and_return(double(id: user_id))
          allow(Substwirp::AdminSubscription).to receive(:grant_admin_subscription).once.with(user_id.to_s, ticket_product_id).and_raise("failure")
          call
        end

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