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

  alias Microwaveprop.Weather.Station
  alias Microwaveprop.Weather.SurfaceObservation

  defp create_station do
    %Station{}
    |> Station.changeset(%{
      station_code: "KDFW",
      station_type: "asos",
      name: "Dallas/Fort Worth International",
      lat: 32.8998,
      lon: -97.0403
    })
    |> Repo.insert!()
  end

  @valid_obs_attrs %{
    observed_at: ~U[2026-03-28 18:00:00Z],
    temp_f: 75.0,
    dewpoint_f: 55.0,
    relative_humidity: 49.0,
    wind_speed_kts: 12.0,
    wind_direction_deg: 180,
    sea_level_pressure_mb: 1013.25,
    altimeter_setting: 29.92,
    sky_condition: "SCT",
    precip_1h_in: 0.03,
    wx_codes: "RA"
  }

  describe "changeset/2" do
    test "valid attributes with station_id" do
      station = create_station()
      attrs = Map.put(@valid_obs_attrs, :station_id, station.id)
      changeset = SurfaceObservation.changeset(%SurfaceObservation{}, attrs)
      assert changeset.valid?
    end

    test "requires station_id and observed_at" do
      changeset = SurfaceObservation.changeset(%SurfaceObservation{}, %{})

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

    test "all weather fields are optional" do
      station = create_station()

      attrs = %{
        station_id: station.id,
        observed_at: ~U[2026-03-28 18:00:00Z]
      }

      changeset = SurfaceObservation.changeset(%SurfaceObservation{}, attrs)
      assert changeset.valid?
    end

    test "persists to the database" do
      station = create_station()
      attrs = Map.put(@valid_obs_attrs, :station_id, station.id)
      changeset = SurfaceObservation.changeset(%SurfaceObservation{}, attrs)
      assert {:ok, obs} = Repo.insert(changeset)
      assert obs.temp_f == 75.0
      assert obs.sky_condition == "SCT"
      assert obs.precip_1h_in == 0.03
      assert obs.wx_codes == "RA"
      assert obs.station_id == station.id
    end

    test "enforces unique station_id + observed_at" do
      station = create_station()
      attrs = Map.put(@valid_obs_attrs, :station_id, station.id)

      assert {:ok, _} = %SurfaceObservation{} |> SurfaceObservation.changeset(attrs) |> Repo.insert()
      assert {:error, changeset} = %SurfaceObservation{} |> SurfaceObservation.changeset(attrs) |> Repo.insert()
      assert %{station_id: ["has already been taken"]} = errors_on(changeset)
    end
  end
end
