defmodule GrowthTest do
  @moduledoc false

  use ExUnit.Case, async: true

  doctest Growth

  @child %{
    name: "Jane Doe",
    gender: :female,
    date_of_measurement: Date.utc_today(),
    age_in_days: 91,
    weight: 5.84,
    height: 59.78,
    head_circumference: 39.51,
    arm_circumference: 13.02,
    subscapular_skinfold: 7.79,
    triceps_skinfold: 9.75
  }
  @child_date_of_birth Date.shift(@child.date_of_measurement, day: @child.age_in_days * -1)

  describe "new/4" do
    test "create a new growth measurement" do
      growth =
        Growth.new(@child.name, @child.gender, @child_date_of_birth,
          date_of_measurement: @child.date_of_measurement,
          weight: @child.weight,
          height: @child.height,
          head_circumference: @child.head_circumference,
          arm_circumference: @child.arm_circumference,
          subscapular_skinfold: @child.subscapular_skinfold,
          triceps_skinfold: @child.triceps_skinfold
        )

      assert @child.name == growth.name
      assert @child.gender == growth.gender
      assert @child_date_of_birth == growth.date_of_birth
      assert @child.date_of_measurement == growth.date_of_measurement
      assert @child.age_in_days == growth.age_in_days
      assert 13 == growth.age_in_weeks
      assert 2 == growth.age_in_months
      assert @child.weight == growth.weight
      assert @child.height == growth.height
      assert @child.head_circumference == growth.head_circumference
      assert @child.arm_circumference == growth.arm_circumference
      assert @child.subscapular_skinfold == growth.subscapular_skinfold
      assert @child.triceps_skinfold == growth.triceps_skinfold
    end
  end

  describe "with_bmi/1" do
    test "calculate bmi from measurement" do
      growth =
        %Growth{
          name: @child.name,
          gender: @child.gender,
          date_of_birth: @child_date_of_birth,
          date_of_measurement: @child.date_of_measurement,
          weight: @child.weight,
          height: @child.height,
          head_circumference: @child.head_circumference,
          arm_circumference: @child.arm_circumference,
          subscapular_skinfold: @child.subscapular_skinfold,
          triceps_skinfold: @child.triceps_skinfold
        }
        |> Growth.with_age_in_days()
        |> Growth.with_age_in_weeks()
        |> Growth.with_age_in_months()
        |> Growth.with_bmi()

      assert 16.341842694989243 == growth.bmi
    end
  end

  describe "with_results/1" do
    test "calculate z-score and percentiles from measurement" do
      growth =
        %Growth{
          name: @child.name,
          gender: @child.gender,
          date_of_birth: @child_date_of_birth,
          date_of_measurement: @child.date_of_measurement,
          weight: @child.weight,
          height: @child.height,
          head_circumference: @child.head_circumference,
          arm_circumference: @child.arm_circumference,
          subscapular_skinfold: @child.subscapular_skinfold,
          triceps_skinfold: @child.triceps_skinfold,
          results: []
        }
        |> Growth.with_age_in_days()
        |> Growth.with_age_in_weeks()
        |> Growth.with_age_in_months()
        |> Growth.with_bmi()
        |> Growth.with_results()

      assert [
               day: {9.496948997971584e-4, 0.5003788733920584},
               week: {9.496948997971584e-4, 0.5003788733920584},
               month: {1.0060928051683196, 0.8428145353253619}
             ] == Keyword.get(growth.results, :weight)

      assert [
               day: {0.0012831717968983271, 0.5005119113423219},
               week: {0.0012831717968983271, 0.5005119113423219},
               month: {1.3322618635180914, 0.9086129228760054}
             ] == Keyword.get(growth.results, :height)

      assert [
               day: {-0.007440424136462911, 0.4970317276150869},
               week: {-0.007440424136462911, 0.4970317276150869},
               month: {0.3827194919327071, 0.6490361198066796}
             ] == Keyword.get(growth.results, :bmi)

      assert [
               day: {-0.008864109494641385, 0.4964637782528006},
               week: {-0.008864109494641385, 0.4964637782528006},
               month: {1.0380198575748647, 0.8503695948597997}
             ] == Keyword.get(growth.results, :head_circumference)

      assert [day: {-0.004182676756535293, 0.49833135826198854}] ==
               Keyword.get(growth.results, :arm_circumference)

      assert [day: {0.001811404894950268, 0.5007226456043324}] ==
               Keyword.get(growth.results, :subscapular_skinfold)

      assert [day: {-0.0019309186728254878, 0.49922967538007906}] ==
               Keyword.get(growth.results, :triceps_skinfold)
    end
  end
end
