require "test_helper"

class Admin::RequestsControllerTest < ActionDispatch::IntegrationTest
  setup do
    @admin = users(:admin_user)
    @requested_entry = entries(:requested_entry)
    @approved_entry = entries(:approved_entry)
    login_as(@admin)
  end

  test "should require admin authentication" do
    logout
    get admin_requests_path
    assert_redirected_to login_path
  end

  test "should show requests index" do
    get admin_requests_path

    assert_response :success
    assert_select "h1", "Entry Requests"
    assert_select "h2", /Pending Review/
    assert_select "h2", /Approved/
  end

  test "should list requested entries" do
    get admin_requests_path

    assert_response :success
    assert_select "td", text: @requested_entry.fi
    assert_select "a[href=?]", admin_request_path(@requested_entry)
  end

  test "should list approved entries" do
    get admin_requests_path

    assert_response :success
    assert_select "td", text: @approved_entry.fi
  end

  test "should show request details" do
    get admin_request_path(@requested_entry)

    assert_response :success
    assert_select "h1", "Entry Request Details"
    assert_select "div", text: @requested_entry.fi
    assert_select "div", text: @requested_entry.en
    assert_select "span", text: @requested_entry.requested_by.name
  end

  test "should show edit form for requested entry" do
    get edit_admin_request_path(@requested_entry)

    assert_response :success
    assert_select "h1", "Edit Entry Request"
    assert_select "form[action=?]", admin_request_path(@requested_entry)
    assert_select "input[name='entry[fi]'][value=?]", @requested_entry.fi
  end

  test "should update entry details" do
    patch admin_request_path(@requested_entry), params: {
      entry: {
        category: "phrase",
        fi: "päivitetty sana",
        en: "updated word",
        notes: "Updated notes"
      }
    }

    @requested_entry.reload
    assert_equal "phrase", @requested_entry.category
    assert_equal "päivitetty sana", @requested_entry.fi
    assert_equal "updated word", @requested_entry.en
    assert_equal "Updated notes", @requested_entry.notes
    assert_redirected_to admin_request_path(@requested_entry)
    assert_equal "Request updated successfully.", flash[:notice]
  end

  test "should not update with invalid data" do
    patch admin_request_path(@requested_entry), params: {
      entry: {
        fi: "",
        en: "",
        sv: "",
        no: "",
        ru: "",
        de: ""
      }
    }

    assert_response :unprocessable_entity
    @requested_entry.reload
    assert_equal "testisana", @requested_entry.fi  # Unchanged
  end

  test "should approve request and send invitation" do
    user = @requested_entry.requested_by
    assert_nil user.invitation_token
    assert_nil user.invitation_sent_at

    assert_enqueued_emails 1 do
      post approve_admin_request_path(@requested_entry)
    end

    user.reload
    @requested_entry.reload

    assert_equal "approved", @requested_entry.status
    assert_not_nil user.invitation_token
    assert_not_nil user.invitation_sent_at
    assert_equal @admin, user.invited_by
    assert_redirected_to admin_requests_path
    assert_match(/invitation sent/i, flash[:notice])
  end

  test "should not approve already approved entry" do
    # Try to approve an already approved entry
    user = @approved_entry.requested_by

    post approve_admin_request_path(@approved_entry)

    @approved_entry.reload
    assert_equal "approved", @approved_entry.status
  end

  test "should reject request and delete entry and user" do
    user = @requested_entry.requested_by
    entry_id = @requested_entry.id
    user_id = user.id

    assert_difference("Entry.count", -1) do
      assert_difference("User.count", -1) do
        delete reject_admin_request_path(@requested_entry)
      end
    end

    assert_not Entry.exists?(entry_id)
    assert_not User.exists?(user_id)
    assert_redirected_to admin_requests_path
    assert_match(/rejected and deleted/i, flash[:notice])
  end

  test "should reject but not delete user with multiple entries" do
    user = @requested_entry.requested_by

    # Create another entry for the same user
    another_entry = Entry.create!(
      category: :word,
      fi: "toinen sana",
      en: "another word",
      status: :requested,
      requested_by: user
    )

    assert_difference("Entry.count", -1) do
      assert_no_difference("User.count") do
        delete reject_admin_request_path(@requested_entry)
      end
    end

    assert User.exists?(user.id)
    assert Entry.exists?(another_entry.id)
  end

  test "contributors should not access admin requests" do
    logout
    contributor = users(:contributor_user)
    login_as(contributor)

    get admin_requests_path
    assert_redirected_to root_path
    assert_match(/administrator/i, flash[:alert])
  end

  test "reviewers should not access admin requests" do
    logout
    reviewer = users(:reviewer_user)
    login_as(reviewer)

    get admin_requests_path
    assert_redirected_to root_path
    assert_match(/administrator/i, flash[:alert])
  end
end
