# frozen_string_literal: true

require 'rails_helper'
require 'yaml'

RSpec.describe BuildKbartJob, type: :job do
  let(:doc_a) do
    SolrDocument.new(id: "aaaaaaaaa",
                     has_model_ssim: "Monograph",
                     title_tesim: ["A Book _Italic_"],
                     creator_tesim: ["Adams, Firstname"],
                     isbn_tesim: ["A123456789 (hardcover)", "A987654321 (ebook)"],
                     doi_ssim: "10.3998/mpub.A",
                     publisher_tesim: ["A Press"],
                     visibility_ssi: "open",
                     date_published_dtsim: ["2023-03-30T15:04:53Z"],
                     date_created_tesim: ["1999"],
                     products_lsim: [product.id])
  end

  let(:doc_b) do
    SolrDocument.new(id: 'bbbbbbbbb',
                     has_model_ssim: "Monograph",
                     title_tesim: ["B Book _Italic_"],
                     creator_tesim: ["Brock, Firstname"],
                     isbn_tesim: ["B123456789 (hardcover)", "B987654321 (ebook)"],
                     doi_ssim: "10.3998/mpub.B",
                     publisher_tesim: ["B Press"],
                     visibility_ssi: "open",
                     volume_tesim: ["Vol 1"],
                     edition_name_tesim: ["Second Edition"],
                     date_published_dtsim: ["2023-02-20T15:04:53Z"],
                     date_created_tesim: ["2000"],
                     products_lsim: [product.id])
  end

  let(:doc_c) do
    SolrDocument.new(id: 'ccccccccc',
                     has_model_ssim: "Monograph",
                     title_tesim: ["C Book _Italic_"],
                     creator_tesim: ["Cassidy, Firstname"],
                     isbn_tesim: ["C987654321 (open access)"],
                     doi_ssim: "10.3998/mpub.C",
                     publisher_tesim: ["C Press"],
                     open_access_tesim: ["yes"],
                     visibility_ssi: "open",
                     date_published_dtsim: ["2023-01-10T15:04:53Z"],
                     date_created_tesim: ["2023"],
                     products_lsim: [product.id])
  end

  let(:doc_d) do
    SolrDocument.new(id: 'ddddddddd',
                     has_model_ssim: "Monograph",
                     title_tesim: ["D Book _Italic_"],
                     creator_tesim: ["Davidson, Firstname"],
                     isbn_tesim: ["D123456789 (hardcover)", "D987654321 (ebook)"],
                     doi_ssim: "10.3998/mpub.D",
                     publisher_tesim: ["D Press"],
                     visibility_ssi: 'restricted',
                     date_published_dtsim: ["2000-01-01T15:04:53Z"],
                     date_created_tesim: ["2001"],
                     products_lsim: [product.id])
  end

  subject { BuildKbartJob.new }

  describe "#perform" do
    let(:product) { create(:product, identifier: 'test_product', needs_kbart: true, group_key: 'test_product') }
    let(:test_root) { File.join(Settings.scratch_space_path, 'spec', 'public', 'products', product.group_key, 'kbart') }
    let(:old_kbart) do <<~KBART
