defmodule MvWeb.ProfileNavigationTest do
  use MvWeb.ConnCase, async: true
  import Phoenix.LiveViewTest

  setup do
    system_actor = Mv.Helpers.SystemActor.get_system_actor()
    %{actor: system_actor}
  end

  describe "profile navigation" do
    test "clicking profile button redirects to current user profile", %{conn: conn} do
      # User needs a role with page permission for "/" (e.g. admin)
      user = Mv.Fixtures.user_with_role_fixture("admin")
      conn = conn_with_password_user(conn, user)
      {:ok, view, _html} = live(conn, "/")

      # Click the profile button
      view |> element("a", "Profil") |> render_click()

      # Verify we're on the profile page
      assert_redirected(view, "/users/#{user.id}")
    end

    test "profile navigation shows correct user data", %{conn: conn, actor: actor} do
      # User with password (from create_test_user) and admin role so they can access "/"
      user = create_test_user(%{email: "test@example.com"})
      admin_role = Mv.Fixtures.role_fixture("admin")

      {:ok, user} =
        user
        |> Ash.Changeset.for_update(:update, %{})
        |> Ash.Changeset.manage_relationship(:role, admin_role, type: :append_and_remove)
        |> Ash.update(actor: actor)

      user = Ash.load!(user, :role, domain: Mv.Accounts, actor: actor)
      conn = conn_with_password_user(conn, user)

      # Navigate to profile
      {:ok, view, _html} = live(conn, "/")
      view |> element("a", "Profil") |> render_click()

      # Verify profile data
      {:ok, _profile_view, html} = live(conn, "/users/#{user.id}")
      assert html =~ to_string(user.email)
      assert html =~ "Password Authentication"
      assert html =~ "Enabled"
    end
  end

  describe "sidebar" do
    test "renders profile button with correct attributes", %{conn: conn} do
      # User needs a role with page permission for "/"
      user = Mv.Fixtures.user_with_role_fixture("admin")
      conn = conn_with_password_user(conn, user)
      {:ok, _view, html} = live(conn, "/")

      assert html =~ ~s(role="button")
      assert html =~ "dropdown-content"
      assert html =~ "avatar"
      assert html =~ "Profil"
    end

    @tag :skip
    # credo:disable-for-next-line Credo.Check.Design.TagTODO
    # TODO: Implement user initials in navbar avatar - see issue #170
    test "shows user initials in avatar", %{conn: conn} do
      # Setup: Create and login a user
      user = create_test_user(%{email: "test.user@example.com"})
      conn = conn_with_password_user(conn, user)
      {:ok, _view, html} = live(conn, "/")

      # Initials from test.user@example.com
      assert html =~ "<span>TU</span>"
    end
  end

  describe "profile navigation with OIDC user" do
    test "shows correct profile data for OIDC user", %{conn: conn, actor: actor} do
      # Setup: Create OIDC user with sub claim
      user_info = %{
        "sub" => "oidc_123",
        "preferred_username" => "oidc.user@example.com"
      }

      oauth_tokens = %{
        "access_token" => "test_token",
        "id_token" => "test_id_token"
      }

      user =
        Mv.Accounts.User
        |> Ash.Changeset.for_create(:register_with_rauthy, %{
          user_info: user_info,
          oauth_tokens: oauth_tokens
        })
        |> Ash.create!(domain: Mv.Accounts, actor: actor)

      # Assign role so user can access "/" (page permission)
      admin_role = Mv.Fixtures.role_fixture("admin")

      {:ok, user_with_role} =
        user
        |> Ash.Changeset.for_update(:update, %{})
        |> Ash.Changeset.manage_relationship(:role, admin_role, type: :append_and_remove)
        |> Ash.update(actor: actor)

      user_with_role = Ash.load!(user_with_role, :role, domain: Mv.Accounts, actor: actor)

      # Login user via OIDC
      conn = sign_in_user_via_oidc(conn, user_with_role)

      # Navigate to home and click profile
      {:ok, view, _html} = live(conn, "/")
      view |> element("a", "Profil") |> render_click()

      # Verify we're on the correct profile page with OIDC specific information
      {:ok, _profile_view, html} = live(conn, "/users/#{user_with_role.id}")
      assert html =~ to_string(user_with_role.email)
      # Password auth should be disabled for OIDC users
      assert html =~ "Not enabled"
    end

    test "profile navigation works across different authentication methods", %{
      conn: conn,
      actor: actor
    } do
      # Users need a role with page permission for "/"
      password_user = Mv.Fixtures.user_with_role_fixture("admin")

      # Create OIDC user and assign admin role
      user_info = %{
        "sub" => "oidc_789",
        "preferred_username" => "oidc@example.com"
      }

      oauth_tokens = %{
        "access_token" => "test_token",
        "id_token" => "test_id_token"
      }

      oidc_user =
        Mv.Accounts.User
        |> Ash.Changeset.for_create(:register_with_rauthy, %{
          user_info: user_info,
          oauth_tokens: oauth_tokens
        })
        |> Ash.create!(domain: Mv.Accounts, actor: actor)

      admin_role = Mv.Fixtures.role_fixture("admin")

      {:ok, oidc_user_with_role} =
        oidc_user
        |> Ash.Changeset.for_update(:update, %{})
        |> Ash.Changeset.manage_relationship(:role, admin_role, type: :append_and_remove)
        |> Ash.update(actor: actor)

      oidc_user_with_role =
        Ash.load!(oidc_user_with_role, :role, domain: Mv.Accounts, actor: actor)

      # Test with password user
      conn_password = conn_with_password_user(conn, password_user)
      {:ok, view_password, _html} = live(conn_password, "/")
      view_password |> element("a", "Profil") |> render_click()
      assert_redirected(view_password, "/users/#{password_user.id}")

      # Test with OIDC user
      conn_oidc = sign_in_user_via_oidc(conn, oidc_user_with_role)
      {:ok, view_oidc, _html} = live(conn_oidc, "/")
      view_oidc |> element("a", "Profil") |> render_click()
      assert_redirected(view_oidc, "/users/#{oidc_user_with_role.id}")
    end
  end

  describe "authenticated views" do
    # User must have a role with page permission to access /members, /users, etc.
    setup %{conn: conn} do
      user = Mv.Fixtures.user_with_role_fixture("admin")
      conn = conn_with_password_user(conn, user)
      {:ok, conn: conn, user: user}
    end

    @authenticated_paths [
      "/",
      "/members",
      "/members/new",
      "/users",
      "/users/new"
    ]

    for path <- @authenticated_paths do
      @path path
      test "layout shows user data on #{path}", %{conn: conn, user: user} do
        {:ok, _view, html} = live(conn, @path)
        # The navbar (which requires current_user) should be visible
        assert html =~ "navbar"
        # Profile button should be visible
        assert html =~ "Profil"
        # User ID should be in profile link
        assert html =~ ~p"/users/#{user.id}"
      end
    end

    test "layout shows user data on user profile page", %{conn: conn, user: user} do
      {:ok, _view, html} = live(conn, ~p"/users/#{user.id}")
      # The sidebar (which requires current_user) should be visible
      assert html =~ "sidebar"
      # Profile button should be visible
      assert html =~ "Profil"
      # User ID should be in profile link
      assert html =~ ~p"/users/#{user.id}"
    end
  end
end
