# frozen_string_literal: true

require 'spec_helper'

describe ReleaseTools::Security::AppSecIssue do
  subject(:appsec_issue) { described_class.new }

  let(:versions) do
    [
      ReleaseTools::Version.new('12.7.4'),
      ReleaseTools::Version.new('12.6.6'),
      ReleaseTools::Version.new('12.5.9')
    ]
  end

  let(:security_issues) do
    [
      ReleaseTools::Security::ImplementationIssue.new(create(:issue), []),
      ReleaseTools::Security::ImplementationIssue.new(create(:issue), [])
    ]
  end

  let(:coordinator) { instance_double(ReleaseTools::PatchRelease::Coordinator, versions: versions) }
  let(:fetcher) { instance_double(ReleaseTools::Security::IssuesFetcher, execute: security_issues) }
  let(:tracking_issue) { build(:issue, due_date: '2024-04-01') }
  let(:comms_issue) { build(:issue) }

  before do
    allow(ReleaseTools::PatchRelease::Coordinator)
      .to receive(:new)
      .and_return(coordinator)

    allow(ReleaseTools::Security::IssuesFetcher)
      .to receive(:new)
      .and_return(fetcher)

    allow(ReleaseTools::GitlabClient)
      .to receive_messages(
        next_security_tracking_issue: tracking_issue,
        security_communication_issue: comms_issue
      )

    security_issues.each do |security_issue|
      allow(security_issue)
        .to receive_messages(cves_issue: build(:issue), canonical_issue: build(:issue))
    end
  end

  it_behaves_like 'issuable #initialize'

  describe '#title' do
    it 'returns the title' do
      expect(appsec_issue.title).to eq('AppSec Task Issue for Patch Release: 12.7.4, 12.6.6, 12.5.9')
    end
  end

  describe '#confidential?' do
    it 'returns true' do
      expect(appsec_issue).to be_confidential
    end
  end

  describe '#labels' do
    it 'returns the appropriate labels' do
      expect(appsec_issue.labels).to eq('AppSecWorkType::SecurityReleaseRotation')
    end
  end

  describe '#security_issues' do
    it 'returns security issues' do
      expect(appsec_issue.security_issues).to eq(security_issues)
    end
  end

  describe '#due_date' do
    it 'returns the same date as the tracking issue' do
      expect(appsec_issue.due_date).to eq('2024-04-01')
    end
  end

  describe '#assignees' do
    let(:schedule) { instance_spy(ReleaseTools::ReleaseManagers::Schedule) }

    before do
      allow(ReleaseTools::ReleaseManagers::Schedule)
        .to receive(:new)
        .and_return(schedule)
    end

    it 'returns AppSec release managers' do
      expect(schedule)
        .to receive(:active_appsec_release_managers)
        .and_return([build(:user, id: 1), build(:user, id: 2)])

      expect(appsec_issue.assignees).to eq([1, 2])
    end

    context 'when something goes wrong' do
      it 'returns nil' do
        allow(schedule)
          .to receive(:active_appsec_release_managers)
          .and_raise(ReleaseTools::ReleaseManagers::Schedule::VersionNotFoundError)

        expect(appsec_issue.assignees).to be_nil
      end
    end
  end

  describe '#description' do
    it 'generates the description' do
      expect(appsec_issue.description).to be_present
    end
  end
end
