defmodule Towerops.Accounts.GrantSudoModeTest do
  use Towerops.DataCase, async: true

  import Towerops.AccountsFixtures

  alias Towerops.Accounts
  alias Towerops.Accounts.User
  alias Towerops.Admin

  describe "grant_sudo_mode/1" do
    test "updates user's last_sudo_at timestamp" do
      user = user_fixture()
      assert is_nil(user.last_sudo_at)

      {:ok, updated_user} = Accounts.grant_sudo_mode(user)

      assert %DateTime{} = updated_user.last_sudo_at
      assert DateTime.diff(DateTime.utc_now(), updated_user.last_sudo_at, :second) < 2
    end

    test "updates an already set last_sudo_at timestamp" do
      user = user_fixture()

      # First grant
      {:ok, user_with_sudo} = Accounts.grant_sudo_mode(user)
      first_timestamp = user_with_sudo.last_sudo_at

      # Wait to ensure different timestamp (at least 1 second)
      Process.sleep(1100)

      # Second grant should update the timestamp
      {:ok, updated_user} = Accounts.grant_sudo_mode(user_with_sudo)
      assert DateTime.after?(updated_user.last_sudo_at, first_timestamp)
    end

    test "validates changeset" do
      user = user_fixture()

      # Test the changeset validation directly
      changeset = User.sudo_changeset(user, %{})
      refute changeset.valid?
      assert "can't be blank" in errors_on(changeset).last_sudo_at
    end

    test "creates audit log entry when sudo mode is granted" do
      user = user_fixture()

      # Verify no audit logs exist before
      logs_before = Admin.list_audit_logs_for_user(user.id)
      assert Enum.empty?(logs_before)

      # Grant sudo mode
      {:ok, updated_user} = Accounts.grant_sudo_mode(user)

      # Verify audit log was created
      logs_after = Admin.list_audit_logs_for_user(user.id)
      assert length(logs_after) == 1

      [log] = logs_after
      assert log.action == "sudo_mode_granted"
      assert log.superuser_id == user.id
      assert log.target_user_id == user.id
      assert log.metadata["granted_at"]

      # Verify the granted_at timestamp matches the user's last_sudo_at
      granted_at = log.metadata["granted_at"] |> DateTime.from_iso8601() |> elem(1)
      assert DateTime.diff(granted_at, updated_user.last_sudo_at, :second) == 0
    end
  end
end
