defmodule Towerops.Preseem.FleetProfileTest do
  use Towerops.DataCase, async: true

  import Towerops.AccountsFixtures
  import Towerops.OrganizationsFixtures

  alias Towerops.Preseem.FleetProfile

  setup do
    user = user_fixture()
    org = organization_fixture(user.id)
    %{organization: org}
  end

  describe "changeset/2" do
    test "valid changeset with all fields", %{organization: org} do
      attrs = %{
        organization_id: org.id,
        manufacturer: "Cambium",
        model: "ePMP 3000",
        firmware_version: "4.7.1",
        device_count: 25,
        avg_subscribers: 18.5,
        avg_qoe_score: 82.3,
        avg_capacity_score: 71.0,
        capacity_ceiling: 35,
        avg_busy_hours: 6.2,
        performance_data: %{"p50_qoe" => 84.0, "p10_qoe" => 65.2},
        computed_at: DateTime.truncate(DateTime.utc_now(), :second)
      }

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

    test "requires organization_id" do
      attrs = %{
        manufacturer: "Cambium",
        model: "ePMP 3000",
        device_count: 25,
        computed_at: DateTime.truncate(DateTime.utc_now(), :second)
      }

      changeset = FleetProfile.changeset(%FleetProfile{}, attrs)
      refute changeset.valid?
      assert "can't be blank" in errors_on(changeset).organization_id
    end

    test "requires manufacturer" do
      attrs = %{
        organization_id: Ecto.UUID.generate(),
        model: "ePMP 3000",
        device_count: 25,
        computed_at: DateTime.truncate(DateTime.utc_now(), :second)
      }

      changeset = FleetProfile.changeset(%FleetProfile{}, attrs)
      refute changeset.valid?
      assert "can't be blank" in errors_on(changeset).manufacturer
    end

    test "requires model" do
      attrs = %{
        organization_id: Ecto.UUID.generate(),
        manufacturer: "Cambium",
        device_count: 25,
        computed_at: DateTime.truncate(DateTime.utc_now(), :second)
      }

      changeset = FleetProfile.changeset(%FleetProfile{}, attrs)
      refute changeset.valid?
      assert "can't be blank" in errors_on(changeset).model
    end

    test "requires device_count" do
      attrs = %{
        organization_id: Ecto.UUID.generate(),
        manufacturer: "Cambium",
        model: "ePMP 3000",
        computed_at: DateTime.truncate(DateTime.utc_now(), :second)
      }

      changeset = FleetProfile.changeset(%FleetProfile{}, attrs)
      refute changeset.valid?
      assert "can't be blank" in errors_on(changeset).device_count
    end

    test "requires computed_at" do
      attrs = %{
        organization_id: Ecto.UUID.generate(),
        manufacturer: "Cambium",
        model: "ePMP 3000",
        device_count: 25
      }

      changeset = FleetProfile.changeset(%FleetProfile{}, attrs)
      refute changeset.valid?
      assert "can't be blank" in errors_on(changeset).computed_at
    end

    test "persists and reloads from database", %{organization: org} do
      now = DateTime.truncate(DateTime.utc_now(), :second)

      attrs = %{
        organization_id: org.id,
        manufacturer: "Ubiquiti",
        model: "LiteAP AC",
        firmware_version: "8.7.11",
        device_count: 12,
        avg_subscribers: 22.7,
        avg_qoe_score: 88.1,
        avg_capacity_score: 76.5,
        capacity_ceiling: 40,
        avg_busy_hours: 5.0,
        performance_data: %{"percentiles" => %{"p50" => 85, "p90" => 92}},
        computed_at: now
      }

      {:ok, profile} = %FleetProfile{} |> FleetProfile.changeset(attrs) |> Repo.insert()
      reloaded = Repo.get!(FleetProfile, profile.id)

      assert reloaded.organization_id == org.id
      assert reloaded.manufacturer == "Ubiquiti"
      assert reloaded.model == "LiteAP AC"
      assert reloaded.firmware_version == "8.7.11"
      assert reloaded.device_count == 12
      assert reloaded.avg_subscribers == 22.7
      assert reloaded.avg_qoe_score == 88.1
      assert reloaded.avg_capacity_score == 76.5
      assert reloaded.capacity_ceiling == 40
      assert reloaded.avg_busy_hours == 5.0
      assert reloaded.computed_at == now
    end

    test "stores and retrieves performance_data map", %{organization: org} do
      performance_data = %{
        "by_firmware" => %{
          "4.7.1" => %{"count" => 10, "avg_qoe" => 85.0},
          "4.6.0" => %{"count" => 5, "avg_qoe" => 78.2}
        },
        "capacity_curve" => [
          %{"subscribers" => 10, "avg_qoe" => 92.0},
          %{"subscribers" => 20, "avg_qoe" => 85.0},
          %{"subscribers" => 30, "avg_qoe" => 72.0}
        ]
      }

      attrs = %{
        organization_id: org.id,
        manufacturer: "Cambium",
        model: "ePMP 3000",
        device_count: 15,
        performance_data: performance_data,
        computed_at: DateTime.truncate(DateTime.utc_now(), :second)
      }

      {:ok, profile} = %FleetProfile{} |> FleetProfile.changeset(attrs) |> Repo.insert()
      reloaded = Repo.get!(FleetProfile, profile.id)

      assert reloaded.performance_data == performance_data
    end

    test "firmware_version is optional", %{organization: org} do
      attrs = %{
        organization_id: org.id,
        manufacturer: "Cambium",
        model: "ePMP 3000",
        device_count: 25,
        computed_at: DateTime.truncate(DateTime.utc_now(), :second)
      }

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

      {:ok, profile} = Repo.insert(changeset)
      assert is_nil(profile.firmware_version)
    end
  end
end
