defmodule WhoNeedHelpWeb.UserRegistrationControllerTest do
  use WhoNeedHelpWeb.ConnCase, async: true

  import WhoNeedHelp.AccountsFixtures
  import Swoosh.TestAssertions

  describe "GET /users/register" do
    test "renders registration page", %{conn: conn} do
      conn = get(conn, ~p"/users/register")
      response = html_response(conn, 200)
      assert get_resp_header(conn, "cache-control") == ["no-store"]
      assert response =~ "Register"
      assert response =~ ~p"/users/log-in"
      assert response =~ ~p"/users/register"
      assert response =~ "A password is not required"
      assert response =~ "Sign up with Google"
      assert response =~ ~p"/auth/google/register"
      assert response =~ "I am 18 or older and accept the Terms and Safety Rules"
      assert response =~ ~s(href="/terms")
      assert response =~ ~s(href="/privacy")
      assert response =~ ~s(href="/safety")
    end

    test "redirects if already logged in", %{conn: conn} do
      conn = conn |> log_in_user(user_fixture()) |> get(~p"/users/register")

      assert redirected_to(conn) == ~p"/"
    end
  end

  describe "POST /users/register" do
    test "returns bad request for malformed parameters", %{conn: conn} do
      conn = post(conn, ~p"/users/register", %{"user" => "invalid"})

      assert html_response(conn, 400) =~ "The registration form is invalid."
      assert get_resp_header(conn, "cache-control") == ["no-store"]
    end

    test "renders validation errors when email has a forged nested type", %{conn: conn} do
      conn =
        post(conn, ~p"/users/register", %{
          "user" => %{
            "email" => %{"nested" => "value"},
            "display_name" => "Malformed email",
            "locale" => "en",
            "terms_accepted" => "true"
          }
        })

      assert html_response(conn, 200) =~ "blank"
      refute get_session(conn, :user_token)
    end

    @tag :capture_log
    test "creates account but does not log in", %{conn: conn} do
      email = unique_user_email()

      conn =
        post(conn, ~p"/users/register", %{
          "user" => valid_user_attributes(email: email)
        })

      refute get_session(conn, :user_token)
      assert redirected_to(conn) == ~p"/users/log-in"

      assert conn.assigns.flash["info"] =~
               "If this address can be registered or signed in, login instructions will arrive shortly."

      assert_email_sent()
    end

    test "does not reveal whether a valid email is already registered", %{conn: conn} do
      user = user_fixture()
      params = %{"user" => valid_user_attributes(email: user.email)}

      existing_conn = post(conn, ~p"/users/register", params)

      assert redirected_to(existing_conn) == ~p"/users/log-in"

      assert existing_conn.assigns.flash["info"] ==
               "If this address can be registered or signed in, login instructions will arrive shortly."

      assert_email_sent(fn email ->
        Enum.any?(email.to, fn {_name, address} -> address == user.email end)
      end)
    end

    test "render errors for invalid data", %{conn: conn} do
      conn =
        post(conn, ~p"/users/register", %{
          "user" => %{"email" => "with spaces"}
        })

      response = html_response(conn, 200)
      assert response =~ "Register"
      assert response =~ "must have the @ sign and no spaces"
    end
  end
end
