require "rails_helper"

RSpec.describe ContractsController, type: :controller do
  let(:current_user) { create(:user) }

  before do
    sign_in current_user
  end

  shared_examples "a contracts controller" do
    describe "#show" do
      context "for a native release" do
        it "responds with a PDF contract generated dynamically" do
          pdf_body = Tempfile.new
          allow_any_instance_of(Contract).to receive(:to_pdf).and_return(pdf_body)

          get :show, params: { format: :pdf, "#{native_releasable.model_name.singular}_id" => native_releasable }

          expect(response).to be_successful
          expect(content_type).to eq("application/pdf")
          expect(content_disposition).to include("inline")
        end
      end

      context "for a non-native release" do
        it "responds with the attached contract" do
          contract = double(:contract, service_url: "http://example.org/contract.pdf")
          allow_any_instance_of(non_native_releasable.class).to receive(:contract).and_return(contract)

          get :show, params: { format: :pdf, "#{non_native_releasable.model_name.singular}_id" => non_native_releasable }

          expect(response).to be_redirect
          expect(response).to redirect_to("http://example.org/contract.pdf")
        end
      end
    end
  end

  context "for appearance releases" do
    let(:native_releasable) { create(:appearance_release_with_contract_template, :native) }
    let(:non_native_releasable) { create(:appearance_release_with_contract_template, :non_native) }

    it_behaves_like "a contracts controller"
  end

  context "for location releases" do
    let(:native_releasable) { create(:location_release_with_contract_template, :native) }
    let(:non_native_releasable) { create(:location_release_with_contract_template, :non_native) }

    it_behaves_like "a contracts controller"
  end

  context "for material releases" do
    let(:native_releasable) { create(:material_release_with_contract_template, :native) }
    let(:non_native_releasable) { create(:material_release_with_contract_template, :non_native) }

    it_behaves_like "a contracts controller"
  end

  context "for talent releases" do
    let(:native_releasable) { create(:talent_release_with_contract_template, :native) }
    let(:non_native_releasable) { create(:talent_release_with_contract_template, :non_native) }

    it_behaves_like "a contracts controller"
  end

  context "for medical releases" do
    let(:native_releasable) { create(:medical_release_with_contract_template, :native) }
    let(:non_native_releasable) { create(:medical_release_with_contract_template, :non_native) }

    describe "#show when user is account manager" do
      it_behaves_like "a contracts controller"
    end

    shared_examples "a medical contracts controller for non-authorized users" do
      describe "#show" do
        context "for a native release" do
          it "responds with not authorized error" do
            pdf_body = Tempfile.new
            allow_any_instance_of(Contract).to receive(:to_pdf).and_return(pdf_body)

            expect {
              get :show, params: { format: :pdf, "#{native_releasable.model_name.singular}_id" => native_releasable }
            }.to raise_exception(Pundit::NotAuthorizedError)
          end
        end

        context "for a non-native release" do
          it "responds with the attached contract" do
            contract = double(:contract, service_url: "http://example.org/contract.pdf")
            allow_any_instance_of(non_native_releasable.class).to receive(:contract).and_return(contract)

            expect {
              get :show, params: { format: :pdf, "#{non_native_releasable.model_name.singular}_id" => non_native_releasable }
            }.to raise_exception(Pundit::NotAuthorizedError)
          end
        end
      end
    end

    describe "#show when user is project manager" do
      let(:manager_user) { create(:user, :manager) }
      before do
        sign_in manager_user
      end
      it_behaves_like "a medical contracts controller for non-authorized users"
    end

    describe "#show when user is associate" do
      let(:associate_user) { create(:user, :associate) }
      before do
        sign_in associate_user
      end
      it_behaves_like "a medical contracts controller for non-authorized users"
    end
  end
end
