require "rails_helper"

RSpec.describe Project, type: :model do
  describe "associations" do
    it { is_expected.to belong_to(:account) }
    it { is_expected.to have_many(:acquired_media_releases).dependent(:destroy) }
    it { is_expected.to have_many(:appearance_releases).dependent(:destroy) }
    it { is_expected.to have_many(:location_releases).dependent(:destroy) }
    it { is_expected.to have_many(:material_releases).dependent(:destroy) }
    it { is_expected.to have_many(:music_releases).dependent(:destroy) }
    it { is_expected.to have_many(:talent_releases).dependent(:destroy) }
    it { is_expected.to have_many(:medical_releases).dependent(:destroy) }
    it { is_expected.to have_many(:videos).dependent(:destroy) }
    it { is_expected.to have_many(:contract_templates).dependent(:destroy) }
    it { is_expected.to have_many(:project_memberships).dependent(:destroy) }
    it { is_expected.to have_many(:users).through(:project_memberships) }
    it { is_expected.to have_many(:directories).dependent(:destroy) }
    it { is_expected.to have_many(:broadcasts).dependent(:destroy) }
    it { is_expected.to have_many(:downloads).dependent(:destroy) }
    it { is_expected.to have_many(:zoom_meetings).dependent(:destroy) }
  end

  describe "nested attributes" do
    it { is_expected.to accept_nested_attributes_for(:project_memberships) }
  end

  describe "validations" do
    it { is_expected.to validate_presence_of(:name) }

    describe "#name uniqueness validation" do
      subject { build(:project) }
      it { is_expected.to validate_uniqueness_of(:name).scoped_to(:account_id) }
    end
  end

  describe "#import_contract_templates" do
    it "imports contract templates from other projects within the account" do
      existing_project = create(:project_with_contract_template)
      new_project = create(:project, name: "New Project", account: existing_project.account)

      expect {
        expect(new_project.import_contract_templates(existing_project.contract_templates.pluck(:id))).to be_truthy
      }.to change(ContractTemplate, :count).by(1)

      expect(new_project.reload.contract_templates.size).to eq(1)
      expect(new_project.contract_templates.first.body.to_s).to eq(existing_project.contract_templates.first.body.to_s)
      expect(new_project.contract_templates.first.guardian_clause.to_s).to eq(existing_project.contract_templates.first.guardian_clause.to_s)
    end
  end

  describe "#members" do
    it "returns users who have membership to the project and account managers" do
      account = build(:account)
      account_manager = create(:user, :account_manager, primary_account: account)
      associate = create(:user, :associate, primary_account: account)
      project = create(:project, members: associate, account: account)

      members = project.members

      expect(members).to include(associate)
      expect(members).to include(account_manager)
    end
  end

  describe '#zoom_meeting' do
    before(:all) do
      WebMock.disable_net_connect!(allow_localhost: true)
    end

    let(:project) { create(:project) }

    context 'there is a meeting already going' do
      let!(:zoom_meeting) { create(:zoom_meeting, status: :started, project: project, api_meeting_id: 'meeting-id') }

      it 'returns the active meeting' do
        expect(project.zoom_meeting).to eq(zoom_meeting)
      end
    end

    context 'there is no meeting' do
      context 'there is a free user available' do
        let!(:free_zoom_user) { create(:zoom_user, :with_api_id) }

        before do
          allow_any_instance_of(ZoomGateway).to receive(:create_meeting).and_return('new-meeting-id')
        end

        it 'creates new meeting' do
          expect { project.zoom_meeting }.to change { ZoomMeeting.count }.by(1)
        end

        it 'returns new meeting' do
          expect(project.zoom_meeting.api_meeting_id).to eq('new-meeting-id')
        end
      end

      context 'there is no free user available' do
        before do
          allow_any_instance_of(ZoomGateway).to receive(:create_host).and_return('new-host-id')
          allow_any_instance_of(ZoomGateway).to receive(:create_meeting).and_return('new-meeting-id')
        end

        it 'creates new user' do
          expect { project.zoom_meeting }.to change { ZoomUser.count }.by(1)
        end

        it 'creates new meeting' do
          expect { project.zoom_meeting }.to change { ZoomMeeting.count }.by(1)
        end

        it 'returns new meeting' do
          expect(project.zoom_meeting.api_meeting_id).to eq('new-meeting-id')
        end
      end
    end
  end
end
