# frozen_string_literal: true

#
# Copyright (C) 2014 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.

require "spec_helper"

describe CanvasQuizStatistics::Analyzers::FillInMultipleBlanks do
  subject { described_class.new(question_data) }

  let(:question_data) { QuestionHelpers.fixture("fill_in_multiple_blanks_question") }

  it "does not blow up when no responses are provided" do
    expect do
      subject.run([])
    end.to_not raise_error
  end

  describe "[:answer_sets]" do
    describe "[][:answers][:responses]" do
      it "counts those who filled in a correct answer" do
        stats = subject.run([
                              {
                                answer_for_color1: "Red",
                                answer_id_for_color1: "9711"
                              }
                            ])

        answer_set = stats[:answer_sets].detect { |as| as[:text] == "color1" }
        answer = answer_set[:answers].detect { |a| a[:text] == "Red" }
        expect(answer[:responses]).to eq(1)
      end

      it "stringifies ids" do
        stats = subject.run([
                              {
                                answer_for_color1: "Red",
                                answer_id_for_color1: 9711
                              }
                            ])

        answer_set = stats[:answer_sets].detect { |as| as[:text] == "color1" }
        answer = answer_set[:answers].detect { |a| a[:text] == "Red" }
        expect(answer[:responses]).to eq(1)
      end

      it "counts those who filled in an unknown answer" do
        stats = subject.run([
                              {
                                answer_for_color1: "purple",
                                answer_id_for_color1: nil
                              }
                            ])

        answer_set = stats[:answer_sets].detect { |as| as[:text] == "color1" }
        answer = answer_set[:answers].detect { |a| a[:id] == Constants::UnknownAnswerKey }
        expect(answer).to be_present
        expect(answer[:responses]).to eq(1)
      end

      it "counts those who did not fill in any answer" do
        stats = subject.run([
                              {
                                answer_for_color1: "",
                                answer_id_for_color1: nil
                              }
                            ])

        answer_set = stats[:answer_sets].detect { |as| as[:text] == "color1" }
        answer = answer_set[:answers].detect { |a| a[:id] == Constants::MissingAnswerKey }
        expect(answer).to be_present
        expect(answer[:responses]).to eq(1)
      end

      it "does not generate the unknown or missing answers unless needed" do
        stats = subject.run([
                              {
                                answer_for_color1: "Red",
                                answer_id_for_color1: "9711"
                              }
                            ])

        stats[:answer_sets].detect { |as| as[:text] == "color1" }.tap do |answer_set|
          unknown_answer = answer_set[:answers].detect { |a| a[:id] == Constants::UnknownAnswerKey }
          missing_answer = answer_set[:answers].detect { |a| a[:id] == Constants::MissingAnswerKey }

          expect(unknown_answer).not_to be_present
          expect(missing_answer).not_to be_present
        end

        stats[:answer_sets].detect { |as| as[:text] == "color2" }.tap do |answer_set|
          unknown_answer = answer_set[:answers].detect { |a| a[:id] == Constants::UnknownAnswerKey }
          missing_answer = answer_set[:answers].detect { |a| a[:id] == Constants::MissingAnswerKey }

          expect(unknown_answer).not_to be_present
          expect(missing_answer).to be_present
          expect(missing_answer[:responses]).to eq(1)
        end
      end
    end
  end

  it_behaves_like "[:correct]"
  it_behaves_like "[:partially_correct]"
  it_behaves_like "[:incorrect]"

  describe "[:responses]" do
    it "counts all students who have filled any blank" do
      stats = subject.run([
                            {
                              answer_id_for_color1: "9711"
                            }
                          ])

      expect(stats[:responses]).to eq(1)
    end

    it "does not count students who didnt" do
      expect(subject.run([{}])[:responses]).to eq(0)
    end

    it "does not consider an answer to be present if it's empty" do
      expect(subject.run([{
                           answer_for_color: ""
                         }])[:responses]).to eq(0)

      expect(subject.run([{
                           answer_for_color: nil
                         }])[:responses]).to eq(0)
    end
  end

  describe "[:answered]" do
    it "counts students who have filled every blank" do
      stats = subject.run([
                            {
                              answer_id_for_color1: "9711",
                              answer_id_for_color2: "9702"
                            }
                          ])

      expect(stats[:answered]).to eq(1)
    end

    it "counts students who have filled every blank, even if incorrectly" do
      stats = subject.run([
                            {
                              answer_for_color1: "foo",
                              answer_for_color2: "bar"
                            }
                          ])

      expect(stats[:answered]).to eq(1)
    end

    it "does not count a student who has left any blank" do
      stats = subject.run([
                            {
                              answer_for_color1: "purple"
                            }
                          ])

      expect(stats[:answered]).to eq(0)
    end
  end
end
