defmodule BerrypodWeb.Admin.AccountTest do
  use BerrypodWeb.ConnCase, async: false

  import Phoenix.LiveViewTest
  import Berrypod.AccountsFixtures

  alias Berrypod.Accounts

  setup do
    user = user_fixture()
    %{user: user}
  end

  describe "unauthenticated" do
    test "redirects to login", %{conn: conn} do
      {:error, redirect} = live(conn, ~p"/admin/account")
      assert {:redirect, %{to: path}} = redirect
      assert path == ~p"/users/log-in"
    end
  end

  describe "account page" do
    setup %{conn: conn, user: user} do
      conn = log_in_user(conn, user)
      %{conn: conn, user: user}
    end

    test "renders email and password forms", %{conn: conn, user: user} do
      {:ok, view, html} = live(conn, ~p"/admin/account")

      assert html =~ "Account"
      assert html =~ user.email
      assert has_element?(view, "#email_form")
      assert has_element?(view, "#password_form")
    end

    test "validates email change", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/account")

      result =
        view
        |> element("#email_form")
        |> render_change(%{"user" => %{"email" => "with spaces"}})

      assert result =~ "must have the @ sign and no spaces"
    end

    test "submits email change", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/account")

      result =
        view
        |> form("#email_form", %{"user" => %{"email" => unique_user_email()}})
        |> render_submit()

      assert result =~ "A link to confirm your email"
    end

    test "validates password", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/account")

      result =
        view
        |> element("#password_form")
        |> render_change(%{
          "user" => %{
            "password" => "short",
            "password_confirmation" => "mismatch"
          }
        })

      assert result =~ "should be at least 12 character(s)"
    end

    test "submits valid password change", %{conn: conn, user: user} do
      new_password = valid_user_password()
      {:ok, view, _html} = live(conn, ~p"/admin/account")

      form =
        form(view, "#password_form", %{
          "user" => %{
            "email" => user.email,
            "password" => new_password,
            "password_confirmation" => new_password
          }
        })

      render_submit(form)
      new_password_conn = follow_trigger_action(form, conn)

      assert redirected_to(new_password_conn) == ~p"/admin/account"
      assert Accounts.get_user_by_email_and_password(user.email, new_password)
    end
  end

  describe "two-factor authentication" do
    setup %{conn: conn, user: user} do
      conn = log_in_user(conn, user)
      %{conn: conn, user: user}
    end

    test "shows 2FA section", %{conn: conn} do
      {:ok, _view, html} = live(conn, ~p"/admin/account")

      assert html =~ "Two-factor authentication"
      assert html =~ "Off"
      assert html =~ "Enable 2FA"
    end

    test "shows enabled state when TOTP is enabled", %{conn: conn, user: user} do
      # Enable TOTP for the user
      secret = NimbleTOTP.secret()
      code = NimbleTOTP.verification_code(secret)
      {:ok, _user, _codes} = Accounts.enable_totp(user, secret, code)

      {:ok, _view, html} = live(conn, ~p"/admin/account")

      assert html =~ "Two-factor authentication"
      assert html =~ "Enabled"
      assert html =~ "Disable 2FA"
    end
  end
end
