require 'rails_helper'
require 'webmock/rspec'

RSpec.describe BtcpayCheckDonationJob, type: :job do
  let(:user) { create :user, cn: 'jimmy', ou: 'kosmos.org' }

  let(:donation) do
    user.donations.create!(
      donation_method: "btcpay",
      btcpay_invoice_id: "K4e31MhbLKmr3D7qoNYRd3",
      paid_at: nil, payment_status: "processing",
      fiat_amount: 120, fiat_currency: "USD"
    )
  end

  before do
    allow_any_instance_of(User).to receive(:ldap_entry).and_return({
      uid: user.cn, ou: user.ou, mail: user.email, admin: nil,
      display_name: nil
    })
  end

  after(:each) do
    clear_enqueued_jobs
    clear_performed_jobs
  end

  describe "invoice still processing" do
    subject(:job) { described_class.perform_later(donation) }

    before do
      invoice = File.read("#{Rails.root}/spec/fixtures/btcpay/onchain_eur_processing_invoice.json")
      payments = File.read("#{Rails.root}/spec/fixtures/btcpay/onchain_eur_processing_payments.json")
      stub_request(:get, "http://btcpay.example.com/api/v1/stores/123456/invoices/K4e31MhbLKmr3D7qoNYRd3")
        .to_return(status: 200, headers: {}, body: invoice)
      stub_request(:get, "http://btcpay.example.com/api/v1/stores/123456/invoices/K4e31MhbLKmr3D7qoNYRd3/payment-methods")
        .to_return(status: 200, headers: {}, body: payments)
    end

    it "enqueues itself to check again later" do
      expect_any_instance_of(described_class).to receive(:re_enqueue_job).once
      perform_enqueued_jobs { job }
    end
  end

  describe "invoice settled" do
    subject(:job) { described_class.perform_later(donation) }

    before do
      invoice = File.read("#{Rails.root}/spec/fixtures/btcpay/onchain_eur_settled_invoice.json")
      payments = File.read("#{Rails.root}/spec/fixtures/btcpay/onchain_eur_settled_payments.json")
      stub_request(:get, "http://btcpay.example.com/api/v1/stores/123456/invoices/K4e31MhbLKmr3D7qoNYRd3")
        .to_return(status: 200, headers: {}, body: invoice)
      stub_request(:get, "http://btcpay.example.com/api/v1/stores/123456/invoices/K4e31MhbLKmr3D7qoNYRd3/payment-methods")
        .to_return(status: 200, headers: {}, body: payments)
    end

    it "updates the donation record" do
      perform_enqueued_jobs(only: described_class) { job }
      donation.reload
      expect(donation.paid_at).not_to be_nil
      expect(donation.payment_status).to eq("settled")
    end

    it "notifies the user via email" do
      perform_enqueued_jobs(only: described_class) { job }
      expect(enqueued_jobs.size).to eq(1)
      job = enqueued_jobs.select{|j| j['job_class'] == "ActionMailer::MailDeliveryJob"}.first
      expect(job['arguments'][0]).to eq('NotificationMailer')
      expect(job['arguments'][1]).to eq('bitcoin_donation_confirmed')
      expect(job['arguments'][3]['params']['user']['_aj_globalid']).to eq('gid://akkounts/User/1')
    end

    it "does not enqueue itself again" do
      expect_any_instance_of(described_class).not_to receive(:re_enqueue_job)
      perform_enqueued_jobs(only: described_class) { job }
    end
  end
end
