require "rails_helper"

describe MatchAppearanceReleasesJob do
  let(:project) { create(:project) }
  let(:dummy_appearance_release) { create(:appearance_release_import, :with_headshot, :with_contract) }
  let(:dummy_matching_request) { instance_double(MatchingRequest, id: 999) }

  before :all do
    ENV["AWS_BUCKET"] = ""
  end

  describe ".perform_now" do
    it "returns if no attachment is sent" do
      expect(MatchingRequest).not_to receive(:create)
      attachments = []
      MatchAppearanceReleasesJob.perform_now project, attachments
    end

    it "returns if no valid attachment is sent" do
      expect(MatchingRequest).not_to receive(:create)
      dummy_video = create(:video)
      attachments = [dummy_video.file.blob.signed_id]
      MatchAppearanceReleasesJob.perform_now project, attachments
    end

    it "does not create new appearance release if BrayniacAI returns empty matches array" do
      signed_ids = [dummy_appearance_release.person_photo.blob.signed_id]
      keys = [dummy_appearance_release.person_photo.key]
      payload = {
        project: project,
        attachments: signed_ids
      }
      qr_matching_payload = {
        bucket: '',
        files: keys,
        request_id: dummy_matching_request.id
      }
      qr_matching_mock_response = double(
        request_id: dummy_matching_request.id,
        matches: []
      )

      expect(MatchingRequest).to receive(:create).with(payload).and_return(dummy_matching_request)
      expect(BrayniacAI::QrMatching).to receive(:create!).with(qr_matching_payload).and_return(qr_matching_mock_response)
      expect(dummy_matching_request).to receive(:destroy)

      MatchAppearanceReleasesJob.perform_now project, signed_ids

      expect(AppearanceRelease.last).to eq dummy_appearance_release
    end

    it "creates new incomplete appearance release if BrayniacAI returns single headshot match" do
      signed_ids = [dummy_appearance_release.person_photo.blob.signed_id]
      keys = [dummy_appearance_release.person_photo.key]
      payload = {
        project: project,
        attachments: signed_ids
      }
      qr_matching_payload = {
        bucket: '',
        files: keys,
        request_id: dummy_matching_request.id
      }
      mock_match = double(
        headshots: keys,
        contracts: [],
        unknowns: [],
        identifier: 'some/identifier/123'
      )
      matches = [mock_match]
      qr_matching_mock_response = double(
        request_id: dummy_matching_request.id,
        matches: matches
      )

      expect(MatchingRequest).to receive(:create).with(payload).and_return(dummy_matching_request)
      expect(BrayniacAI::QrMatching).to receive(:create!).with(qr_matching_payload).and_return(qr_matching_mock_response)
      expect(dummy_matching_request).to receive(:destroy)

      MatchAppearanceReleasesJob.perform_now project, signed_ids

      expect(AppearanceRelease.last.identifier).to eq mock_match.identifier
      expect(AppearanceRelease.last.person_photo).to be_attached
      expect(AppearanceRelease.last.contract).not_to be_attached
    end

    it "creates new incomplete appearance release if BrayniacAI returns single contract match" do
      signed_ids = [dummy_appearance_release.contract.blob.signed_id]
      keys = [dummy_appearance_release.contract.key]
      payload = {
        project: project,
        attachments: signed_ids
      }
      qr_matching_payload = {
        bucket: '',
        files: keys,
        request_id: dummy_matching_request.id
      }
      mock_match = double(
        headshots: [],
        contracts: keys,
        unknowns: [],
        identifier: 'some/identifier/123'
      )
      matches = [mock_match]
      qr_matching_mock_response = double(
        request_id: dummy_matching_request.id,
        matches: matches
      )

      expect(MatchingRequest).to receive(:create).with(payload).and_return(dummy_matching_request)
      expect(BrayniacAI::QrMatching).to receive(:create!).with(qr_matching_payload).and_return(qr_matching_mock_response)
      expect(dummy_matching_request).to receive(:destroy)

      MatchAppearanceReleasesJob.perform_now project, signed_ids

      expect(AppearanceRelease.last.identifier).to eq mock_match.identifier
      expect(AppearanceRelease.last.person_photo.attached?).to eq false
      expect(AppearanceRelease.last.contract.attached?).to eq true
    end

    it "creates new complete appearance release if BrayniacAI returns match for headshot and contract" do
      signed_ids = [
        dummy_appearance_release.person_photo.blob.signed_id,
        dummy_appearance_release.contract.blob.signed_id
      ]
      keys = [
        dummy_appearance_release.person_photo.key,
        dummy_appearance_release.contract.key
      ]
      payload = {
        project: project,
        attachments: signed_ids
      }
      qr_matching_payload = {
        bucket: '',
        files: keys,
        request_id: dummy_matching_request.id
      }
      mock_match = double(
        headshots: [keys[0]],
        contracts: [keys[1]],
        unknowns: [],
        identifier: 'some/identifier/123'
      )
      matches = [mock_match]
      qr_matching_mock_response = double(
        request_id: dummy_matching_request.id,
        matches: matches
      )

      expect(MatchingRequest).to receive(:create).with(payload).and_return(dummy_matching_request)
      expect(BrayniacAI::QrMatching).to receive(:create!).with(qr_matching_payload).and_return(qr_matching_mock_response)
      expect(dummy_matching_request).to receive(:destroy)

      MatchAppearanceReleasesJob.perform_now project, signed_ids

      expect(AppearanceRelease.last.identifier).to eq mock_match.identifier
      expect(AppearanceRelease.last.person_photo.attached?).to eq true
      expect(AppearanceRelease.last.contract.attached?).to eq true
    end

    it "creates two new incomplete appearance releases if BrayniacAI returns two matches for headshot and contract" do
      signed_ids = [
        dummy_appearance_release.person_photo.blob.signed_id,
        dummy_appearance_release.contract.blob.signed_id
      ]
      keys = [
        dummy_appearance_release.person_photo.key,
        dummy_appearance_release.contract.key
      ]
      payload = {
        project: project,
        attachments: signed_ids
      }
      qr_matching_payload = {
        bucket: '',
        files: keys,
        request_id: dummy_matching_request.id
      }
      mock_match1 = double(
        headshots: [keys[0]],
        contracts: [],
        unknowns: [],
        identifier: 'some/identifier/123'
      )
      mock_match2 = double(
        headshots: [],
        contracts: [keys[1]],
        unknowns: [],
        identifier: 'some/identifier/789'
      )
      matches = [mock_match1, mock_match2]
      qr_matching_mock_response = double(
        request_id: dummy_matching_request.id,
        matches: matches
      )

      expect(MatchingRequest).to receive(:create).with(payload).and_return(dummy_matching_request)
      expect(BrayniacAI::QrMatching).to receive(:create!).with(qr_matching_payload).and_return(qr_matching_mock_response)
      expect(dummy_matching_request).to receive(:destroy)

      MatchAppearanceReleasesJob.perform_now project, signed_ids

      releases = AppearanceRelease.last(2)

      expect(releases[0].identifier).to eq mock_match1.identifier
      expect(releases[0].person_photo.attached?).to eq true
      expect(releases[0].contract.attached?).to eq false

      expect(releases[1].identifier).to eq mock_match2.identifier
      expect(releases[1].person_photo.attached?).to eq false
      expect(releases[1].contract.attached?).to eq true
    end
  end
end