require "rails_helper"

describe GenerateContractsZipJob do
  let(:project) { create(:project) }
  let(:download) { create(:download, project: project) }
  let(:contract_template) { create(:contract_template, :project) }

  before do
    create(:appearance_release_with_contract_template, :native, project: project, person_name: "John Doe")
    create(:appearance_release_with_contract_template, :non_native, project: project)
    dir = Rails.root.join("spec", "fixtures", "files")
    files = ["contract.pdf", "AppearanceRelease.pdf"]
    # Attachments in the test environment do not persist to cloud storage
    # Therefore we want to stub calls to `open` with a cloud storage URL 
    allow_any_instance_of(ReleaseContractCollectionService).to receive(:open).and_return(StringIO.new("file data"))
    allow_any_instance_of(ReleaseContractCollectionService).to receive(:build).and_yield(dir, files)
  end

  describe ".perform_later" do
    it "enqueues a background job for generating zip file" do
      expect {
        GenerateContractsZipJob.perform_later(project, download, "AppearanceRelease", project.appearance_releases.ids)
      }.to have_enqueued_job
    end
  end

  describe ".perform_now" do
    it "updates a download record and creates attachment for it" do
      GenerateContractsZipJob.perform_now(project, download, "AppearanceRelease", project.appearance_releases.ids)

      expect(download.project).to eq project
      expect(download.release_type).to eq "AppearanceRelease"
      expect(download.name).to eq "my-video-project_appearance-releases"
      expect(download.status).to eq "success"
      expect(download.file).to be_attached
    end

    context "When there are errors" do
      let(:error) { StandardError.new("Contracts or contract templates not found.") }

      before do
        allow(ProjectsChannel).to receive(:broadcast_download_generation_update).with(download, I18n.t("contract_downloads.download.failure"))
        allow_any_instance_of(ReleaseContractCollectionService).to receive(:build).and_raise(StandardError, "Contracts or contract templates not found")
      end
  
      it "updates status to 'failure' and sends user a notification" do
        GenerateContractsZipJob.perform_now(project, download, "AppearanceRelease", project.appearance_releases.ids)
  
        expect(download.status).to eq "failure"
        expect(ProjectsChannel).to have_received(:broadcast_download_generation_update).with(download, I18n.t("contract_downloads.download.failure"))
      end
    end
  end

  after do
    # Delete the file created in fixture.
    # Or the tests will fail on next run due to already existing files in existing zip.
    path = Rails.root.join("spec", "fixtures", "files")
    File.delete("#{path}/my-video-project_appearance-releases.zip") if File.exists? "#{path}/my-video-project_appearance-releases.zip"
  end
end
