defmodule ToweropsWeb.Plugs.UpdateSessionActivityTest do
  use ToweropsWeb.ConnCase, async: true

  import Towerops.AccountsFixtures

  alias Towerops.Accounts
  alias ToweropsWeb.Plugs.UpdateSessionActivity

  describe "init/1" do
    test "returns options unchanged" do
      assert UpdateSessionActivity.init([]) == []
      assert UpdateSessionActivity.init(some: :option) == [some: :option]
    end
  end

  describe "call/2" do
    test "returns conn unchanged" do
      conn = Plug.Test.init_test_session(build_conn(), %{})

      result = UpdateSessionActivity.call(conn, [])

      assert result == conn
    end

    test "spawns background task to update session activity" do
      user = user_fixture()
      {token, user_token} = Accounts.generate_user_session_token_with_record(user)

      now = DateTime.utc_now()

      # Create browser session
      {:ok, _session} =
        Accounts.create_browser_session(%{
          user_id: user.id,
          user_token_id: user_token.id,
          device_name: "Test Browser",
          ip_address: "127.0.0.1",
          user_agent: "Mozilla/5.0 Test",
          last_activity_at: now,
          expires_at: DateTime.add(now, 30, :day)
        })

      # Call plug with session token - should spawn background task without blocking
      result =
        build_conn()
        |> Plug.Test.init_test_session(%{user_token: token})
        |> UpdateSessionActivity.call([])

      # Should return immediately (not block on background task)
      assert result
    end

    test "handles missing session token gracefully" do
      build_conn()
      |> Plug.Test.init_test_session(%{})
      |> UpdateSessionActivity.call([])

      # Should not raise an error - test passes if no exception
    end

    test "handles invalid session token gracefully" do
      build_conn()
      |> Plug.Test.init_test_session(%{user_token: "invalid-token-does-not-exist"})
      |> UpdateSessionActivity.call([])

      # Wait for background task to complete
      Process.sleep(100)

      # Should not raise an error - test passes if no exception
    end

    test "does not block the request while updating" do
      user = user_fixture()
      {token, user_token} = Accounts.generate_user_session_token_with_record(user)

      now = DateTime.utc_now()

      {:ok, _session} =
        Accounts.create_browser_session(%{
          user_id: user.id,
          user_token_id: user_token.id,
          device_name: "Test Browser",
          ip_address: "127.0.0.1",
          user_agent: "Mozilla/5.0 Test",
          last_activity_at: now,
          expires_at: DateTime.add(now, 30, :day)
        })

      # Time the request - should be fast even though update happens in background
      start_time = System.monotonic_time(:millisecond)

      build_conn()
      |> Plug.Test.init_test_session(%{user_token: token})
      |> UpdateSessionActivity.call([])

      end_time = System.monotonic_time(:millisecond)
      duration = end_time - start_time

      # Should complete very quickly since update is async
      assert duration < 200
    end

    test "handles nil token gracefully" do
      build_conn()
      |> Plug.Test.init_test_session(%{user_token: nil})
      |> UpdateSessionActivity.call([])

      # Should not raise an error - test passes if no exception
    end
  end
end
