defmodule Symbiont.HeartbeatTest do
  use ExUnit.Case, async: false
  import Symbiont.TestHelpers

  @moduletag :capture_log

  setup do
    tmp_dir = Path.join(System.tmp_dir!(), "symbiont_hb_test_#{:rand.uniform(999_999)}")
    File.mkdir_p!(tmp_dir)

    stop_all_services()
    ensure_task_supervisor()

    Application.put_env(:symbiont, :data_dir, tmp_dir)
    Application.put_env(:symbiont, :heartbeat_interval_ms, :timer.hours(24))

    {:ok, _} = Symbiont.Ledger.start_link(data_dir: tmp_dir)
    {:ok, _} = Symbiont.Queue.start_link(data_dir: tmp_dir)
    {:ok, _} = Symbiont.Heartbeat.start_link([])

    on_exit(fn ->
      stop_all_services()
      File.rm_rf!(tmp_dir)
    end)

    %{tmp_dir: tmp_dir}
  end

  test "pulse returns a health snapshot" do
    snapshot = Symbiont.Heartbeat.pulse()

    assert snapshot["status"] == "healthy"
    assert is_integer(snapshot["queue_size"])
    assert snapshot["queue_size"] == 0
    assert snapshot["tasks_processed"] == 0
    assert snapshot["timestamp"] != nil
  end

  test "pulse logs to heartbeat.jsonl", %{tmp_dir: tmp_dir} do
    _snapshot = Symbiont.Heartbeat.pulse()

    path = Path.join(tmp_dir, "heartbeat.jsonl")
    content = File.read!(path)
    assert String.contains?(content, "healthy")

    lines = content |> String.split("\n", trim: true)
    assert length(lines) >= 1
  end

  test "last_snapshot returns nil before first heartbeat" do
    snapshot = Symbiont.Heartbeat.last_snapshot()
    assert is_nil(snapshot) or is_map(snapshot)
  end

  test "pulse processes queued tasks" do
    {:ok, _} = Symbiont.Queue.enqueue("Test task 1")
    {:ok, _} = Symbiont.Queue.enqueue("Test task 2")
    assert Symbiont.Queue.size() == 2

    snapshot = Symbiont.Heartbeat.pulse()
    assert snapshot["tasks_processed"] == 2

    assert Symbiont.Queue.size() == 0
  end
end
