# frozen_string_literal: true

describe ImageProcessorJob, type: :job do
  let(:blob) do
    ActiveStorage::Blob.create_and_upload!(io: StringIO.new("toto"), filename: "toto.png")
  end

  let(:blob_jpg) do
    ActiveStorage::Blob.create_and_upload!(io: StringIO.new("toto"), filename: "toto.jpg")
  end

  let(:attachment) { ActiveStorage::Attachment.new(name: "test", blob: blob) }
  let(:antivirus_pending) { false }
  let(:watermark_service) { instance_double("WatermarkService") }
  let(:auto_rotate_service) { instance_double("AutoRotateService") }

  before do
    virus_scanner_mock = instance_double("ActiveStorage::VirusScanner", pending?: antivirus_pending)
    allow(blob).to receive(:attachments).and_return([attachment])

    allow(blob).to receive(:virus_scanner).and_return(virus_scanner_mock)
    allow(blob_jpg).to receive(:virus_scanner).and_return(virus_scanner_mock)

    allow(WatermarkService).to receive(:new).and_return(watermark_service)
    allow(watermark_service).to receive(:process).and_return(true)

    allow(AutoRotateService).to receive(:new).and_return(auto_rotate_service)
    allow(auto_rotate_service).to receive(:process).and_return(true)
  end

  context "when the blob is not scanned yet" do
    let(:antivirus_pending) { true }

    it "raises a FileNotScannedYetError" do
      expect { described_class.perform_now(blob) }.to have_enqueued_job(described_class).with(blob)
    end
  end

  describe 'autorotate' do
    context "when image is not a jpg" do
      let(:rotated_file) { Tempfile.new("rotated.png") }

      before do
        allow(rotated_file).to receive(:size).and_return(100)
      end

      it "it does not process autorotate" do
        expect(auto_rotate_service).not_to receive(:process)
        described_class.perform_now(blob)
      end
    end

    context "when image is a jpg " do
      let(:rotated_file) { Tempfile.new("rotated.jpg") }

      before do
        allow(rotated_file).to receive(:size).and_return(100)
      end

      it "it processes autorotate" do
        expect(auto_rotate_service).to receive(:process).and_return(rotated_file)
        described_class.perform_now(blob_jpg)
      end
    end
  end

  describe 'create representation' do
    let(:blob_info) do
      {
        filename: file.original_filename,
        byte_size: file.size,
        checksum: Digest::SHA256.file(file.path),
        content_type: file.content_type,
        # we don't want to run virus scanner on this file
        metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
      }
    end

    let(:blob) do
      blob = ActiveStorage::Blob.create_before_direct_upload!(**blob_info)
      blob.upload(file)
      blob
    end

    context "when type image is usual" do
      let(:file) { fixture_file_upload('spec/fixtures/files/logo_test_procedure.png', 'image/png') }

      context "when representation is not required" do
        it "it does not create blob representation" do
          expect { described_class.perform_now(blob) }.not_to change { ActiveStorage::VariantRecord.count }
        end
      end

      context "when representation is required" do
        before do
          allow(blob).to receive(:representation_required?).and_return(true)
        end

        it "it creates blob representation" do
          expect { described_class.perform_now(blob) }.to change { ActiveStorage::VariantRecord.count }.by(1)
        end
      end
    end

    context "when type image is rare" do
      let(:file) { fixture_file_upload('spec/fixtures/files/pencil.tiff', 'image/tiff') }

      before do
        allow(blob).to receive(:representation_required?).and_return(true)
      end

      it "creates a second variant" do
        expect { described_class.perform_now(blob) }.to change { ActiveStorage::VariantRecord.count }.by(2)
      end
    end
  end

  describe 'watermark' do
    context "when watermark is already done" do
      before do
        allow(blob).to receive(:watermark_done?).and_return(true)
      end

      it "does not process the watermark" do
        expect(watermark_service).not_to receive(:process)
        described_class.perform_now(blob)
      end
    end

    context "when the blob is ready to be watermarked" do
      let(:watermarked_file) { Tempfile.new("watermarked.png") }

      before do
        allow(watermarked_file).to receive(:size).and_return(100)
        allow(blob).to receive(:watermark_pending?).and_return(true)
      end

      it "processes the blob with watermark" do
        expect(watermark_service).to receive(:process).and_return(watermarked_file)

        expect {
          described_class.perform_now(blob)
        }.to change {
          blob.reload.checksum
        }

        expect(blob.byte_size).to eq(100)
        expect(blob.watermarked_at).to be_present
      end
    end
  end
end