"publication_title","print_identifier","online_identifier","date_first_issue_online","num_first_vol_online","num_first_issue_online","date_last_issue_online","num_last_vol_online","num_last_issue_online","title_url","first_author","title_id","embargo_info","coverage_depth","notes","publisher_name","publication_type","date_monograph_published_print","date_monograph_published_online","monograph_volume","monograph_edition","first_editor","parent_publication_title_id","preceding_publication_title_id","access_type"
"A Book Italic","A123456789","A987654321","","","","","","","https://doi.org/10.3998/mpub.A","Adams","10.3998/mpub.A","","fulltext","","A Press","monograph","1999","2023-03-30","","","","","","P"
"B Book Italic","B123456789","B987654321","","","","","","","https://doi.org/10.3998/mpub.B","Brock","10.3998/mpub.B","","fulltext","","B Press","monograph","2000","2023-02-20","Vol 1","Second Edition","","","","P"
"C Book Italic","","C987654321","","","","","","","https://doi.org/10.3998/mpub.C","Cassidy","10.3998/mpub.C","","fulltext","","C Press","monograph","","2023-01-10","","","","","","F"
    KBART
    end
    let(:sftp) { double('sftp', dir: dir, rename: true) }
    let(:login) { { fulcrum_sftp_credentials: { sftp: 'fake', user: 'fake', password: 'fake', root: '/' } }.with_indifferent_access }
    let(:dir) { double("dir") }

    before do
      allow_any_instance_of(BuildKbartJob).to receive(:yaml_config).and_return(login)
      allow(Net::SFTP).to receive(:start).and_yield(sftp)
      allow(sftp).to receive(:mkdir!)
      allow(dir).to receive(:entries).and_return([])
    end

    context "without components" do
      before do
        FileUtils.mkdir_p(test_root)
        File.write(File.join(test_root, "test_product_2022-01-01.csv"), old_kbart)

        ActiveFedora::SolrService.add([doc_c.to_h, doc_b.to_h, doc_d.to_h, doc_a.to_h])
        ActiveFedora::SolrService.commit
      end

      it "does not create a new kbart file" do
        travel_to(Time.zone.local(2022, 02, 02, 12, 00, 00)) do
          expect(Net::SFTP).not_to receive(:start)

          subject.perform_now

          expect(Dir.glob(test_root + "/*").count).to eq 1
          expect(File.exist?(File.join(test_root, "test_product_2022-01-01.csv"))).to be true
          expect(File.exist?(File.join(test_root, "test_product_2022-02-02.csv"))).to be false
        end
      end
    end

    context "with components" do
      context "with an unknown product group key" do
        let(:product) { create(:product, identifier: 'something', needs_kbart: true, group_key: 'unknown') }
        let(:test_root) { File.join(Settings.scratch_space_path, 'spec', 'public', 'products', product.group_key, 'kbart') }

        before do
          FileUtils.rm_rf(test_root)
          allow(Monograph).to receive(:find)

          product.components = [
            create(:component, noid: doc_c.id),
            create(:component, noid: doc_b.id),
            create(:component, noid: doc_d.id),
            create(:component, noid: doc_a.id)
          ]

          ActiveFedora::SolrService.add([doc_c.to_h, doc_b.to_h, doc_d.to_h, doc_a.to_h])
          ActiveFedora::SolrService.commit
        end

        after do
          FileUtils.mkdir_p(test_root)
        end

        it "does not create a new kbart file" do
          travel_to(Time.zone.local(2022, 02, 02, 12, 00, 00)) do
            FileUtils.mkdir_p(test_root)

            expect(Net::SFTP).not_to receive(:start)
            expect(MarcLogger).to receive(:error)

            subject.perform_now

            expect(Dir.glob(test_root + "/*").count).to eq 0
          end
        end
      end

      context "with a known product group key" do
        before do
          FileUtils.rm_rf(test_root)
          allow(Monograph).to receive(:find)

          product.components = [
            create(:component, noid: doc_c.id),
            create(:component, noid: doc_b.id),
            create(:component, noid: doc_d.id),
            create(:component, noid: doc_a.id)
          ]

          ActiveFedora::SolrService.add([doc_c.to_h, doc_b.to_h, doc_d.to_h, doc_a.to_h])
          ActiveFedora::SolrService.commit
        end

        context "when there are no updates" do
          before do
            FileUtils.mkdir_p(test_root)
            File.write(File.join(test_root, "test_product_2022-01-01.csv"), old_kbart)
          end

          it "does not create a new kbart file" do
            travel_to(Time.zone.local(2022, 02, 02, 12, 00, 00)) do
              expect(Net::SFTP).not_to receive(:start)

              subject.perform_now

              expect(Dir.glob(test_root + "/*").count).to eq 1
              expect(File.exist?(File.join(test_root, "test_product_2022-01-01.csv"))).to be true
              expect(File.exist?(File.join(test_root, "test_product_2022-02-02.csv"))).to be false
            end
          end
        end

        context "when there's an update" do
          let(:doc_e) do
            SolrDocument.new(id: 'eeeeeeeee',
                            has_model_ssim: "Monograph",
                            title_tesim: ["E Book _Italic_"],
                            creator_tesim: ["Edwards, Firstname"],
                            isbn_tesim: ["E123456789 (hardcover)", "E987654321 (ebook)"],
                            doi_ssim: "10.3998/mpub.E",
                            publisher_tesim: ["E Press"],
                            visibility_ssi: "open",
                            date_published_dtsim: ["2022-02-22T15:04:53Z"],
                            date_created_tesim: ["2022"],
                            products_lsim: [product.id])
          end
          let(:local_csv) { File.join(test_root, "test_product_2022-02-02.csv") }
          let(:local_tsv) { File.join(test_root, "test_product_2022-02-02.txt") }
          let(:remote_csv) { "/home/fulcrum_ftp/heliotropium/publishing/Testing/KBART/test_product_2022-02-02.csv" }
          let(:remote_tsv) { "/home/fulcrum_ftp/heliotropium/publishing/Testing/KBART/test_product_2022-02-02.txt" }

          before do
            allow(Monograph).to receive(:find)
            product.components << create(:component, noid: doc_e.id)

            ActiveFedora::SolrService.add([doc_e.to_h])
            ActiveFedora::SolrService.commit

            FileUtils.mkdir_p(test_root)
            File.write(File.join(test_root, "test_product_2022-01-01.csv"), old_kbart)

            allow(sftp).to receive(:upload!).and_return(true)
          end

          it "creates new kbart files, .csv and .txt" do
            travel_to(Time.zone.local(2022, 02, 02, 12, 00, 00)) do
              subject.perform_now

              expect(Net::SFTP).to have_received(:start)
              expect(sftp).to have_received(:upload!).with(local_csv, remote_csv).once
              expect(sftp).to have_received(:upload!).with(local_tsv, remote_tsv).once

              expect(Dir.glob(test_root + "/*").count).to eq 3
              expect(File.exist?(File.join(test_root, "test_product_2022-01-01.csv"))).to be true
              expect(File.exist?(File.join(test_root, "test_product_2022-02-02.csv"))).to be true
              expect(File.exist?(File.join(test_root, "test_product_2022-02-02.txt"))).to be true

              # sneak in a check for the txt/tsv here I guess
              tsv = CSV.read(File.join(test_root, "test_product_2022-02-02.txt"), col_sep: "\t")

              expect(tsv[0][0]).to eq "publication_title"
              expect(tsv[1][0]).to eq "A Book Italic"
              expect(tsv[2][0]).to eq "B Book Italic"
              expect(tsv[3][0]).to eq "C Book Italic"
              expect(tsv[4][0]).to eq "E Book Italic"
            end
          end

          context "with explicitly set Eastern time zone" do
            it "creates a kbart file with the correct date" do
              # Time zone problems and confusion with the date in the file name mean we need to explicitly
              # set the timezone to Eastern in the job. See HELIO-4528
              # GMT time is the fulcrum default, so we go to 2022-02-03 at 1 AM GMT
              travel_to(Time.zone.local(2022, 02, 03, 01, 00, 00)) do
                expect(Time.zone.name).to eq "UTC"
                expect(Time.zone.now.strftime "%Y-%m-%d").to eq "2022-02-03"
                # We set the time zone to "Eastern Time (US & Canada)" in the job itself so the generated
                # KBART file should have the previous date 2022-02-02, not 2022-02-03 as Eastern is 4 or 5 hours
                # before GMT/UTC. The whole point of this is so we can build KBARTs at 21:00 Eastern and have the file name
                # date reflect that day, not the next day, without having to change the timezone for all of Fulcrum.
                subject.perform_now

                expect(File.exist?(File.join(test_root, "test_product_2022-01-01.csv"))).to be true
                expect(File.exist?(File.join(test_root, "test_product_2022-02-02.csv"))).to be true
                expect(File.exist?(File.join(test_root, "test_product_2022-02-03.csv"))).to be false
              end
            end
          end
        end

        context "when there are no existing kbart files" do
          let(:local_csv) { File.join(test_root, "test_product_2022-02-02.csv") }
          let(:local_tsv) { File.join(test_root, "test_product_2022-02-02.txt") }
          let(:remote_csv) { "/home/fulcrum_ftp/heliotropium/publishing/Testing/KBART/test_product_2022-02-02.csv" }
          let(:remote_tsv) { "/home/fulcrum_ftp/heliotropium/publishing/Testing/KBART/test_product_2022-02-02.txt" }

          before do
            FileUtils.mkdir_p(test_root)
            allow(sftp).to receive(:upload!).and_return(true)
          end

          it "creates new kbart files (csv and txt)" do
            travel_to(Time.zone.local(2022, 02, 02, 12, 00, 00)) do
              subject.perform_now

              expect(Net::SFTP).to have_received(:start)
              expect(sftp).to have_received(:upload!).with(local_csv, remote_csv).once
              expect(sftp).to have_received(:upload!).with(local_tsv, remote_tsv).once

              expect(Dir.glob(test_root + "/*").count).to eq 2
              expect(File.exist?(File.join(test_root, "test_product_2022-02-02.csv"))).to be true
              expect(File.exist?(File.join(test_root, "test_product_2022-02-02.txt"))).to be true
            end
          end
        end
      end
    end
  end

  describe "#yaml_config" do
    context "no config" do
      it "returns nil" do
        expect(subject.yaml_config).to be nil
      end
    end

    context "with config" do
      let(:data) do
        {
          "fulcrum_sftp_credentials" => {
            "sftp" => 'ftp.fulcrum.org',
            "user" => 'username',
            "password" => 'password',
            "root" => '/'
          }
        }
      end
      let(:config_file) { Tempfile.new("fulcrum_sftp.yml") }

      before do
        allow(Rails.root).to receive(:join).with('config', 'fulcrum_sftp.yml').and_return(config_file)
      end

      it "returns login information" do
        config_file.write(data.to_yaml)
        config_file.rewind
        config = subject.yaml_config["fulcrum_sftp_credentials"]
        expect(config["sftp"]).to eq "ftp.fulcrum.org"
        expect(config["user"]).to eq "username"
        expect(config["password"]).to eq "password"
        expect(config["root"]).to eq "/"
      end
    end
  end

  describe "#maybe_move_old_kbarts" do
    # I'd rather not actually connect to sftp from rspec so mocks it is. Hope it's good enough.
    let(:sftp) { double("sftp", dir: dir, rename: true) }
    let(:dir) { double("dir") }

    context "umpebc" do
      let(:group_key) { "umpebc" }
      let(:file_root) { "UMPEBC_2018" }
      let(:entry1) { double("entry", name: "UMPEBC_2018_2022-01-01.csv") }
      let(:entry2) { double("entry", name: "UMPEBC_2018_2022-01-01.txt") }
      let(:bad_entry) { double("entry", name: "UMPEBC_2018-but-then-something-wrong.txt") }
      let(:entries) do
        [ entry1, entry2, bad_entry ]
      end

      before do
        allow(sftp.dir).to receive(:entries).with("/home/fulcrum_ftp/ftp.fulcrum.org/UMPEBC/KBART").and_return(entries)
      end

      context "when the old kbart dir already exists" do
        before do
          allow(sftp).to receive(:mkdir!).with("/home/fulcrum_ftp/ftp.fulcrum.org/UMPEBC/KBART/UMPEBC_old").and_raise(StandardError)
        end

        it "throws on mkdir which is fine, renames (moves) the old kbarts to UMPEBC_old" do
          subject.maybe_move_old_kbarts(sftp, group_key, file_root)
          expect(sftp).to have_received(:mkdir!).with("/home/fulcrum_ftp/ftp.fulcrum.org/UMPEBC/KBART/UMPEBC_old")
          expect(sftp).to have_received(:rename).exactly(2).times
          expect(sftp).to have_received(:rename).with("/home/fulcrum_ftp/ftp.fulcrum.org/UMPEBC/KBART/UMPEBC_2018_2022-01-01.csv", "/home/fulcrum_ftp/ftp.fulcrum.org/UMPEBC/KBART/UMPEBC_old/UMPEBC_2018_2022-01-01.csv")
          expect(sftp).to have_received(:rename).with("/home/fulcrum_ftp/ftp.fulcrum.org/UMPEBC/KBART/UMPEBC_2018_2022-01-01.txt", "/home/fulcrum_ftp/ftp.fulcrum.org/UMPEBC/KBART/UMPEBC_old/UMPEBC_2018_2022-01-01.txt")
        end
      end

      context "when the old kbart diretory doesn't yet exist" do
        before do
          allow(sftp).to receive(:mkdir!).with("/home/fulcrum_ftp/ftp.fulcrum.org/UMPEBC/KBART/UMPEBC_old").and_return(true)
          allow(MarcLogger).to receive(:info)
        end

        it "creates UMPEBC_old, renames (moves) the old kbarts to UMPEBC_old" do
          subject.maybe_move_old_kbarts(sftp, group_key, file_root)
          expect(sftp).to have_received(:mkdir!).with("/home/fulcrum_ftp/ftp.fulcrum.org/UMPEBC/KBART/UMPEBC_old")
          expect(sftp).to have_received(:rename).exactly(2).times
          expect(sftp).to have_received(:rename).with("/home/fulcrum_ftp/ftp.fulcrum.org/UMPEBC/KBART/UMPEBC_2018_2022-01-01.csv", "/home/fulcrum_ftp/ftp.fulcrum.org/UMPEBC/KBART/UMPEBC_old/UMPEBC_2018_2022-01-01.csv")
          expect(sftp).to have_received(:rename).with("/home/fulcrum_ftp/ftp.fulcrum.org/UMPEBC/KBART/UMPEBC_2018_2022-01-01.txt", "/home/fulcrum_ftp/ftp.fulcrum.org/UMPEBC/KBART/UMPEBC_old/UMPEBC_2018_2022-01-01.txt")
        end
      end
    end

    context "amherst" do
      let(:group_key) { "amherst" }
      let(:file_root) { "amherst" }
      let(:entry1) { double("entry", name: "amherst_2023-04-04.csv") }
      let(:entry2) { double("entry", name: "amherst_2023-04-04.txt") }
      let(:bad_entry) { double("entry", name: "amherst_deleted.txt") }
      let(:entries) do
        [entry1, entry2, bad_entry]
      end

      before do
        allow(sftp.dir).to receive(:entries).with("/home/fulcrum_ftp/ftp.fulcrum.org/Amherst_College_Press/KBART").and_return(entries)
        allow(sftp).to receive(:mkdir!).with("/home/fulcrum_ftp/ftp.fulcrum.org/Amherst_College_Press/KBART/amherst_old").and_return(true)
      end

      it "renames (moves) the old kbarts amherst_old" do
        subject.maybe_move_old_kbarts(sftp, group_key, file_root)
        expect(sftp).to have_received(:rename).exactly(2).times
        expect(sftp).to have_received(:rename).with("/home/fulcrum_ftp/ftp.fulcrum.org/Amherst_College_Press/KBART/amherst_2023-04-04.csv", "/home/fulcrum_ftp/ftp.fulcrum.org/Amherst_College_Press/KBART/amherst_old/amherst_2023-04-04.csv")
        expect(sftp).to have_received(:rename).with("/home/fulcrum_ftp/ftp.fulcrum.org/Amherst_College_Press/KBART/amherst_2023-04-04.txt", "/home/fulcrum_ftp/ftp.fulcrum.org/Amherst_College_Press/KBART/amherst_old/amherst_2023-04-04.txt")
      end
    end
  end

  describe "#published_sorted_monographs" do
    let(:product) { create(:product, identifier: 'test_product', needs_kbart: true, group_key: 'test_product') }

    before do
      allow(Monograph).to receive(:find)

      product.components = [
        create(:component, noid: doc_c.id),
        create(:component, noid: doc_b.id),
        create(:component, noid: doc_d.id),
        create(:component, noid: doc_a.id)
      ]

      ActiveFedora::SolrService.add([doc_c.to_h, doc_b.to_h, doc_d.to_h, doc_a.to_h])
      ActiveFedora::SolrService.commit
    end

    it "returns the title sorted presenters of published monographs that belong to the product" do
      monographs = subject.published_sorted_monographs(product)

      expect(monographs.count).to eq 3
      expect(monographs[0]).to be_an_instance_of(Hyrax::MonographPresenter)
      expect(monographs[0].page_title).to eq "A Book Italic"
      expect(monographs[1].page_title).to eq "B Book Italic"
      expect(monographs[2].page_title).to eq "C Book Italic"
    end

    context "with a tombstoned work" do
      let(:doc_e) do
        SolrDocument.new(id: 'eeeeeeeee',
                         has_model_ssim: "Monograph",
                         title_tesim: ["E Book _Italic_"],
                         creator_tesim: ["Egbert, Firstname"],
                         isbn_tesim: ["D123456789 (hardcover)", "D987654321 (ebook)"],
                         doi_ssim: "10.3998/mpub.E",
                         publisher_tesim: ["E Press"],
                         visibility_ssi: 'open',
                         date_published_dtsim: ["2020-01-01T15:04:53Z"],
                         date_created_tesim: ["2020"],
                         products_lsim: [product.id],
                         tombstone_ssim: ["yes"])
      end

      before do
        ActiveFedora::SolrService.add(doc_e.to_h)
        ActiveFedora::SolrService.commit
      end

      it "does not return the tombstoned work" do
        monographs = subject.published_sorted_monographs(product)

        expect(monographs.count).to eq 3
        expect(monographs[0]).to be_an_instance_of(Hyrax::MonographPresenter)
        expect(monographs[0].page_title).to eq "A Book Italic"
        expect(monographs[1].page_title).to eq "B Book Italic"
        expect(monographs[2].page_title).to eq "C Book Italic"
      end
    end
  end

  describe "#most_recent_kbart" do
    let(:product) { create(:product, identifier: 'test_product', needs_kbart: true, group_key: 'test_product') }
    let(:test_root) { File.join(Settings.scratch_space_path, 'spec', 'public', 'products', product.group_key, 'kbart') }

    before do
      FileUtils.rm_rf(test_root)
      FileUtils.mkdir_p(test_root)
      FileUtils.touch(File.join(test_root, "test_product_2022-01-01.csv"))
      FileUtils.touch(File.join(test_root, "test_product_2022-02-01.csv"))
      FileUtils.touch(File.join(test_root, "test_product_2020-01-01.csv"))
    end

    it "returns the most recent kbart file for the product" do
      expect(subject.most_recent_kbart(test_root, product.identifier)).to eq File.join(test_root, "test_product_2022-02-01.csv").to_s
    end
  end

  describe "#kbart_root" do
    let(:product) { create(:product, identifier: 'test_product', needs_kbart: true, group_key: 'test_product') }

    it "returns the kbart root directory for the product" do
      expect(subject.kbart_root(product).to_s).to match(/public\/products\/test_product\/kbart/)
    end
  end

  describe "#make_kbart_csv" do
    let(:product) { create(:product, identifier: 'test_product', needs_kbart: true, group_key: 'test_product') }
    let(:monographs) do
      [
        Hyrax::MonographPresenter.new(doc_a, nil),
        Hyrax::MonographPresenter.new(doc_b, nil),
        Hyrax::MonographPresenter.new(doc_c, nil)
      ]
    end

    it "makes a csv with a header" do
      csv = CSV.parse(subject.make_kbart_csv(monographs))

      expect(csv[0][0]).to eq "publication_title"
      expect(csv[0][24]).to eq "access_type"

      expect(csv[1][0]).to eq "A Book Italic"
      # not OA means access_type is "P"
      expect(csv[1][24]).to eq "P"

      expect(csv[2][0]).to eq "B Book Italic"
      # a print_isbn means a date_monograph_published_print
      expect(csv[2][1]).to eq "B123456789"
      expect(csv[2][17]).to eq "2000"
      expect(csv[2][19]).to eq "Vol 1"
      expect(csv[2][20]).to eq "Second Edition"

      expect(csv[3][0]).to eq "C Book Italic"
      # no print isbn means no date_monograph_published_print
      expect(csv[3][1]).to eq ""
      expect(csv[3][17]).to eq ""
      # open access mean access_type is F
      expect(csv[3][24]).to eq "F"
    end
  end

  describe "#first_author_last_name" do
    let(:monograph) { Hyrax::MonographPresenter.new(SolrDocument.new(creator_tesim: ["Lastname, Firstname\nOtherlast, Otherfirst"]), nil) }

    it "returns the first author's last name" do
      expect(subject.first_author_last_name(monograph)).to eq "Lastname"
    end

    # This turned into a bit of a mess. Lots of ways it can go wrong I guess.
    # HELIO-4457 and HELIO-4457
    context "when there is no name/creator" do
      context "when the creator array exists, but has nil in it" do
        # This shouldn't happen, but it has for historical HEB metadata, HELIO-4457
        let(:monograph) { Hyrax::MonographPresenter.new(SolrDocument.new(creator_tesim: [nil]), nil) }

        it "returns the empty string" do
          expect(subject.first_author_last_name(monograph)).to eq ""
        end
      end

      context "when the array exists but is empty" do
        let(:monograph) { Hyrax::MonographPresenter.new(SolrDocument.new(creator_tesim: []), nil) }

        it "returns the empty string" do
          expect(subject.first_author_last_name(monograph)).to eq ""
        end
      end

      context "when it's just not there at all" do
        let(:monograph) { Hyrax::MonographPresenter.new(SolrDocument.new(title_tesim: ["No Author Book"]), nil) }

        it "returns the empty string" do
          expect(subject.first_author_last_name(monograph)).to eq ""
        end
      end

      context "when it's an empty array inside an empty array" do
        let(:monograph) { Hyrax::MonographPresenter.new(SolrDocument.new(title_tesim: [[]]), nil) }

        it "returns an empty string" do
          expect(subject.first_author_last_name(monograph)).to eq ""
        end
      end

      # This is still crashing mysteriously (sometimes! not always!) I just don't know anymore
      # HELIO-4877
      context "when there's an exception" do
        let(:monograph) { Hyrax::MonographPresenter.new(SolrDocument.new(id: '999999999', creator_tesim: ['Test']), nil) }

        before do
          allow(monograph).to receive(:id).and_return('999999999')
          allow(monograph).to receive(:solr_document).and_raise(StandardError, 'test exception')
          allow(MarcLogger).to receive(:error)
        end

        it "logs the exception and returns an empty string" do
          result = subject.first_author_last_name(monograph)
          expect(result).to eq ""
          expect(MarcLogger).to have_received(:error).with("Error in BuildKbartJob.first_author_last_name for 999999999: test exception")
        end
      end
    end
  end

  describe "#print_isbn" do
    context "a normal book with multiple ISBNS" do
      isbns = ["978-0-472-07581-2 (hardcover)", "978-0-472-05581-4 (paper)", "978-0-472-90313-9 (open access)"]

      it "returns the unformated hardcover ISBN" do
        expect(subject.print_isbn(isbns)).to eq "9780472075812"
      end
    end

    context "with 'print' type" do
      isbns = ["978-0-472-07581-2 (print)", "978-0-472-90313-9 (open access)"]

      it "returns the print ISBN" do
        expect(subject.print_isbn(isbns)).to eq "9780472075812"
      end
    end

    context "with no print ISBNs" do
      isbns = ["978-0-472-07581-2 (ebook)", "978-0-472-05581-4 (pdf)", "978-0-472-90313-9 (open access)"]

      it "returns an empty string" do
        expect(subject.print_isbn(isbns)).to eq ""
      end
    end

    context "with no ISBN types" do
      isbns = ["978-0-472-90313-9"]

      it "returns an empty string" do
        expect(subject.print_isbn(isbns)).to eq ""
      end
    end

    context "with no ISBNs" do
      isbns = []

      it "returns an empty string" do
        expect(subject.print_isbn(isbns)).to eq ""
      end
    end
  end

  describe "#online_isbn" do
    context "a normal book with multiple ISBNs" do
      isbns = ["978-0-472-07581-2 (hardcover)", "978-0-472-05581-4 (paper)", "978-0-472-90313-9 (open access)"]

      it "returns the unformated open access ISBN" do
        expect(subject.online_isbn(isbns)).to eq "9780472903139"
      end
    end

    context "with both ebook and open access types" do
      isbns = ["978-0-472-07581-2 (hardcover)", "978-0-472-05581-4 (ebook)", "978-0-472-90313-9 (open access)"]

      it "returns the open access isbn" do
        expect(subject.online_isbn(isbns)).to eq "9780472903139"
      end
    end

    context "with just the ebook" do
      isbns = ["978-0-472-07581-2 (hardcover)", "978-0-472-05581-4 (paper)", "978-0-472-90313-9 (ebook)"]

      it "returns the ebook isbn" do
        expect(subject.online_isbn(isbns)).to eq "9780472903139"
      end
    end
  end

  describe "#title_url" do
    context "if there's a DOI" do
      let(:monograph) { Hyrax::MonographPresenter.new(SolrDocument.new(doi_ssim: "10.3998/mpub.11691056"), nil) }

      it "returns the DOI" do
        expect(subject.title_url(monograph)).to eq "https://doi.org/10.3998/mpub.11691056"
      end
    end

    context "if the press is heb" do
      let(:monograph) { Hyrax::MonographPresenter.new(SolrDocument.new(id: "123456789", press_tesim: "heb", identifier_tesim: ["heb_id:heb00001.0001.001"]), nil) }

      it "returns the heb handle" do
        expect(subject.title_url(monograph)).to eq "https://hdl.handle.net/2027/heb00001.0001.001"
      end
    end

    context "if there's a hdl property on the monograph" do
      let(:monograph) { Hyrax::MonographPresenter.new(SolrDocument.new(hdl_ssim: "2027/spo.13469761.0014.001"), nil) }

      it "returns the monograph hdl" do
        expect(subject.title_url(monograph)).to eq "https://hdl.handle.net/2027/spo.13469761.0014.001"
      end
    end

    context "if there's no doi or hdl property" do
      let(:monograph) { Hyrax::MonographPresenter.new(SolrDocument.new(id: "999999999"), nil) }

      it "returns the default fulcrum handle" do
        expect(subject.title_url(monograph)).to eq "https://hdl.handle.net/2027/fulcrum.999999999"
      end
    end
  end

  describe "#title_id" do
    context "if it's heb" do
      let(:monograph) { Hyrax::MonographPresenter.new(SolrDocument.new(press_tesim: ["heb"], identifier_tesim: ["heb_id:heb90000.0001.001", "something else"]), nil) }

      it "returns the capitalized hebid" do
        expect(subject.title_id(monograph)).to eq "HEB90000.0001.001"
      end
    end

    context "if there's a doi" do
      let(:monograph) { Hyrax::MonographPresenter.new(SolrDocument.new(press_tesim: ["other"], doi_ssim: ["10.3998/mpub.11691056"]), nil) }

      it "returns the doi, not the doi url" do
        expect(subject.title_id(monograph)).to eq "10.3998/mpub.11691056"
      end
    end

    context "if there's a hdl property but no doi" do
      let(:monograph) { Hyrax::MonographPresenter.new(SolrDocument.new(press_tesim: ["other"], hdl_ssim: ["2027/spo.13469761.0014.001"]), nil) }


      it "returns the hdl property" do
        expect(subject.title_id(monograph)).to eq "2027/spo.13469761.0014.001"
      end
    end

    context "if it's not heb, there's no doi and no explicit hdl property" do
      let(:monograph) { Hyrax::MonographPresenter.new(SolrDocument.new(id: "999999999", press_tesim: ["other"]), nil) }

      it "returns the default fulcrum handle, not handle url" do
        expect(subject.title_id(monograph)).to eq "2027/fulcrum.999999999"
      end
    end
  end

  describe "#publisher_name" do
    # context "if it's barpublishing" do
    #   let(:monograph) { Hyrax::MonographPresenter.new(SolrDocument.new(press_tesim: ["barpublishing"]), nil) }

    #   it "returns 'British Archaeological Reports'" do
    #     expect(subject.publisher_name(monograph)).to eq "British Archaeological Reports"
    #   end
    # end

    # context "if it's heb" do
    #   let(:monograph) { Hyrax::MonographPresenter.new(SolrDocument.new(press_tesim: ["heb"], publisher_tesim: ["Oxford Press"]), nil) }

    #   it "returns the monograph's publisher property" do
    #     expect(subject.publisher_name(monograph)).to eq "Oxford Press"
    #   end
    # end

    # context "all other presses" do
    #   # It's probably a long ago mistake that a press name is indexed on the Monograph as _ssim but ok
    #   let(:monograph) { Hyrax::MonographPresenter.new(SolrDocument.new(press_name_ssim: ["The Name of the Press"]), nil) }

    #   it "returns the press name" do
    #     expect(subject.publisher_name(monograph)).to eq "The Name of the Press"
    #   end
    # end

    # All presses are now the same and use "publisher" (publisher_tesim) for this see HELIO-4514
    context "bar publishing" do
      let(:monograph) { Hyrax::MonographPresenter.new(SolrDocument.new(press_tesim: ["barpublishing"], publisher_tesim: ["British Archaeological Reports"]), nil) }

      it do
        expect(subject.publisher_name(monograph)).to eq "British Archaeological Reports"
      end
    end

    context "heb" do
      let(:monograph) { Hyrax::MonographPresenter.new(SolrDocument.new(press_tesim: ["heb"], publisher_tesim: ["Oxford Press"]), nil) }

      it "returns the monograph's publisher property" do
        expect(subject.publisher_name(monograph)).to eq "Oxford Press"
      end
    end

    context "all presses" do
      let(:monograph) { Hyrax::MonographPresenter.new(SolrDocument.new(press_tesim: "bigten", publisher_tesim: ["University of Michigan Press"], press_name_ssim: ["The Name of the Press"]), nil) }

      it "returns the monograph's publisher property" do
        expect(subject.publisher_name(monograph)).to eq "University of Michigan Press"
      end
    end
  end
end
