defmodule Towerops.Monitoring.PingTest do
  use ExUnit.Case, async: true

  alias Towerops.Monitoring.Ping

  describe "ping/2" do
    @tag :integration
    test "successfully pings localhost" do
      assert {:ok, response_time} = Ping.ping("127.0.0.1")
      assert is_integer(response_time)
      assert response_time >= 0
    end

    @tag :integration
    test "uses default timeout of 5000ms" do
      # Test that ping works without explicit timeout
      assert {:ok, _response_time} = Ping.ping("127.0.0.1")
    end

    @tag :integration
    test "accepts custom timeout" do
      assert {:ok, _response_time} = Ping.ping("127.0.0.1", 1000)
    end

    test "returns error for unreachable host" do
      # Use an address that should be unreachable
      # 192.0.2.0/24 is TEST-NET-1, reserved for documentation
      assert {:error, _reason} = Ping.ping("192.0.2.1", 1000)
    end

    test "returns error for invalid IP address" do
      # Invalid IP address should fail
      assert {:error, _reason} = Ping.ping("999.999.999.999", 1000)
    end

    @tag :integration
    test "calculates response time" do
      # Ping should complete in reasonable time
      {:ok, response_time} = Ping.ping("127.0.0.1", 5000)

      # Response time should be positive and reasonable (< 5 seconds)
      assert response_time > 0
      assert response_time < 5000
    end

    @tag :integration
    test "handles timeout correctly" do
      # Very short timeout should likely fail or be very fast
      result = Ping.ping("127.0.0.1", 1)

      case result do
        {:ok, time} -> assert time >= 0
        {:error, _} -> assert true
      end
    end

    @tag :integration
    test "minimum timeout is 1 second" do
      # Even with 0ms timeout, should use minimum of 1 second
      result = Ping.ping("127.0.0.1", 0)
      assert {:ok, _} = result
    end

    @tag :integration
    test "respects different OS types" do
      # This test just ensures the OS detection doesn't crash
      case :os.type() do
        {:unix, :darwin} ->
          assert {:ok, _} = Ping.ping("127.0.0.1")

        {:unix, _} ->
          assert {:ok, _} = Ping.ping("127.0.0.1")

        {:win32, _} ->
          assert {:ok, _} = Ping.ping("127.0.0.1")
      end
    end
  end
end
