require "rails_helper"

describe HeadshotCollection do
  describe ".for_project" do
    it "generates a collection for a given project" do
      project = create(:project, 
                       appearance_releases: create_list(:appearance_release, 1),
                       talent_releases: create_list(:talent_release, 1),
                       headshot_collection_uid: "123abc"
                      )

      collection = HeadshotCollection.for_project(project)

      expect(collection).not_to be_nil
      expect(collection).to be_a(HeadshotCollection)
      expect(collection.releasables).to include(project.appearance_releases.first)
      expect(collection.releasables).to include(project.talent_releases.first)
      expect(collection.collection_uid).to eq(project.headshot_collection_uid)
    end

    context "when a release has no headshot photo attachment" do
      it "excludes that release from the headshot collection" do
        project = create(:project, 
                         appearance_releases: build_list(:appearance_release, 1, :without_person_photo),
                         talent_releases: [],
                        )

        collection = HeadshotCollection.for_project(project)
        expect(collection).to be_a(HeadshotCollection)
        expect(collection.releasables).not_to include(project.appearance_releases.first)
      end
    end
  end

  describe "#as_json" do
    it "uses the custom hash format" do
      collection = HeadshotCollection.new "uid", []

      expect(collection.as_json).to eq(collection.to_hash)
    end
  end
  
  describe "#to_hash" do
    it "includes the name of the bucket where the headshots are stored" do
      allow(ENV).to receive(:[]).with("AWS_BUCKET").and_return("test-bucket")

      collection = HeadshotCollection.new("uid", [])
      bucket_name = collection.to_hash[:bucket_name]

      expect(bucket_name).to eq("test-bucket")
    end

    it "includes the collection UID" do
      collection = HeadshotCollection.new("uid", [])
      collection_uid = collection.to_hash[:collection_uid]

      expect(collection_uid).to eq("uid")
    end

    it "forces the collection UID to be a string" do
      collection = HeadshotCollection.new(10, [])
      collection_uid = collection.to_hash[:collection_uid]

      expect(collection_uid).to eq("10")
    end

    it "includes a mapping of IDs to headshot keys" do
      releases = build_releases_with_photo_keys(["123", "456"])
      collection = HeadshotCollection.new("uid", releases)

      mapping = collection.to_hash[:ids_to_images]

      expect(mapping["appearance_release_#{releases.first.id}"]).to include("123")
      expect(mapping["appearance_release_#{releases.last.id}"]).to include("456")
    end

    it "differentiates between release types" do
      releases = [
        build_release_with_photo_key("123", release_type: :appearance_release),
        build_release_with_photo_key("456", release_type: :talent_release),
      ]
      collection = HeadshotCollection.new("uid", releases)

      mapping = collection.to_hash[:ids_to_images]

      expect(mapping["appearance_release_#{releases.first.id}"]).to include("123")
      expect(mapping["talent_release_#{releases.last.id}"]).to include("456")
    end

    context "when collection uid is blank" do
      it "is not included in the hash" do
        releases = []
        collection = HeadshotCollection.new(nil, releases)

        hash = collection.to_hash

        expect(hash.keys).not_to include(:collection_uid)
      end
    end

    context "when there are no releasables" do
      it "includes a blank hash value for the ids_to_images key" do
        releases = []
        collection = HeadshotCollection.new(nil, releases)

        hash = collection.to_hash

        expect(hash.keys).to include(:ids_to_images)
        expect(hash[:ids_to_images]).to eq(Hash.new)
      end
    end
  end

  private

  def build_release_with_photo_key(key, release_type: :appearance_release)
      build_stubbed(release_type).tap do |release|
        photo = double(key: key)
        allow(release).to receive(:photo).and_return(photo)
      end
  end

  def build_releases_with_photo_keys(keys)
    keys.map { |key| build_release_with_photo_key(key) }
  end
end
