require "test_helper"

class RequestsControllerTest < ActionDispatch::IntegrationTest
  test "should show new request form for anonymous users" do
    get new_request_path

    assert_response :success
    assert_select "h1", "Request a New Entry"
    assert_select "form"
    assert_select "input[name='entry[name]']"
    assert_select "input[name='entry[email]']"
    assert_select "select[name='entry[category]']"
  end

  test "should show new request form for logged-in users without name/email fields" do
    login_as(users(:contributor_user))
    get new_request_path

    assert_response :success
    assert_select "h1", "Request a New Entry"
    assert_select "form"
    assert_select "input[name='entry[name]']", count: 0
    assert_select "input[name='entry[email]']", count: 0
    assert_select ".bg-blue-50", text: /Submitting as/
  end

  test "should create entry request with valid data" do
    assert_difference([ "User.count", "Entry.count" ], 1) do
      post requests_path, params: {
        entry: {
          name: "New Requester",
          email: "newrequester@example.com",
          category: "word",
          fi: "uusi sana",
          en: "new word",
          notes: "Please add this word"
        }
      }
    end

    entry = Entry.last
    user = User.last

    assert_equal "requested", entry.status
    assert_equal user, entry.requested_by
    assert_equal "New Requester", user.name
    assert_equal "newrequester@example.com", user.email
    assert_equal "contributor", user.role
    assert_nil user.invitation_token
    assert_redirected_to root_path
    assert_match(/thank you for your request/i, flash[:notice])
  end

  test "should require at least one translation" do
    assert_no_difference([ "User.count", "Entry.count" ]) do
      post requests_path, params: {
        entry: {
          name: "New Requester",
          email: "newrequester@example.com",
          category: "word",
          notes: "No translations provided"
        }
      }
    end

    assert_response :unprocessable_entity
    assert_select ".bg-red-50", text: /At least one language translation is required/
  end

  test "should redirect to login if email already exists" do
    existing_user = users(:contributor_user)

    assert_no_difference([ "User.count", "Entry.count" ]) do
      post requests_path, params: {
        entry: {
          name: "Test User",
          email: existing_user.email,
          category: "word",
          fi: "sana",
          en: "word"
        }
      }
    end

    assert_redirected_to login_path
    assert_equal "An account with this email already exists. Please log in.", flash[:alert]
  end

  test "should show pending count for email with existing requests" do
    requester = users(:requester_user)
    get new_request_path, params: { email: requester.email }

    assert_response :success
    # User has one requested entry from fixtures
    assert_select ".bg-blue-50", text: /1 pending request/
  end

  test "should create entry with only one translation" do
    assert_difference([ "User.count", "Entry.count" ], 1) do
      post requests_path, params: {
        entry: {
          name: "Single Translation",
          email: "single@example.com",
          category: "word",
          fi: "vain suomeksi"
        }
      }
    end

    entry = Entry.last
    assert_equal "vain suomeksi", entry.fi
    assert_nil entry.en
    assert_nil entry.sv
    assert_redirected_to root_path
  end

  test "should create entry with multiple translations" do
    assert_difference([ "User.count", "Entry.count" ], 1) do
      post requests_path, params: {
        entry: {
          name: "Multi Lingual",
          email: "multilingual@example.com",
          category: "phrase",
          fi: "hyvää päivää",
          en: "good day",
          sv: "god dag",
          no: "god dag",
          ru: "добрый день",
          de: "guten Tag"
        }
      }
    end

    entry = Entry.last
    assert_equal "hyvää päivää", entry.fi
    assert_equal "good day", entry.en
    assert_equal "god dag", entry.sv
    assert_equal "god dag", entry.no
    assert_equal "добрый день", entry.ru
    assert_equal "guten Tag", entry.de
    assert_redirected_to root_path
  end

  test "logged-in user can submit request without providing name/email" do
    user = users(:contributor_user)
    login_as(user)

    assert_no_difference("User.count") do
      assert_difference("Entry.count", 1) do
        post requests_path, params: {
          entry: {
            category: "word",
            fi: "kirjautunut käyttäjä",
            en: "logged in user"
          }
        }
      end
    end

    entry = Entry.last
    assert_equal user, entry.requested_by
    assert_equal "requested", entry.status
    assert_redirected_to root_path
    assert_match(/thank you for your request/i, flash[:notice])
  end

  test "should not modify existing user when they submit request" do
    user = users(:contributor_user)
    original_name = user.name
    original_updated_at = user.updated_at
    login_as(user)

    post requests_path, params: {
      entry: {
        category: "word",
        fi: "testi"
      }
    }

    user.reload
    assert_equal original_name, user.name
    assert_equal original_updated_at.to_i, user.updated_at.to_i
  end

  test "should reuse existing pending user without modifying them" do
    # Create a user without accepted invitation
    existing_user = User.create!(
      name: "Pending User",
      email: "pending_test@example.com",
      password: SecureRandom.alphanumeric(32),
      role: :contributor
    )
    original_name = existing_user.name
    original_updated_at = existing_user.updated_at

    # Create first entry
    Entry.create!(
      category: :word,
      fi: "first",
      status: :requested,
      requested_by: existing_user
    )

    # Submit second request with same email but different name
    assert_no_difference("User.count") do
      assert_difference("Entry.count", 1) do
        post requests_path, params: {
          entry: {
            name: "Different Name",  # This should be ignored
            email: existing_user.email,
            category: "word",
            fi: "second"
          }
        }
      end
    end

    existing_user.reload
    assert_equal original_name, existing_user.name  # Name should not change
    assert_equal original_updated_at.to_i, existing_user.updated_at.to_i  # Should not be updated
    assert_equal 2, existing_user.requested_entries.count
  end
end
