# frozen_string_literal: true

require 'rails_helper'

RSpec.describe AppearanceRelease do
  it_behaves_like 'a contractable'
  it_behaves_like 'an exploitable'
  it_behaves_like 'a notable'
  it_behaves_like 'a releasable'
  it_behaves_like 'a taggable'

  it { is_expected.to respond_to(:photos) }
  it { is_expected.to respond_to(:photo) }

  describe 'associations' do
    it { is_expected.to have_many(:video_release_confirmations).dependent(:destroy) }
    it { is_expected.to have_many(:confirmed_videos).source(:video).through(:video_release_confirmations) }
  end

  describe 'validations' do
    it { is_expected.to allow_content_types('image/png', 'image/jpeg').for(:person_photo) }
    it { is_expected.not_to allow_content_types('application/pdf', 'image/gif').for(:person_photo) }
    it { is_expected.to allow_value('test@test.com', nil).for(:person_email) }
    it { is_expected.not_to allow_values('foo', 'test@foo', 'N/A').for(:person_email) }
    it { is_expected.to validate_presence_of(:person_first_name) }
    it { is_expected.to validate_presence_of(:person_last_name) }

    context 'for native releases' do
      it { is_expected.to validate_attachment_of(:person_photo).on(:native) }
      it { is_expected.to validate_attachment_of(:signature).on(:native) }

      it 'validates person_photo_is_acceptable on new records' do
        appearance_release = build(:appearance_release)
        allow(BrayniacAI::Validation).to receive(:create).and_return(double(:validation, valid: false, error: 'api error'))

        expect(appearance_release.valid?(:native)).to eq false
        expect(appearance_release.errors[:person_photo]).to eq ['api error']
      end

      it 'does not validate person_photo_is_acceptable on existing records' do
        appearance_release = create(:appearance_release, :native)

        expect(appearance_release.valid?(:native)).to eq true
      end
    end

    context 'for non-native releases' do
      it 'fails to create release if nothing is attached' do
        release = create(:appearance_release, :without_person_photo)

        expect(release.valid?(:non_native)).to eq false
      end

      it 'creates release if only contract is attached' do
        release = create(:appearance_release, :without_person_photo, :non_native)

        expect(release.valid?(:non_native)).to eq true
      end

      it 'creates release if only person_photo is attached' do
        release = create(:appearance_release, :with_person_photo_only)

        expect(release.valid?(:non_native)).to eq true
      end
    end

    context 'when the signer is a minor' do
      subject { build(:appearance_release, minor: true) }

      it { is_expected.to validate_presence_of(:guardian_first_name) }
      it { is_expected.to validate_presence_of(:guardian_last_name) }
    end
  end

  describe 'attachments' do
    it { is_expected.to respond_to(:contract) }
    it { is_expected.to respond_to(:person_photo) }
    it { is_expected.to respond_to(:signature) }
  end

  describe 'scopes' do
    describe '.complete' do
      it 'returns records that have both a person photo and a contract' do
        skip "Test is inconsistently failing in CI"

        without_photo_or_contract = create(:appearance_release, person_photo: nil, contract: nil)
        with_photo_without_contract = create(:appearance_release, contract: nil)
        without_photo_with_contract = create(:appearance_release, :non_native, person_photo: nil)
        with_photo_and_contract = create(:appearance_release, :non_native)

        complete_releases = described_class.complete
        all_releases = described_class.all

        expect(complete_releases).not_to include(all_releases[0])
        expect(complete_releases).not_to include(all_releases[1])
        expect(complete_releases).not_to include(all_releases[2])
        expect(complete_releases).to include(all_releases[3])
      end
    end

    describe '.incomplete' do
      it 'returns records that are missing either a person photo or a contract' do
        skip "Test is inconsistently failing in CI"

        without_photo_or_contract = create(:appearance_release, person_photo: nil, contract: nil)
        with_photo_without_contract = create(:appearance_release, contract: nil)
        without_photo_with_contract = create(:appearance_release, :non_native, person_photo: nil)
        with_photo_and_contract = create(:appearance_release, :non_native)

        incomplete_releases = described_class.incomplete
        all_releases = described_class.all

        expect(incomplete_releases).to include(all_releases[0])
        expect(incomplete_releases).to include(all_releases[1])
        expect(incomplete_releases).to include(all_releases[2])
        expect(incomplete_releases).not_to include(all_releases[3])
      end
    end

    describe '.with_person_photo' do
      it 'returns records that have a person photo attachment' do
        with_photo = create(:appearance_release, :with_person_photo)
        without_photo = create(:appearance_release, :without_person_photo)

        results = described_class.with_person_photo

        expect(results.size).to eq 1
        expect(results).to include(with_photo)
        expect(results).not_to include(without_photo)
      end
    end
  end

  describe '#native?' do
    it 'returns true when the release has a signature' do
      release = build(:appearance_release, :native)

      expect(release).to be_native
    end
  end

  describe '#uses_edl?' do
    it { is_expected.to be_uses_edl }
  end

  describe '#photos' do
    it 'returns photo if it is attached' do
      ar = create(:appearance_release)
      expect(ar.photos).to eq [ar.photo]
    end

    it 'returns empty list if photo is not attached' do
      ar = AppearanceRelease.new
      expect(ar.photos).to eq []
    end
  end

  describe '#contract_file_name' do
    it 'includes signed timestamp, release number, and person name' do
      release = create(:appearance_release_with_contract_template, signed_at: Date.new(2020, 2, 10), person_first_name: 'John', person_last_name: 'Doe')

      expect(release.contract_file_name).to eq('my-video-project_appearance_2020.02.10_1_doe-john')
    end

    context 'when signed at is nil' do
      it 'uses the created at date' do
        release = create(:appearance_release_with_contract_template,
                         signed_at: nil,
                         created_at: DateTime.new(2020, 2, 10, 12, 0, 0),
                         person_first_name: 'John', person_last_name: 'Doe')

        expect(release.contract_file_name).to eq('my-video-project_appearance_2020.02.10_1_doe-john')
      end
    end
  end
end
