defmodule Microwaveprop.Weather.HrrrProfileTest do
  use Microwaveprop.DataCase, async: true

  alias Microwaveprop.Weather.HrrrProfile

  @sample_profile [
    %{"pres" => 1000.0, "hght" => 110, "tmpc" => 25.0, "dwpc" => 18.0},
    %{"pres" => 975.0, "hght" => 350, "tmpc" => 23.0, "dwpc" => 16.0},
    %{"pres" => 950.0, "hght" => 590, "tmpc" => 21.0, "dwpc" => 14.0}
  ]

  @valid_attrs %{
    valid_time: ~U[2026-03-28 18:00:00Z],
    lat: 32.90,
    lon: -97.04,
    run_time: ~U[2026-03-28 18:00:00Z],
    profile: @sample_profile,
    hpbl_m: 1500.0,
    pwat_mm: 25.0,
    surface_temp_c: 25.0,
    surface_dewpoint_c: 18.0,
    surface_pressure_mb: 1013.0,
    surface_refractivity: 320.5,
    min_refractivity_gradient: -45.0,
    ducting_detected: false,
    duct_characteristics: nil
  }

  describe "changeset/2" do
    test "valid attributes" do
      changeset = HrrrProfile.changeset(%HrrrProfile{}, @valid_attrs)
      assert changeset.valid?
    end

    test "requires valid_time, lat, lon" do
      changeset = HrrrProfile.changeset(%HrrrProfile{}, %{})

      assert %{
               valid_time: ["can't be blank"],
               lat: ["can't be blank"],
               lon: ["can't be blank"]
             } = errors_on(changeset)
    end

    test "derived params are optional" do
      attrs = %{valid_time: ~U[2026-03-28 18:00:00Z], lat: 32.90, lon: -97.04}
      changeset = HrrrProfile.changeset(%HrrrProfile{}, attrs)
      assert changeset.valid?
    end

    test "persists to the database with JSONB profile" do
      changeset = HrrrProfile.changeset(%HrrrProfile{}, @valid_attrs)
      assert {:ok, profile} = Repo.insert(changeset)
      assert length(profile.profile) == 3
      assert hd(profile.profile)["pres"] == 1000.0
      assert profile.ducting_detected == false
      assert profile.hpbl_m == 1500.0
    end

    test "persists duct_characteristics as JSONB" do
      duct_chars = [%{"base" => 200, "top" => 500, "strength" => 5.2}]

      attrs =
        @valid_attrs
        |> Map.put(:ducting_detected, true)
        |> Map.put(:duct_characteristics, duct_chars)

      changeset = HrrrProfile.changeset(%HrrrProfile{}, attrs)
      assert {:ok, profile} = Repo.insert(changeset)
      assert profile.ducting_detected == true
      assert [%{"base" => 200, "top" => 500}] = profile.duct_characteristics
    end

    test "enforces unique lat + lon + valid_time" do
      assert {:ok, _} =
               %HrrrProfile{} |> HrrrProfile.changeset(@valid_attrs) |> Repo.insert()

      # Partitioned tables raise ConstraintError directly
      assert_raise Ecto.ConstraintError, fn ->
        %HrrrProfile{} |> HrrrProfile.changeset(@valid_attrs) |> Repo.insert!()
      end
    end
  end
end
