require 'rails_helper'

RSpec.describe "Devise login sessions", type: :request do
  let(:user) { create :user, cn: 'fiatjaf', ou: 'kosmos.org' }
  let(:auth_event) { JSON.parse(File.read("#{Rails.root}/spec/fixtures/nostr/valid_auth_event.json")) }

  before do
    login_as user, :scope => :user

    allow_any_instance_of(User).to receive(:dn)
      .and_return("cn=#{user.cn},ou=kosmos.org,cn=users,dc=kosmos,dc=org")
    allow_any_instance_of(User).to receive(:nostr_pubkey).and_return(nil)

    allow(LdapManager::FetchUserByNostrKey).to receive(:call).with(
      pubkey: "07e188a1ff87ce171d517b8ed2bb7a31b1d3453a0db3b15379ec07b724d232f3"
    ).and_return(nil)
  end

  describe "POST /users/nostr_login" do
    before do
      session_stub = { shared_secret: "YMeTyOxIEJcfe6vd" }
      allow_any_instance_of(Users::SessionsController).to receive(:session).and_return(session_stub)
    end

    context "With key configured for an account" do
      before do
        expect(LdapManager::FetchUserByNostrKey).to receive(:call).with(
          pubkey: "07e188a1ff87ce171d517b8ed2bb7a31b1d3453a0db3b15379ec07b724d232f3"
        ).and_return(user)

        post users_nostr_login_path,
          params: { signed_event: auth_event }.to_json,
          headers: {
            "CONTENT_TYPE" => "application/json",
            "HTTP_ACCEPT" => "application/json"
          }
      end

      it "returns a success status" do
        expect(response).to have_http_status(200)
      end
    end

    context "With wrong site tag" do
      before do
        Setting.accounts_domain = "accounts.wikipedia.org"
        expect(LdapManager::FetchUserByNostrKey).not_to receive(:call)

        post users_nostr_login_path,
          params: { signed_event: auth_event }.to_json,
          headers: {
            "CONTENT_TYPE" => "application/json",
            "HTTP_ACCEPT" => "application/json"
          }
      end

      after do
        Setting.accounts_domain = "accounts.kosmos.org"
      end

      it "returns a 422 status" do
        expect(response).to have_http_status(401)
      end

      it "informs the user about the failure" do
        expect(flash[:alert]).to eq("Login verification failed")
      end
    end

    context "With wrong shared secret" do
      before do
        session_stub = { shared_secret: "ho-chi-minh" }
        allow_any_instance_of(Users::SessionsController).to receive(:session).and_return(session_stub)

        expect(LdapManager::FetchUserByNostrKey).not_to receive(:call)

        post users_nostr_login_path,
          params: { signed_event: auth_event }.to_json,
          headers: {
            "CONTENT_TYPE" => "application/json",
            "HTTP_ACCEPT" => "application/json"
          }
      end

      it "returns a 422 status" do
        expect(response).to have_http_status(401)
      end

      it "informs the user about the failure" do
        expect(flash[:alert]).to eq("Login verification failed")
      end
    end
  end
end
