defmodule BerrypodWeb.Setup.RecoverTest do
  use BerrypodWeb.ConnCase, async: false

  import Phoenix.LiveViewTest
  import Berrypod.AccountsFixtures
  import ExUnit.CaptureLog

  alias Berrypod.Setup

  describe "when no admin exists" do
    test "redirects to setup", %{conn: conn} do
      {:ok, _view, html} =
        conn
        |> live(~p"/recover")
        |> follow_redirect(conn, ~p"/setup")

      assert html =~ "Set up your shop"
    end
  end

  describe "when admin exists" do
    setup do
      user = user_fixture()
      %{user: user}
    end

    test "renders recovery page", %{conn: conn} do
      {:ok, _view, html} = live(conn, ~p"/recover")

      assert html =~ "Account recovery"
      assert html =~ "recovery secret has been printed"
      assert html =~ "New password"
    end

    test "logs setup secret on mount", %{conn: conn} do
      log =
        capture_log(fn ->
          {:ok, _view, _html} = live(conn, ~p"/recover")
        end)

      assert log =~ "Account recovery requested"
      assert log =~ Setup.setup_secret()
    end

    test "rejects short password", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/recover")

      html =
        view
        |> form("form", %{recover: %{password: "short"}})
        |> render_submit()

      assert html =~ "at least 12 characters"
    end

    test "resets password and redirects to login", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/recover")

      result =
        view
        |> form("form", %{recover: %{password: "new_password_123"}})
        |> render_submit()

      assert {:error, {:redirect, %{to: "/recover/login/" <> _token}}} = result
    end
  end

  describe "when admin exists (prod mode)" do
    setup do
      original = Application.get_env(:berrypod, :env)
      Application.put_env(:berrypod, :env, :prod)
      user = user_fixture()
      on_exit(fn -> Application.put_env(:berrypod, :env, original) end)
      %{user: user}
    end

    test "shows secret field in prod", %{conn: conn} do
      {:ok, _view, html} = live(conn, ~p"/recover")
      assert html =~ "Setup secret"
    end

    test "rejects wrong secret", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/recover")

      html =
        view
        |> form("form", %{recover: %{secret: "wrong_secret", password: "a_valid_password_123"}})
        |> render_submit()

      assert html =~ "Wrong setup secret"
    end
  end

  describe "when already logged in" do
    setup %{conn: conn} do
      user = user_fixture()
      conn = log_in_user(conn, user)
      %{conn: conn, user: user}
    end

    test "redirects to admin", %{conn: conn} do
      {:ok, _view, _html} =
        conn
        |> live(~p"/recover")
        |> follow_redirect(conn, ~p"/admin")
    end
  end
end
