defmodule Microwaveprop.TerrainTest do
  use Microwaveprop.DataCase, async: true

  alias Microwaveprop.Radio.Contact
  alias Microwaveprop.Terrain

  @qso_attrs %{
    station1: "W5XD",
    station2: "K5TR",
    qso_timestamp: ~U[2026-03-28 18:00:00Z],
    mode: "CW",
    band: Decimal.new("1296"),
    pos1: %{"lat" => 32.9, "lon" => -97.0},
    pos2: %{"lat" => 30.3, "lon" => -97.7}
  }

  defp create_contact do
    {:ok, contact} =
      %Contact{}
      |> Contact.changeset(@qso_attrs)
      |> Repo.insert()

    contact
  end

  defp terrain_attrs(contact) do
    %{
      contact_id: contact.id,
      sample_count: 65,
      path_points: [
        %{"lat" => 32.9, "lon" => -97.0, "elev" => 200.0, "dist_km" => 0.0},
        %{"lat" => 30.3, "lon" => -97.7, "elev" => 180.0, "dist_km" => 295.0}
      ],
      verdict: "CLEAR",
      max_elevation_m: 450.0,
      min_clearance_m: 120.0,
      diffraction_db: 0.0,
      fresnel_hit_count: 0,
      obstructed_count: 0
    }
  end

  describe "upsert_terrain_profile/1" do
    test "inserts a new terrain profile" do
      contact = create_contact()
      attrs = terrain_attrs(contact)

      assert {:ok, profile} = Terrain.upsert_terrain_profile(attrs)
      assert profile.contact_id == contact.id
      assert profile.sample_count == 65
      assert profile.verdict == "CLEAR"
    end

    test "upserts on conflict (same contact_id)" do
      contact = create_contact()
      attrs = terrain_attrs(contact)

      {:ok, _} = Terrain.upsert_terrain_profile(attrs)

      updated_attrs = Map.merge(attrs, %{verdict: "BLOCKED", diffraction_db: 6.5})
      {:ok, profile} = Terrain.upsert_terrain_profile(updated_attrs)

      assert profile.verdict == "BLOCKED"
      assert profile.diffraction_db == 6.5
    end
  end

  describe "get_terrain_profile/1" do
    test "returns profile for a QSO" do
      contact = create_contact()
      {:ok, _} = Terrain.upsert_terrain_profile(terrain_attrs(contact))

      profile = Terrain.get_terrain_profile(contact.id)
      assert profile.contact_id == contact.id
    end

    test "returns nil when no profile exists" do
      contact = create_contact()
      assert Terrain.get_terrain_profile(contact.id) == nil
    end
  end

  describe "has_terrain_profile?/1" do
    test "returns true when profile exists" do
      contact = create_contact()
      {:ok, _} = Terrain.upsert_terrain_profile(terrain_attrs(contact))

      assert Terrain.has_terrain_profile?(contact.id)
    end

    test "returns false when no profile exists" do
      contact = create_contact()
      refute Terrain.has_terrain_profile?(contact.id)
    end
  end
end
