defmodule AprsmeWeb.PageControllerUptimeTest do
  @moduledoc """
  Direct tests for the four `format_uptime_parts/4` branches in PageController.

  We can't call the private function directly. Instead, register a fake
  `Aprsme.Is` process that responds to `:get_status` with a chosen
  `uptime_seconds`, then hit the controller and check the formatted string.
  """
  use AprsmeWeb.ConnCase, async: false

  defmodule FakeIs do
    @moduledoc false
    use GenServer

    def start_link(uptime_seconds) do
      GenServer.start_link(__MODULE__, uptime_seconds, name: Aprsme.Is)
    end

    @impl true
    def init(uptime_seconds), do: {:ok, uptime_seconds}

    @impl true
    def handle_call(:get_status, _from, uptime_seconds) do
      now = DateTime.utc_now()
      connected_at = DateTime.add(now, -uptime_seconds, :second)

      reply = %{
        connected: true,
        server: "test.local",
        port: 14_580,
        connected_at: connected_at,
        uptime_seconds: uptime_seconds,
        login_id: "N0CALL",
        filter: "r/0/0/100",
        packet_stats: %{total_packets: 0, packets_per_second: 0, last_packet_at: nil},
        stored_packet_count: 0,
        oldest_packet_timestamp: nil
      }

      {:reply, reply, uptime_seconds}
    end
  end

  setup do
    # The real Aprsme.Is doesn't start in :test env, so the name is free.
    # Defensive: if some prior test registered something under it, unregister.
    if pid = Process.whereis(Aprsme.Is) do
      :erlang.unregister(Aprsme.Is)
      _ = pid
    end

    original_cluster = Application.get_env(:aprsme, :cluster_enabled)
    Application.put_env(:aprsme, :cluster_enabled, false)

    on_exit(fn -> Application.put_env(:aprsme, :cluster_enabled, original_cluster) end)
    :ok
  end

  defp call_with_uptime(uptime_seconds) do
    {:ok, fake} = FakeIs.start_link(uptime_seconds)

    try do
      conn = Phoenix.ConnTest.build_conn()
      result = AprsmeWeb.PageController.status_json(conn, %{})
      Jason.decode!(result.resp_body)
    after
      if Process.alive?(fake), do: GenServer.stop(fake)
    end
  end

  describe "format_uptime branches via status_json" do
    test "formats multi-day uptime as 'Xd Yh Zm Ss'" do
      body = call_with_uptime(2 * 86_400 + 3 * 3600 + 15 * 60 + 5)
      display = body["aprs_is"]["uptime_display"]
      assert display =~ ~r/^\d+d \d+h \d+m \d+s$/
      assert String.starts_with?(display, "2d ")
    end

    test "formats sub-day, multi-hour uptime as 'Yh Zm Ss'" do
      body = call_with_uptime(5 * 3600 + 30 * 60 + 12)
      display = body["aprs_is"]["uptime_display"]
      assert display =~ ~r/^\d+h \d+m \d+s$/
      refute display =~ "d "
    end

    test "formats sub-hour, multi-minute uptime as 'Zm Ss'" do
      body = call_with_uptime(30 * 60 + 7)
      display = body["aprs_is"]["uptime_display"]
      assert display =~ ~r/^\d+m \d+s$/
      refute display =~ "h "
    end

    test "formats sub-minute uptime as 'Ss'" do
      body = call_with_uptime(45)
      display = body["aprs_is"]["uptime_display"]
      assert display =~ ~r/^\d+s$/
      refute display =~ "m "
    end
  end
end
