require "test_helper"

class Admin::InvitationsControllerTest < ActionDispatch::IntegrationTest
  test "should redirect to login when not authenticated" do
    get admin_invitations_path
    assert_redirected_to login_path
  end

  test "should redirect to root when logged in as non-admin" do
    login_as(users(:contributor_user))
    get admin_invitations_path
    assert_redirected_to root_path
  end

  test "should show invitations index when logged in as admin" do
    login_as(users(:admin_user))
    get admin_invitations_path
    assert_response :success
  end

  test "should get new invitation page when logged in as admin" do
    login_as(users(:admin_user))
    get new_admin_invitation_path
    assert_response :success
    assert_select "form"
    assert_select "input[name='user[email]']"
    assert_select "input[name='user[name]']"
    assert_select "select[name='user[role]']"
    assert_select "select[name='user[primary_language]']"
  end

  test "should display pending invitations on index page" do
    login_as(users(:admin_user))
    get admin_invitations_path
    assert_response :success
    assert_select "h1,h2", /Invitations/
  end

  test "should create invitation when logged in as admin" do
    login_as(users(:admin_user))

    assert_difference("User.count", 1) do
      post admin_invitations_path, params: {
        user: {
          email: "newuser@example.com",
          name: "New User",
          role: "contributor",
          primary_language: "en"
        }
      }
    end

    assert_redirected_to admin_invitations_path

    new_user = User.find_by(email: "newuser@example.com")
    assert_not_nil new_user
    assert_not_nil new_user.invitation_token
    assert_not_nil new_user.invitation_sent_at
    assert_nil new_user.invitation_accepted_at
    assert_equal users(:admin_user).id, new_user.invited_by_id
  end

  test "should send invitation email when creating invitation" do
    login_as(users(:admin_user))

    assert_enqueued_emails 1 do
      post admin_invitations_path, params: {
        user: {
          email: "newuser@example.com",
          name: "New User",
          role: "contributor",
          primary_language: "en"
        }
      }
    end
  end

  test "should not create invitation with invalid data" do
    login_as(users(:admin_user))

    assert_no_difference("User.count") do
      post admin_invitations_path, params: {
        user: {
          email: "",
          name: "New User",
          role: "contributor",
          primary_language: "en"
        }
      }
    end

    assert_response :unprocessable_entity
  end

  test "should cancel pending invitation when logged in as admin" do
    login_as(users(:admin_user))

    assert_difference("User.count", -1) do
      delete admin_invitation_path(users(:pending_invitation))
    end

    assert_redirected_to admin_invitations_path
  end

  test "should not cancel accepted invitation" do
    login_as(users(:admin_user))

    assert_no_difference("User.count") do
      delete admin_invitation_path(users(:contributor_user))
    end

    assert_redirected_to admin_invitations_path
    follow_redirect!
    assert_select ".bg-red-50", /Cannot cancel an accepted invitation/
  end

  test "should not allow non-admin to create invitation" do
    login_as(users(:contributor_user))

    assert_no_difference("User.count") do
      post admin_invitations_path, params: {
        user: {
          email: "newuser@example.com",
          name: "New User",
          role: "contributor",
          primary_language: "en"
        }
      }
    end

    assert_redirected_to root_path
  end

  test "should not allow non-admin to cancel invitation" do
    login_as(users(:contributor_user))

    assert_no_difference("User.count") do
      delete admin_invitation_path(users(:pending_invitation))
    end

    assert_redirected_to root_path
  end
end
