require "rails_helper"

RSpec.describe UpdateInvoiceJob, type: :job do
  include_context :scheduled_job
  include_examples :scheduled_job_tests

  it "is the correct queue and frequency" do
    expect(described_class.sidekiq_options["queue"]).to eq "low_priority" # overrides default
    expect(described_class.frequency).to be > 11.hours
  end

  describe "perform" do
    let(:invoice_active) { FactoryBot.create(:invoice_paid) }
    let(:invoice_active_updated_at) { Time.current - 1.day }
    let(:organization1) { invoice_active.organization }
    let(:invoice_expired) { FactoryBot.create(:invoice_paid, start_at: Time.current - 2.weeks) }
    let(:organization2) { invoice_expired.organization }
    let(:invoice_to_activate) { FactoryBot.create(:invoice_paid, start_at: Time.current + 0.2) }
    let(:organization3) { invoice_to_activate.organization }
    it "schedules all the workers" do
      expect(invoice_to_activate.future?).to be_truthy
      expect(Invoice.future.pluck(:id)).to eq([invoice_to_activate.id])
      invoice_active.update_column :updated_at, invoice_active_updated_at
      organization1.save
      organization2.save
      expect(organization3.paid?).to be_falsey

      expect(invoice_active.updated_at).to be_within(1.second).of invoice_active_updated_at
      expect(organization1.paid?).to be_truthy
      expect(organization1.current_invoices.first.paid_in_full?).to be_truthy
      # Manually make invoice expired
      invoice_expired.update_column :subscription_end_at, Time.current - 1.day
      invoice_expired.reload
      expect(invoice_expired.should_expire?).to be_truthy
      expect(invoice_expired.active?).to be_truthy
      expect(invoice_expired.expired?).to be_truthy
      # expired invoice is still active for the organization
      expect(organization2.paid?).to be_truthy
      expect(organization2.current_invoices.first.paid_in_full?).to be_truthy
      expect(organization2.current_invoices.first.active?).to be_truthy
      sleep 0.2 # Ensure time has passed to make invoice_to_activate no longer future
      expect(invoice_to_activate.future?).to be_falsey
      expect(Invoice.should_activate.pluck(:id)).to eq([invoice_to_activate.id])
      Sidekiq::Job.clear_all
      Sidekiq::Testing.inline! do
        described_class.new.perform
      end

      organization1.save
      organization2.save
      organization3.reload
      invoice_active.reload
      invoice_expired.reload
      invoice_to_activate.reload

      expect(organization1.is_paid).to be_truthy
      expect(organization1.current_invoices.first.paid_in_full?).to be_truthy
      # the active invoice updated_at hasn't been bumped
      expect(invoice_active.updated_at).to be_within(1.second).of invoice_active_updated_at
      # And expired invoice has been updated
      expect(invoice_expired.active?).to be_falsey
      expect(invoice_expired.expired?).to be_truthy
      expect(organization2.is_paid).to be_falsey
      expect(organization2.current_invoices.first).to_not be_present

      # And the invoice to active has been activated
      expect(invoice_to_activate.active?).to be_truthy
      expect(invoice_to_activate.current?).to be_truthy
      expect(invoice_to_activate.future?).to be_falsey
      expect(organization3.is_paid).to be_truthy
    end
  end
end
