defmodule Growth.Indicators.DownloadTest do
  @moduledoc false

  use ExUnit.Case, async: true

  alias Elixlsx.Sheet
  alias Elixlsx.Workbook

  alias Growth.Indicators.Download

  setup do
    mock_who_request()
  end

  describe "process/3" do
    test "fetch excel from url and convert it to a list of lists" do
      gender = :female
      category = :age_tables

      url =
        "https://cdn.who.int/media/docs/default-source/child-growth/child-growth-standards/indicators/length-height-for-age/lhfa_girls_0-to-13-weeks_zscores.xlsx"

      content = Download.process(gender, category, url)

      expected_content =
        [
          ~w(source category gender age_unit age l m s sd3neg sd2neg sd1neg sd0 sd1 sd2 sd3),
          [
            url,
            category,
            gender,
            "week",
            Decimal.new("0"),
            Decimal.new("1"),
            Decimal.new("49.1477"),
            Decimal.new("0.0379"),
            Decimal.new("43.6"),
            Decimal.new("45.4"),
            Decimal.new("47.3"),
            Decimal.new("49.1"),
            Decimal.new("51"),
            Decimal.new("52.9"),
            Decimal.new("54.7")
          ]
        ]

      assert expected_content == content
    end
  end

  describe "process_gender/1" do
    test "merge multiple contents into a single one" do
      category = :age_tables
      gender = :female

      urls =
        [
          "https://cdn.who.int/media/docs/default-source/child-growth/child-growth-standards/indicators/length-height-for-age/lhfa_girls_0-to-13-weeks_zscores.xlsx",
          "https://cdn.who.int/media/docs/default-source/child-growth/child-growth-standards/indicators/length-height-for-age/lhfa_girls_0-to-2-years_zscores.xlsx"
        ]

      content = Download.process_gender({gender, category, urls})

      expected_content =
        [
          ~w(source category gender age_unit age l m s sd3neg sd2neg sd1neg sd0 sd1 sd2 sd3),
          [
            List.first(urls),
            category,
            gender,
            "week",
            Decimal.new("0"),
            Decimal.new("1"),
            Decimal.new("49.1477"),
            Decimal.new("0.0379"),
            Decimal.new("43.6"),
            Decimal.new("45.4"),
            Decimal.new("47.3"),
            Decimal.new("49.1"),
            Decimal.new("51"),
            Decimal.new("52.9"),
            Decimal.new("54.7")
          ],
          [
            List.last(urls),
            category,
            gender,
            "month",
            Decimal.new("0"),
            Decimal.new("1"),
            Decimal.new("49.1477"),
            Decimal.new("0.0379"),
            Decimal.new("43.6"),
            Decimal.new("45.4"),
            Decimal.new("47.3"),
            Decimal.new("49.1"),
            Decimal.new("51"),
            Decimal.new("52.9"),
            Decimal.new("54.7")
          ]
        ]

      assert expected_content == content
    end
  end

  describe "process_genders/1" do
    test "merge multiple genders and contents into a single one" do
      female_urls = %{
        age_tables: ~w(
          https://cdn.who.int/media/docs/default-source/child-growth/child-growth-standards/indicators/length-height-for-age/lhfa_girls_0-to-13-weeks_zscores.xlsx
          https://cdn.who.int/media/docs/default-source/child-growth/child-growth-standards/indicators/length-height-for-age/lhfa_girls_0-to-2-years_zscores.xlsx
        ),
        expanded_tables: ~w(
          https://cdn.who.int/media/docs/default-source/child-growth/child-growth-standards/indicators/length-height-for-age/expandable-tables/lhfa-girls-zscore-expanded-tables.xlsx
        )
      }

      male_urls = %{
        age_tables: ~w(
          https://cdn.who.int/media/docs/default-source/child-growth/child-growth-standards/indicators/length-height-for-age/lhfa_boys_0-to-13-weeks_zscores.xlsx
          https://cdn.who.int/media/docs/default-source/child-growth/child-growth-standards/indicators/length-height-for-age/lhfa_boys_0-to-2-years_zscores.xlsx
        ),
        expanded_tables: ~w(
          https://cdn.who.int/media/docs/default-source/child-growth/child-growth-standards/indicators/length-height-for-age/expandable-tables/lhfa-boys-zscore-expanded-tables.xlsx
        )
      }

      content = Download.process_genders(%{female: female_urls, male: male_urls})

      expected_content =
        [
          ~w(source category gender age_unit age l m s sd3neg sd2neg sd1neg sd0 sd1 sd2 sd3),
          [
            female_urls |> Map.get(:age_tables) |> List.first(),
            :age,
            :female,
            "week",
            Decimal.new("0"),
            Decimal.new("1"),
            Decimal.new("49.1477"),
            Decimal.new("0.0379"),
            Decimal.new("43.6"),
            Decimal.new("45.4"),
            Decimal.new("47.3"),
            Decimal.new("49.1"),
            Decimal.new("51"),
            Decimal.new("52.9"),
            Decimal.new("54.7")
          ],
          [
            female_urls |> Map.get(:age_tables) |> List.last(),
            :age,
            :female,
            "month",
            Decimal.new("0"),
            Decimal.new("1"),
            Decimal.new("49.1477"),
            Decimal.new("0.0379"),
            Decimal.new("43.6"),
            Decimal.new("45.4"),
            Decimal.new("47.3"),
            Decimal.new("49.1"),
            Decimal.new("51"),
            Decimal.new("52.9"),
            Decimal.new("54.7")
          ],
          [
            male_urls |> Map.get(:age_tables) |> List.first(),
            :age,
            :male,
            "week",
            Decimal.new("0"),
            Decimal.new("1"),
            Decimal.new("49.8842"),
            Decimal.new("0.03795"),
            Decimal.new("44.2"),
            Decimal.new("46.1"),
            Decimal.new("48"),
            Decimal.new("49.9"),
            Decimal.new("51.8"),
            Decimal.new("53.7"),
            Decimal.new("55.6")
          ],
          [
            male_urls |> Map.get(:age_tables) |> List.last(),
            :age,
            :male,
            "month",
            Decimal.new("0"),
            Decimal.new("1"),
            Decimal.new("49.8842"),
            Decimal.new("0.03795"),
            Decimal.new("44.2"),
            Decimal.new("46.1"),
            Decimal.new("48"),
            Decimal.new("49.9"),
            Decimal.new("51.8"),
            Decimal.new("53.7"),
            Decimal.new("55.6")
          ],
          [
            female_urls |> Map.get(:expanded_tables) |> List.first(),
            :expanded,
            :female,
            "day",
            Decimal.new("0"),
            Decimal.new("1"),
            Decimal.new("49.1477"),
            Decimal.new("0.0379"),
            Decimal.new("43.56"),
            Decimal.new("45.422"),
            Decimal.new("47.285"),
            Decimal.new("49.148"),
            Decimal.new("51.01"),
            Decimal.new("52.873"),
            Decimal.new("54.736")
          ],
          [
            male_urls |> Map.get(:expanded_tables) |> List.first(),
            :expanded,
            :male,
            "day",
            Decimal.new("0"),
            Decimal.new("1"),
            Decimal.new("49.8842"),
            Decimal.new("0.03795"),
            Decimal.new("44.205"),
            Decimal.new("46.098"),
            Decimal.new("47.991"),
            Decimal.new("49.884"),
            Decimal.new("51.777"),
            Decimal.new("53.67"),
            Decimal.new("55.564")
          ]
        ]

      assert expected_content == content
    end
  end

  defp mock_who_request do
    Req.Test.stub(Growth.Indicators.Download.WHO, fn %Plug.Conn{path_info: path_info} = conn ->
      filename = List.last(path_info)

      rows =
        case filename do
          "lhfa_girls_0-to-13-weeks_zscores.xlsx" ->
            [
              ~w(Week L M S SD SD3neg SD2neg SD1neg SD0 SD1 SD2 SD3),
              ~w(0 1 49.1477 0.0379 1.8627 43.6 45.4 47.3 49.1 51 52.9 54.7)
            ]

          "lhfa_girls_0-to-2-years_zscores.xlsx" ->
            [
              ~w(Month L M S SD SD3neg SD2neg SD1neg SD0 SD1 SD2 SD3),
              ~w(0 1 49.1477 0.0379 1.8627 43.6 45.4 47.3 49.1 51 52.9 54.7)
            ]

          "lhfa-girls-zscore-expanded-tables.xlsx" ->
            [
              ~w(Day L M S SD4neg SD3neg SD2neg SD1neg SD0 SD1 SD2 SD3 SD4),
              ~w(0 1 49.1477 0.0379 41.697 43.56 45.422 47.285 49.148 51.01 52.873 54.736 56.598)
            ]

          "lhfa_boys_0-to-13-weeks_zscores.xlsx" ->
            [
              ~w(Week L M S SD SD3neg SD2neg SD1neg SD0 SD1 SD2 SD3),
              ~w(0 1 49.8842 0.03795 1.8931 44.2 46.1 48 49.9 51.8 53.7 55.6)
            ]

          "lhfa_boys_0-to-2-years_zscores.xlsx" ->
            [
              ~w(Month L M S SD SD3neg SD2neg SD1neg SD0 SD1 SD2 SD3),
              ~w(0 1 49.8842 0.03795 1.8931 44.2 46.1 48 49.9 51.8 53.7 55.6)
            ]

          "lhfa-boys-zscore-expanded-tables.xlsx" ->
            [
              ~w(Day L M S SD4neg SD3neg SD2neg SD1neg SD0 SD1 SD2 SD3 SD4),
              ~w(0 1 49.8842 0.03795 42.312 44.205 46.098 47.991 49.884 51.777 53.67 55.564 57.457)
            ]
        end

      {:ok, {_charlist_content, content}} =
        %Sheet{name: "zscore", rows: rows}
        |> then(&%Workbook{sheets: [&1]})
        |> Elixlsx.write_to_memory(filename)

      conn
      |> Plug.Conn.put_resp_content_type(
        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
      )
      |> Plug.Conn.send_resp(200, content)
    end)
  end
end
