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

  alias Microwaveprop.Weather.Grib2.LambertConformal

  # HRRR grid parameters (from GRIB2 Section 3, Template 3.30)
  @hrrr_params %{
    nx: 1799,
    ny: 1059,
    la1: 21.138123,
    lo1: 237.280472,
    lad: 38.5,
    lov: 262.5,
    dx: 3000.0,
    dy: 3000.0,
    latin1: 38.5,
    latin2: 38.5,
    scan_mode: 64
  }

  describe "to_grid_index/3" do
    test "first grid point maps to (0, 0)" do
      assert {:ok, {0, 0}} = LambertConformal.to_grid_index(@hrrr_params, 21.138123, 237.280472)
    end

    test "first grid point with negative longitude" do
      # 237.280472 in 0-360 == -122.719528 in -180..180
      assert {:ok, {0, 0}} =
               LambertConformal.to_grid_index(@hrrr_params, 21.138123, -122.719528)
    end

    test "Dallas area returns reasonable indices" do
      # Dallas TX: ~32.78, -96.8 (263.2 in 0-360)
      # HRRR 3km grid covers CONUS; Dallas should be roughly in the middle
      assert {:ok, {i, j}} = LambertConformal.to_grid_index(@hrrr_params, 32.78, -96.8)

      # Indices should be well within grid bounds
      assert i > 100 and i < 1700
      assert j > 100 and j < 900
    end

    test "handles negative longitudes correctly" do
      {:ok, {i1, j1}} = LambertConformal.to_grid_index(@hrrr_params, 40.0, -105.0)
      {:ok, {i2, j2}} = LambertConformal.to_grid_index(@hrrr_params, 40.0, 255.0)

      assert i1 == i2
      assert j1 == j2
    end

    test "returns error for point outside grid" do
      # London, UK — well outside CONUS HRRR domain
      assert {:error, :outside_grid} =
               LambertConformal.to_grid_index(@hrrr_params, 51.5, -0.12)
    end

    test "returns error for point south of grid" do
      # South America
      assert {:error, :outside_grid} =
               LambertConformal.to_grid_index(@hrrr_params, -10.0, -80.0)
    end

    test "edge of grid returns valid indices" do
      # Somewhere near the grid edge — northeast CONUS
      result = LambertConformal.to_grid_index(@hrrr_params, 45.0, -70.0)
      assert {:ok, {i, j}} = result
      assert i >= 0 and i < 1799
      assert j >= 0 and j < 1059
    end
  end
end
