defmodule AprsmeWeb.PacketsLive.CallsignViewTest do
  use AprsmeWeb.ConnCase

  import Aprsme.PacketsFixtures
  import Phoenix.LiveViewTest

  describe "mount" do
    test "renders the page for a callsign with no existing packets", %{conn: conn} do
      {:ok, _view, html} = live(conn, "/packets/NOPACKETS", on_error: :warn)
      assert html =~ "NOPACKETS"
    end

    test "normalizes a lowercase callsign", %{conn: conn} do
      {:ok, _view, html} = live(conn, "/packets/abc1xyz", on_error: :warn)
      assert html =~ "ABC1XYZ"
    end

    test "renders with existing packet in db", %{conn: conn} do
      _packet =
        packet_fixture(%{
          sender: "LIVEPKT-1",
          base_callsign: "LIVEPKT",
          ssid: "1",
          received_at: DateTime.utc_now(),
          lat: Decimal.new("33.0"),
          lon: Decimal.new("-96.0")
        })

      {:ok, _view, html} = live(conn, "/packets/LIVEPKT-1", on_error: :warn)
      assert html =~ "LIVEPKT-1"
    end
  end

  describe "live packet broadcast edge cases" do
    test "broadcasts exceeding 100 packets carry the oldest out of live buffer", %{conn: conn} do
      # Pre-seed a packet so stored=[packet], live=[].
      _p =
        packet_fixture(%{
          sender: "OVERFLOW-1",
          base_callsign: "OVERFLOW",
          ssid: "1",
          received_at: DateTime.utc_now(),
          lat: Decimal.new("33.0"),
          lon: Decimal.new("-96.0")
        })

      {:ok, view, _html} = live(conn, "/packets/OVERFLOW-1", on_error: :warn)

      # Broadcast enough live packets to overflow the 100-packet total.
      for i <- 1..110 do
        payload = %{
          sender: "OVERFLOW-1",
          base_callsign: "OVERFLOW",
          ssid: "1",
          received_at: DateTime.add(DateTime.utc_now(), i, :second),
          data_type: :position,
          destination: "APRS",
          path: "",
          device_identifier: "APRS",
          data_extended: %{symbol_table_id: "/", symbol_code: ">"}
        }

        Phoenix.PubSub.broadcast(
          Aprsme.PubSub,
          "packets:OVERFLOW-1",
          {:postgres_packet, payload}
        )
      end

      Process.sleep(100)
      html = render(view)
      assert html =~ "OVERFLOW-1"
    end

    test "handles broadcast with iso8601 string timestamp", %{conn: conn} do
      {:ok, view, _html} = live(conn, "/packets/STRTIME-1", on_error: :warn)

      payload = %{
        sender: "STRTIME-1",
        base_callsign: "STRTIME",
        ssid: "1",
        received_at: DateTime.to_iso8601(DateTime.utc_now()),
        data_type: :position,
        destination: "APRS",
        path: "",
        data_extended: %{symbol_table_id: "/", symbol_code: ">"}
      }

      Phoenix.PubSub.broadcast(Aprsme.PubSub, "packets:STRTIME-1", {:postgres_packet, payload})
      Process.sleep(30)
      assert render(view) =~ "STRTIME-1"
    end

    test "ignores unknown messages without crashing", %{conn: conn} do
      {:ok, view, _html} = live(conn, "/packets/UNKMSG-1", on_error: :warn)
      send(view.pid, :some_random)
      Process.sleep(20)
      assert Process.alive?(view.pid)
    end
  end

  describe "live packet broadcast" do
    test "handles raw broadcast packet without :data key", %{conn: conn} do
      {:ok, view, _html} = live(conn, "/packets/DB0WUN-13")

      # Simulate a raw broadcast payload (as it arrives from the APRS pipeline)
      # This map does NOT have a :data key — only %Packet{} structs do
      raw_payload = %{
        sender: "DB0WUN-13",
        data_type: :weather,
        destination: "APN000",
        path: "TCPIP*,qAC,T2EISBERG",
        base_callsign: "DB0WUN",
        ssid: "13",
        received_at: DateTime.utc_now(),
        latitude: Decimal.new("50.0001"),
        longitude: Decimal.new("12.1393"),
        temperature: 31,
        humidity: 89,
        wind_speed: 3,
        comment: "232/003g009t031r000p000P000b10215h89L000eMB63",
        device_identifier: "APN000",
        data_extended: %{
          data_type: :weather,
          comment: "232/003g009t031r000p000P000b10215h89L000eMB63",
          latitude: Decimal.new("50.0001"),
          longitude: Decimal.new("12.1393"),
          symbol_code: "_",
          symbol_table_id: "/"
        }
      }

      Phoenix.PubSub.broadcast(Aprsme.PubSub, "packets:DB0WUN-13", {:postgres_packet, raw_payload})

      # Should render without crashing
      html = render(view)
      assert html =~ "DB0WUN-13"
    end
  end
end
