defmodule Oli.Analytics.Summary.MetricsV2Test do
  use Oli.DataCase

  import Oli.Factory

  alias Oli.Delivery.Sections.ContainedPage
  alias Oli.Delivery.Sections.SectionResourceDepot
  alias Oli.Delivery.Metrics
  alias Lti_1p3.Roles.ContextRoles

  describe "v2 metrics calculations" do
    setup do
      map =
        Seeder.base_project_with_resource2()
        |> Seeder.create_section()
        |> Seeder.add_objective("objective one", :o1)
        |> Seeder.add_objective("objective two", :o2)
        |> Seeder.add_objective("objective three", :o3)
        |> Seeder.add_activity(%{title: "one", content: %{}}, :a1)
        |> Seeder.add_activity(%{title: "two", content: %{}}, :a2)
        |> Seeder.add_user(%{}, :user1)
        |> Seeder.add_user(%{}, :user2)

      Seeder.ensure_published(map.publication.id)

      Seeder.create_section_resources(map)
    end

    test "proficiency for objectives", %{
      user1: user1,
      user2: user2,
      section: section,
      o1: o1,
      o2: o2,
      page1: page1,
      project: project
    } do
      objective_type_id = Oli.Resources.ResourceType.id_for_objective()
      page_type_id = Oli.Resources.ResourceType.id_for_page()
      {:ok, section} = Oli.Delivery.Sections.update_section(section, %{analytics_version: :v2})

      id = o1.resource.id
      id2 = o2.resource.id

      [
        # page record
        [-1, -1, section.id, -1, page1.id, nil, page_type_id, 4, 10, 1, 5, 1],
        [-1, -1, section.id, -1, id, nil, objective_type_id, 4, 10, 1, 5, 1],
        [-1, -1, section.id, user1.id, id, nil, objective_type_id, 2, 6, 1, 1, 0],
        [-1, -1, section.id, user2.id, id, nil, objective_type_id, 2, 4, 0, 1, 1],
        [project.id, -1, -1, -1, id, nil, objective_type_id, 4, 10, 1, 5, 1],
        [-1, -1, section.id, -1, id2, nil, objective_type_id, 40, 100, 55, 50, 10],
        [-1, -1, section.id, user1.id, id2, nil, objective_type_id, 2, 6, 1, 3, 1],
        [-1, -1, section.id, user2.id, id2, nil, objective_type_id, 2, 4, 0, 4, 2],
        [project.id, -1, -1, -1, id2, nil, objective_type_id, 4, 10, 1, 5, 1]
      ]
      |> Enum.each(fn v -> add_resource_summary(v) end)

      results = Metrics.raw_proficiency_per_learning_objective(section.id)
      assert Map.keys(results) |> Enum.count() == 2
      assert assert %{^id => {1, 5, 4, 10}, ^id2 => {10, 50, 40, 100}} = results

      assert %{^id => {0, 1, 2, 6}, ^id2 => {1, 3, 2, 6}} =
               Metrics.raw_proficiency_per_learning_objective(section.id, student_id: user1.id)

      assert %{^id => {1, 1, 2, 4}, ^id2 => {2, 4, 2, 4}} =
               Metrics.raw_proficiency_per_learning_objective(section.id, student_id: user2.id)
    end

    test "proficiency for page", %{
      user1: user1,
      user2: user2,
      section: section,
      o1: o1,
      page1: page1,
      page2: page2,
      project: project
    } do
      objective_type_id = Oli.Resources.ResourceType.id_for_objective()
      page_type_id = Oli.Resources.ResourceType.id_for_page()
      {:ok, section} = Oli.Delivery.Sections.update_section(section, %{analytics_version: :v2})

      id = o1.resource.id

      page1_id = page1.id
      page2_id = page2.id

      user1_id = user1.id
      user2_id = user2.id

      [
        # page records
        [-1, -1, section.id, -1, page1.id, nil, page_type_id, 4, 10, 1, 5, 1],
        [-1, -1, section.id, -1, page2.id, nil, page_type_id, 3, 11, 2, 3, 2],
        [-1, -1, section.id, user1.id, page1.id, nil, page_type_id, 2, 10, 1, 5, 1],
        [-1, -1, section.id, user1.id, page2.id, nil, page_type_id, 4, 11, 2, 30, 30],
        [-1, -1, section.id, user2.id, page1.id, nil, page_type_id, 1, 12, 3, 5, 1],
        [-1, -1, section.id, user2.id, page2.id, nil, page_type_id, 2, 14, 4, 3, 2],
        # objective records
        [-1, -1, section.id, -1, id, nil, objective_type_id, 4, 10, 1, 5, 1],
        [-1, -1, section.id, user1.id, id, nil, objective_type_id, 2, 6, 1, 1, 0],
        [-1, -1, section.id, user2.id, id, nil, objective_type_id, 2, 4, 0, 1, 1],
        [project.id, -1, -1, -1, id, nil, objective_type_id, 4, 10, 1, 5, 1]
      ]
      |> Enum.each(fn v -> add_resource_summary(v) end)

      results = Metrics.proficiency_for_student_per_page(section, user1.id)

      assert Map.keys(results) |> Enum.count() == 2
      assert %{^page1_id => "Low", ^page2_id => "High"} = results

      results = Metrics.proficiency_per_student_for_page(section, page1_id)
      assert Map.keys(results) |> Enum.count() == 2
      assert %{^user1_id => "Low", ^user2_id => "Low"} = results

      results = Metrics.proficiency_per_page(section, [page1_id, page2_id])
      assert Map.keys(results) |> Enum.count() == 2
      assert %{^page1_id => "Low", ^page2_id => "Medium"} = results

      contained_pages = [
        %ContainedPage{container_id: 3, page_id: page1_id},
        %ContainedPage{container_id: 3, page_id: page2_id},
        %ContainedPage{container_id: 2, page_id: page1_id}
      ]

      results = Metrics.proficiency_for_student_per_container(section, user1_id, contained_pages)
      assert Map.keys(results) |> Enum.count() == 2
      assert %{2 => "Low", 3 => "High"} = results

      results = Metrics.proficiency_per_container(section, contained_pages)
      assert Map.keys(results) |> Enum.count() == 2
      assert %{2 => "Low", 3 => "Medium"} = results

      results = Metrics.proficiency_per_student_across(section)
      assert Map.keys(results) |> Enum.count() == 2
      assert %{^user1_id => "High", ^user2_id => "Medium"} = results
    end

    test "proficiency_for_student_per_learning_objective/3 shows Not enough data when num first attempts is < 3",
         %{
           user1: user1,
           user2: user2,
           section: section,
           o1: o1,
           o2: o2,
           o3: o3
         } do
      objective_type_id = Oli.Resources.ResourceType.id_for_objective()
      {:ok, section} = Oli.Delivery.Sections.update_section(section, %{analytics_version: :v2})

      id = o1.resource.id
      id2 = o2.resource.id
      id3 = o3.resource.id

      [
        [-1, -1, section.id, user1.id, id, nil, objective_type_id, 2, 6, 1, 1, 0],
        [-1, -1, section.id, user1.id, id2, nil, objective_type_id, 2, 6, 1, 3, 2],
        [-1, -1, section.id, user1.id, id3, nil, objective_type_id, 2, 6, 1, 3, 3],
        [-1, -1, section.id, user2.id, id, nil, objective_type_id, 2, 4, 0, 1, 1],
        [-1, -1, section.id, user2.id, id2, nil, objective_type_id, 2, 4, 0, 4, 2]
      ]
      |> Enum.each(fn v -> add_resource_summary(v) end)

      results =
        Metrics.proficiency_for_student_per_learning_objective(
          [o1.revision, o2.revision, o3.revision],
          user1.id,
          section
        )

      assert Map.keys(results) |> Enum.count() == 3
      assert Map.get(results, id) == "Not enough data"
      assert Map.get(results, id2) == "Medium"
      assert Map.get(results, id3) == "High"
    end

    test "proficiency_for_student_per_learning_objective/3", %{
      user1: user1,
      user2: user2,
      section: section,
      o1: o1,
      o2: o2,
      o3: o3
    } do
      objective_type_id = Oli.Resources.ResourceType.id_for_objective()
      {:ok, section} = Oli.Delivery.Sections.update_section(section, %{analytics_version: :v2})

      id = o1.resource.id
      id2 = o2.resource.id
      id3 = o3.resource.id

      [
        [-1, -1, section.id, user1.id, id, nil, objective_type_id, 1, 6, 1, 3, 0],
        [-1, -1, section.id, user1.id, id2, nil, objective_type_id, 3, 6, 1, 3, 2],
        [-1, -1, section.id, user1.id, id3, nil, objective_type_id, 6, 6, 1, 3, 3],
        [-1, -1, section.id, user2.id, id, nil, objective_type_id, 1, 4, 0, 1, 0],
        [-1, -1, section.id, user2.id, id2, nil, objective_type_id, 2, 4, 0, 4, 2]
      ]
      |> Enum.each(fn v -> add_resource_summary(v) end)

      results =
        Metrics.proficiency_for_student_per_learning_objective(
          [o1.revision, o2.revision, o3.revision],
          user1.id,
          section
        )

      assert Map.keys(results) |> Enum.count() == 3
      assert Map.get(results, id) == "Low"
      assert Map.get(results, id2) == "Medium"
      assert Map.get(results, id3) == "High"
    end

    test "proficiency_per_student_for_objective/2", %{
      user1: user1,
      user2: user2,
      section: section,
      o1: o1,
      o2: o2,
      o3: o3
    } do
      objective_type_id = Oli.Resources.ResourceType.id_for_objective()
      {:ok, section} = Oli.Delivery.Sections.update_section(section, %{analytics_version: :v2})

      id = o1.resource.id
      id2 = o2.resource.id
      id3 = o3.resource.id

      # project_id, publication_id, section_id, user_id, resource_id,
      # part_id, resource_type_id, num_correct, num_attempts, num_hints,
      # num_first_attempts, num_first_attempts_correct
      [
        [-1, -1, section.id, user1.id, id, nil, objective_type_id, 1, 6, 1, 3, 0],
        [-1, -1, section.id, user1.id, id2, nil, objective_type_id, 3, 6, 1, 3, 2],
        [-1, -1, section.id, user1.id, id3, nil, objective_type_id, 6, 6, 1, 3, 3],
        [-1, -1, section.id, user2.id, id, nil, objective_type_id, 1, 4, 0, 1, 0],
        [-1, -1, section.id, user2.id, id2, nil, objective_type_id, 2, 4, 0, 4, 2]
      ]
      |> Enum.each(fn v -> add_resource_summary(v) end)

      proficiencies_objective1 =
        Map.get(Metrics.proficiency_per_student_for_objective(section.id, [id]), id)

      proficiencies_objective2 =
        Map.get(Metrics.proficiency_per_student_for_objective(section.id, [id2]), id2)

      proficiencies_objective3 =
        Map.get(Metrics.proficiency_per_student_for_objective(section.id, [id3]), id3)

      assert Map.get(proficiencies_objective1, user1.id) == "Low"
      assert Map.get(proficiencies_objective1, user2.id) == "Not enough data"
      assert Map.get(proficiencies_objective2, user1.id) == "Medium"
      assert Map.get(proficiencies_objective2, user2.id) == "Medium"
      assert Map.get(proficiencies_objective3, user1.id) == "High"
      refute Map.get(proficiencies_objective3, user2.id)
    end
  end

  describe "learning objectives expanded visualization tests" do
    test "objectives_proficiency/3 returns sub-objectives with proficiency distribution" do
      objective_type_id = Oli.Resources.ResourceType.id_for_objective()

      # Create author and project
      author = insert(:author)
      project = insert(:project, authors: [author])
      section = insert(:section)
      publication = insert(:publication, project: project)

      insert(:section_project_publication,
        section: section,
        project: project,
        publication: publication
      )

      # Create users
      user1 = insert(:user)
      user2 = insert(:user)
      user3 = insert(:user)

      # Create enrollments with proper context roles
      student_role = ContextRoles.get_role(:context_learner)

      enrollment1 = insert(:enrollment, section: section, user: user1)
      enrollment2 = insert(:enrollment, section: section, user: user2)
      enrollment3 = insert(:enrollment, section: section, user: user3)

      # Manually add context_roles associations
      Oli.Repo.insert_all("enrollments_context_roles", [
        %{enrollment_id: enrollment1.id, context_role_id: student_role.id},
        %{enrollment_id: enrollment2.id, context_role_id: student_role.id},
        %{enrollment_id: enrollment3.id, context_role_id: student_role.id}
      ])

      # Create parent and sub-objectives
      parent_resource = insert(:resource)

      parent_revision =
        insert(:revision,
          resource: parent_resource,
          author: author,
          title: "Parent Objective",
          resource_type_id: objective_type_id,
          content: %{}
        )

      sub_obj1_resource = insert(:resource)

      sub_obj1_revision =
        insert(:revision,
          resource: sub_obj1_resource,
          author: author,
          title: "Sub Objective 1",
          resource_type_id: objective_type_id,
          content: %{}
        )

      sub_obj2_resource = insert(:resource)

      sub_obj2_revision =
        insert(:revision,
          resource: sub_obj2_resource,
          author: author,
          title: "Sub Objective 2",
          resource_type_id: objective_type_id,
          content: %{}
        )

      sub_obj3_resource = insert(:resource)

      sub_obj3_revision =
        insert(:revision,
          resource: sub_obj3_resource,
          author: author,
          title: "Sub Objective 3",
          resource_type_id: objective_type_id,
          content: %{}
        )

      # Publish resources
      insert(:published_resource,
        publication: publication,
        resource: parent_resource,
        revision: parent_revision
      )

      insert(:published_resource,
        publication: publication,
        resource: sub_obj1_resource,
        revision: sub_obj1_revision
      )

      insert(:published_resource,
        publication: publication,
        resource: sub_obj2_resource,
        revision: sub_obj2_revision
      )

      insert(:published_resource,
        publication: publication,
        resource: sub_obj3_resource,
        revision: sub_obj3_revision
      )

      # Update parent objective to have children
      {:ok, _} =
        Oli.Resources.Revision.changeset(parent_revision, %{
          children: [sub_obj1_resource.id, sub_obj2_resource.id, sub_obj3_resource.id]
        })
        |> Oli.Repo.update()

      # Create SectionResource records needed for the depot
      insert(:section_resource,
        section: section,
        resource_id: parent_resource.id,
        title: "Parent Objective",
        children: [sub_obj1_resource.id, sub_obj2_resource.id, sub_obj3_resource.id]
      )

      insert(:section_resource,
        section: section,
        resource_id: sub_obj1_resource.id,
        title: "Sub Objective 1"
      )

      insert(:section_resource,
        section: section,
        resource_id: sub_obj2_resource.id,
        title: "Sub Objective 2"
      )

      insert(:section_resource,
        section: section,
        resource_id: sub_obj3_resource.id,
        title: "Sub Objective 3"
      )

      # Create ResourceSummary records for different proficiency levels
      [
        # Sub objective 1 - High proficiency users
        [
          -1,
          publication.id,
          section.id,
          user1.id,
          sub_obj1_resource.id,
          nil,
          objective_type_id,
          8,
          10,
          1,
          10,
          8
        ],
        [
          -1,
          publication.id,
          section.id,
          user2.id,
          sub_obj1_resource.id,
          nil,
          objective_type_id,
          9,
          10,
          1,
          10,
          9
        ],
        # Sub objective 2 - Medium proficiency user
        [
          -1,
          publication.id,
          section.id,
          user1.id,
          sub_obj2_resource.id,
          nil,
          objective_type_id,
          6,
          10,
          1,
          10,
          6
        ],
        # Sub objective 3 - Low proficiency user
        [
          -1,
          publication.id,
          section.id,
          user1.id,
          sub_obj3_resource.id,
          nil,
          objective_type_id,
          2,
          10,
          1,
          10,
          2
        ],
        # User 3 - Not enough data (less than 3 attempts)
        [
          -1,
          publication.id,
          section.id,
          user3.id,
          sub_obj1_resource.id,
          nil,
          objective_type_id,
          1,
          2,
          1,
          2,
          1
        ]
      ]
      |> Enum.each(fn v -> add_resource_summary(v) end)

      sub_objective_section_resources = [
        SectionResourceDepot.get_section_resource(section.id, sub_obj1_resource.id),
        SectionResourceDepot.get_section_resource(section.id, sub_obj2_resource.id),
        SectionResourceDepot.get_section_resource(section.id, sub_obj3_resource.id)
      ]

      # Test the function
      result =
        Metrics.objectives_proficiency(section.id, section.slug, sub_objective_section_resources)

      assert length(result) == 3

      # Find each sub-objective result
      sub_obj1_result = Enum.find(result, &(&1.sub_objective_id == sub_obj1_resource.id))
      sub_obj2_result = Enum.find(result, &(&1.sub_objective_id == sub_obj2_resource.id))
      sub_obj3_result = Enum.find(result, &(&1.sub_objective_id == sub_obj3_resource.id))

      # Verify structure
      assert sub_obj1_result.title == "Sub Objective 1"
      assert sub_obj2_result.title == "Sub Objective 2"
      assert sub_obj3_result.title == "Sub Objective 3"

      # Verify proficiency distributions
      assert sub_obj1_result.proficiency_distribution["High"] == 2
      assert sub_obj1_result.proficiency_distribution["Not enough data"] == 1

      assert sub_obj2_result.proficiency_distribution["Medium"] == 1

      assert sub_obj3_result.proficiency_distribution["Low"] == 1
    end

    test "objectives_proficiency/3 returns empty list when given empty list" do
      objective_type_id = Oli.Resources.ResourceType.id_for_objective()

      author = insert(:author)
      project = insert(:project, authors: [author])
      section = insert(:section)
      publication = insert(:publication, project: project)

      insert(:section_project_publication,
        section: section,
        project: project,
        publication: publication
      )

      # Create objective with no children
      objective_resource = insert(:resource)

      objective_revision =
        insert(:revision,
          resource: objective_resource,
          author: author,
          title: "Solo Objective",
          resource_type_id: objective_type_id,
          content: %{}
        )

      insert(:published_resource,
        publication: publication,
        resource: objective_resource,
        revision: objective_revision
      )

      # Create SectionResource record needed for the depot
      insert(:section_resource,
        section: section,
        resource_id: objective_resource.id,
        title: "Solo Objective",
        children: []
      )

      # Test with empty list of section resources
      result = Metrics.objectives_proficiency(section.id, section.slug, [])
      assert result == []
    end

    test "objectives_proficiency/3 handles non-existent section resources gracefully" do
      section = insert(:section)
      # Create a mock section resource that doesn't exist in depot
      non_existent_section_resource = %{
        resource_id: 99999,
        title: "Non-existent"
      }

      result =
        Metrics.objectives_proficiency(section.id, section.slug, [non_existent_section_resource])

      # Should return one result with empty proficiency distribution
      assert length(result) == 1
      assert hd(result).sub_objective_id == 99999
      assert hd(result).title == "Non-existent"
      assert hd(result).proficiency_distribution == %{}
    end

    test "student_proficiency_for_objective/2 returns student proficiency data in correct format" do
      objective_type_id = Oli.Resources.ResourceType.id_for_objective()

      author = insert(:author)
      project = insert(:project, authors: [author])
      section = insert(:section)
      publication = insert(:publication, project: project)

      insert(:section_project_publication,
        section: section,
        project: project,
        publication: publication
      )

      # Create users
      user1 = insert(:user)
      user2 = insert(:user)
      user3 = insert(:user)

      insert(:enrollment, section: section, user: user1)
      insert(:enrollment, section: section, user: user2)
      insert(:enrollment, section: section, user: user3)

      # Create objective
      objective_resource = insert(:resource)

      objective_revision =
        insert(:revision,
          resource: objective_resource,
          author: author,
          title: "Test Objective",
          resource_type_id: objective_type_id,
          content: %{}
        )

      insert(:published_resource,
        publication: publication,
        resource: objective_resource,
        revision: objective_revision
      )

      # Create ResourceSummary records with different proficiency levels
      [
        # User 1 - High proficiency (90%)
        [
          -1,
          publication.id,
          section.id,
          user1.id,
          objective_resource.id,
          nil,
          objective_type_id,
          9,
          10,
          1,
          10,
          9
        ],
        # User 2 - Medium proficiency (60%)
        [
          -1,
          publication.id,
          section.id,
          user2.id,
          objective_resource.id,
          nil,
          objective_type_id,
          6,
          10,
          1,
          10,
          6
        ],
        # User 3 - Not enough data (only 2 attempts)
        [
          -1,
          publication.id,
          section.id,
          user3.id,
          objective_resource.id,
          nil,
          objective_type_id,
          1,
          2,
          1,
          2,
          1
        ]
      ]
      |> Enum.each(fn v -> add_resource_summary(v) end)

      result = Metrics.student_proficiency_for_objective(section.id, objective_resource.id)

      assert length(result) == 3

      # Find each user's result
      user1_result = Enum.find(result, &(&1.student_id == Integer.to_string(user1.id)))
      user2_result = Enum.find(result, &(&1.student_id == Integer.to_string(user2.id)))
      user3_result = Enum.find(result, &(&1.student_id == Integer.to_string(user3.id)))

      # Verify user 1 (High proficiency)
      assert_in_delta user1_result.proficiency, 0.9, 0.05
      assert user1_result.proficiency_range == "High"

      # Verify user 2 (Medium proficiency)
      assert_in_delta user2_result.proficiency, 0.6, 0.1
      assert user2_result.proficiency_range == "Medium"

      # Verify user 3 (Not enough data)
      assert user3_result.proficiency_range == "Not enough data"
    end

    test "student_proficiency_for_objective/2 returns empty list for objective with no student data" do
      section = insert(:section)
      result = Metrics.student_proficiency_for_objective(section.id, 99999)
      assert result == []
    end

    test "student_proficiency_for_objective/2 handles students with zero proficiency" do
      objective_type_id = Oli.Resources.ResourceType.id_for_objective()

      author = insert(:author)
      project = insert(:project, authors: [author])
      section = insert(:section)
      publication = insert(:publication, project: project)

      insert(:section_project_publication,
        section: section,
        project: project,
        publication: publication
      )

      user = insert(:user)
      insert(:enrollment, section: section, user: user)

      objective_resource = insert(:resource)

      objective_revision =
        insert(:revision,
          resource: objective_resource,
          author: author,
          title: "Test Objective",
          resource_type_id: objective_type_id,
          content: %{}
        )

      insert(:published_resource,
        publication: publication,
        resource: objective_resource,
        revision: objective_revision
      )

      # User with zero proficiency
      add_resource_summary([
        -1,
        publication.id,
        section.id,
        user.id,
        objective_resource.id,
        nil,
        objective_type_id,
        0,
        10,
        1,
        10,
        0
      ])

      result = Metrics.student_proficiency_for_objective(section.id, objective_resource.id)

      zero_result = Enum.find(result, &(&1.student_id == Integer.to_string(user.id)))

      assert zero_result.proficiency == 0.2
      assert zero_result.proficiency_range == "Low"
    end

    test "student_proficiency_for_objective/2 handles students with perfect proficiency" do
      objective_type_id = Oli.Resources.ResourceType.id_for_objective()

      author = insert(:author)
      project = insert(:project, authors: [author])
      section = insert(:section)
      publication = insert(:publication, project: project)

      insert(:section_project_publication,
        section: section,
        project: project,
        publication: publication
      )

      user = insert(:user)
      insert(:enrollment, section: section, user: user)

      objective_resource = insert(:resource)

      objective_revision =
        insert(:revision,
          resource: objective_resource,
          author: author,
          title: "Test Objective",
          resource_type_id: objective_type_id,
          content: %{}
        )

      insert(:published_resource,
        publication: publication,
        resource: objective_resource,
        revision: objective_revision
      )

      # User with perfect proficiency
      add_resource_summary([
        -1,
        publication.id,
        section.id,
        user.id,
        objective_resource.id,
        nil,
        objective_type_id,
        10,
        10,
        1,
        10,
        10
      ])

      result = Metrics.student_proficiency_for_objective(section.id, objective_resource.id)

      perfect_result = Enum.find(result, &(&1.student_id == Integer.to_string(user.id)))

      assert perfect_result.proficiency == 1.0
      assert perfect_result.proficiency_range == "High"
    end

    test "student_proficiency_for_objective/2 consistency with existing function" do
      objective_type_id = Oli.Resources.ResourceType.id_for_objective()

      author = insert(:author)
      project = insert(:project, authors: [author])
      section = insert(:section)
      publication = insert(:publication, project: project)

      insert(:section_project_publication,
        section: section,
        project: project,
        publication: publication
      )

      user = insert(:user)
      insert(:enrollment, section: section, user: user)

      objective_resource = insert(:resource)

      objective_revision =
        insert(:revision,
          resource: objective_resource,
          author: author,
          title: "Test Objective",
          resource_type_id: objective_type_id,
          content: %{}
        )

      insert(:published_resource,
        publication: publication,
        resource: objective_resource,
        revision: objective_revision
      )

      add_resource_summary([
        -1,
        publication.id,
        section.id,
        user.id,
        objective_resource.id,
        nil,
        objective_type_id,
        8,
        10,
        1,
        10,
        8
      ])

      # Test new function
      new_result = Metrics.student_proficiency_for_objective(section.id, objective_resource.id)
      user_new_result = Enum.find(new_result, &(&1.student_id == Integer.to_string(user.id)))

      # Test existing function
      existing_result =
        Metrics.proficiency_per_student_for_objective(section.id, [objective_resource.id])

      user_existing_result = existing_result[objective_resource.id][user.id]

      # Results should be consistent
      assert user_new_result.proficiency_range == user_existing_result
    end
  end
end
