defmodule Microwaveprop.Weather.FrontalAnalysisTest do
  use ExUnit.Case, async: true

  alias Microwaveprop.Weather.FrontalAnalysis

  @grid_spec %{lat_start: 30.0, lat_step: 0.5, lon_start: -100.0, lon_step: 0.5}

  describe "detect_fronts/3" do
    test "finds no fronts in a uniform temperature field" do
      # 10x10 grid, all same temperature and pressure
      temp = Nx.broadcast(295.0, {10, 10})
      pres = Nx.broadcast(101_325.0, {10, 10})

      result = FrontalAnalysis.detect_fronts(temp, pres, @grid_spec)

      assert result.front_points == []
    end

    test "detects a front at a sharp east-west temperature boundary" do
      # North half cold (280K), south half warm (300K) → sharp gradient mid-grid
      cold = Nx.broadcast(280.0, {5, 10})
      warm = Nx.broadcast(300.0, {5, 10})
      temp = Nx.concatenate([cold, warm], axis: 0)
      pres = Nx.broadcast(101_325.0, {10, 10})

      result = FrontalAnalysis.detect_fronts(temp, pres, @grid_spec)

      # Should find front points near the boundary (rows 4-5)
      assert result.front_points != []

      # All front points should be near the middle rows
      Enum.each(result.front_points, fn {lat, _lon, _bearing} ->
        assert lat >= 31.5 and lat <= 34.0
      end)
    end
  end

  describe "nearest_front/3" do
    test "returns the closest front point with distance and bearing" do
      front_points = [
        {33.0, -97.0, 90.0},
        {35.0, -97.0, 45.0}
      ]

      result = FrontalAnalysis.nearest_front(front_points, 33.1, -97.1)
      assert result.distance_km < 20.0
      assert result.front_bearing_deg == 90.0
    end

    test "returns nil for empty front_points" do
      assert FrontalAnalysis.nearest_front([], 33.0, -97.0) == nil
    end
  end

  describe "path_front_angle/2" do
    test "parallel paths return 0" do
      assert FrontalAnalysis.path_front_angle(90.0, 90.0) == 0.0
    end

    test "perpendicular paths return 90" do
      assert FrontalAnalysis.path_front_angle(0.0, 90.0) == 90.0
    end

    test "anti-parallel paths return 0" do
      assert FrontalAnalysis.path_front_angle(180.0, 0.0) == 0.0
    end

    test "45-degree offset returns 45" do
      assert_in_delta FrontalAnalysis.path_front_angle(45.0, 90.0), 45.0, 0.01
    end
  end
end
