# frozen_string_literal: true

#
# Copyright (C) 2018 - 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_relative "../../common"
require_relative "../../helpers/speed_grader_common"
require_relative "../pages/moderate_page"
require_relative "../pages/speedgrader_page"

describe "SpeedGrader" do
  include_context "in-process server selenium tests"
  include SpeedGraderCommon

  before(:once) do
    # a course with 1 teacher
    @teacher1 = course_with_teacher(name: "Teacher1", active_all: true).user
    @teacher2 = course_with_teacher(course: @course, name: "Teacher2", active_all: true).user
    @teacher3 = course_with_teacher(course: @course, name: "Teacher3", active_all: true).user

    # enroll two students
    @student1 = User.create!(name: "First Student")
    @student1.register!
    @course.enroll_student(@student1, enrollment_state: "active")

    @student2 = User.create!(name: "Second Student")
    @student2.register!
    @course.enroll_student(@student2, enrollment_state: "active")
  end

  context "with a moderated assignment" do
    before do
      @moderated_assignment = @course.assignments.create!(
        title: "Moderated Assignment1",
        grader_count: 2,
        final_grader_id: @teacher1.id,
        grading_type: "points",
        points_possible: 15,
        submission_types: "online_text_entry",
        moderated_grading: true
      )
    end

    it "prevents posting grades before they are released", priority: "2" do
      @moderated_assignment.grade_student(@student1, grade: "2", grader: @teacher2, provisional: true).first
      @moderated_assignment.grade_student(@student1, grade: "3", grader: @teacher3, provisional: true)

      user_session(@teacher1)
      ModeratePage.visit(@course.id, @moderated_assignment.id)
      ModeratePage.select_provisional_grade_for_student_by_position(@student1, 0)

      Speedgrader.visit(@course.id, @moderated_assignment.id)

      Speedgrader.click_post_or_hide_grades_button
      expect(Speedgrader.no_grades_to_post_button).to be_displayed
    end

    it "allows posting grades after they are released", priority: "2" do
      @moderated_assignment.grade_student(@student1, grade: "2", grader: @teacher2, provisional: true).first
      @moderated_assignment.grade_student(@student1, grade: "3", grader: @teacher3, provisional: true)

      user_session(@teacher1)
      ModeratePage.visit(@course.id, @moderated_assignment.id)
      ModeratePage.select_provisional_grade_for_student_by_position(@student1, 0)

      ModeratePage.click_release_grades_button
      accept_alert
      wait_for_ajaximations

      Speedgrader.visit(@course.id, @moderated_assignment.id)

      Speedgrader.click_post_or_hide_grades_button
      expect(Speedgrader.post_grades_link).to be_displayed
    end

    it "allows adding provisional grades", priority: "2" do
      user_session(@teacher2)
      Speedgrader.visit(@course.id, @moderated_assignment.id)
      Speedgrader.enter_grade(10)
      wait_for_ajaximations
      expect(@moderated_assignment.provisional_grades.first.scorer_id).to eq @teacher2.id
    end

    it "shows multiple provisional grades", priority: "2" do
      @moderated_assignment.grade_student(@student1, grade: "2", grader: @teacher2, provisional: true)
      @moderated_assignment.grade_student(@student1, grade: "3", grader: @teacher3, provisional: true)

      user_session(@teacher1)
      Speedgrader.visit(@course.id, @moderated_assignment.id)
      Speedgrader.show_details_button.click
      expect(Speedgrader.provisional_grade_radio_buttons.length).to eq 3
      expect(Speedgrader.grading_details_container.text).to include "Custom"
      expect(Speedgrader.grading_details_container.text).to include "Teacher2"
      expect(Speedgrader.grading_details_container.text).to include "Teacher3"
    end

    it "allows selecting a custom grade", priority: "1" do
      @moderated_assignment.grade_student(@student1, grade: "2", grader: @teacher2, provisional: true)
      @moderated_assignment.grade_student(@student1, grade: "3", grader: @teacher3, provisional: true)

      user_session(@teacher1)
      Speedgrader.visit(@course.id, @moderated_assignment.id)
      Speedgrader.show_details_button.click
      Speedgrader.select_provisional_grade_by_label("Custom")
      Speedgrader.enter_grade(12)
      wait_for_ajaximations

      pg = @moderated_assignment.provisional_grades.last
      selections = @moderated_assignment.moderated_grading_selections

      expect(pg.score).to eq 12
      expect(selections.where(selected_provisional_grade_id: pg.id).exists?).to be true
    end
  end

  context "with an anonymous moderated assignment and provisional comments" do
    before(:once) do
      @moderated_assignment = @course.assignments.create!(
        title: "Moderated Assignment1",
        grader_count: 2,
        final_grader_id: @teacher1.id,
        grading_type: "points",
        points_possible: 15,
        submission_types: "online_text_entry",
        moderated_grading: true
      )
      @moderated_assignment.update_submission(
        @student1,
        author: @teacher2,
        comment: "Some comment text by non-final grader",
        provisional: true
      )
      @moderated_assignment.update_submission(
        @student1,
        author: @teacher3,
        comment: "Some comment text by another non-final grader",
        provisional: true
      )
      @moderated_assignment.update_submission(
        @student2,
        author: @teacher2,
        comment: "Some comment text by non-final grader",
        provisional: true
      )
      @moderated_assignment.update_submission(
        @student2,
        author: @teacher3,
        comment: "Some comment text by another non-final grader",
        provisional: true
      )
      ModerationGrader.find_by(user: @teacher2, assignment: @moderated_assignment).update!(anonymous_id: "AAAAA")
      ModerationGrader.find_by(user: @teacher3, assignment: @moderated_assignment).update!(anonymous_id: "BBBBB")
    end

    it "graders cannot view other grader's comments when `grader_comments_visible_to_graders = false`",
       priority: 1 do
      @moderated_assignment.update!(grader_comments_visible_to_graders: false)
      user_session(@teacher3)
      Speedgrader.visit(@course.id, @moderated_assignment.id)

      # dont see Teacher2's comment
      expect(Speedgrader.comments.first.text).not_to include "Some comment text by non-final grader"
      expect(Speedgrader.comment_citation.first.text).not_to eq "Teacher2"

      # see comment made by self
      expect(Speedgrader.comments.first.text).to include "Some comment text by another non-final grader"
      expect(Speedgrader.comment_citation.first.text).to eq "Teacher3"
    end

    it "graders can view other grader's comments when `grader_comments_visible_to_graders = true`" do
      @moderated_assignment.update!(grader_comments_visible_to_graders: true)
      user_session(@teacher3)
      Speedgrader.visit(@course.id, @moderated_assignment.id)

      expect(Speedgrader.comments.first.text).to include "Some comment text by non-final grader"
      expect(Speedgrader.comment_citation.first.text).to eq "Teacher2"
    end

    it "final-grader can view other grader's comments by default", priority: 1 do
      user_session(@teacher1)
      Speedgrader.visit(@course.id, @moderated_assignment.id)

      expect(Speedgrader.comments.first.text).to include "Some comment text by non-final grader"
      expect(Speedgrader.comment_citation.first.text).to eq "Teacher2"
    end

    it "final-grader cannot view other grader's name with `grader_names_visible_to_final_grader = false`" do
      @moderated_assignment.update!(
        anonymous_grading: true,
        graders_anonymous_to_graders: true,
        grader_names_visible_to_final_grader: false
      )
      user_session(@teacher1)
      Speedgrader.visit(@course.id, @moderated_assignment.id)

      expect(Speedgrader.comments.first.text).to include "Some comment text by non-final grader"
      expect(Speedgrader.comment_citation.first.text).to eq "Grader 1"
    end

    it "anonymizes grader comments for other non-final graders when `graders_anonymous_to_graders = true`",
       priority: 1 do
      @moderated_assignment.update!(
        grader_comments_visible_to_graders: true,
        anonymous_grading: true,
        graders_anonymous_to_graders: true,
        grader_names_visible_to_final_grader: false
      )
      user_session(@teacher3)
      Speedgrader.visit(@course.id, @moderated_assignment.id)
      Speedgrader.click_next_student_btn

      expect(Speedgrader.comments.length).to eq 2
      expect(Speedgrader.comments.first.text).to include "Some comment text by non-final grader"
      expect(Speedgrader.comment_citation.first.text).to eq "Grader 1"
    end
  end

  context "with a moderated anonymous assignment" do
    before(:once) do
      @moderated_anonymous_assignment = @course.assignments.create!(
        title: "Moderated Anonymous Assignment1",
        grader_count: 2,
        final_grader_id: @teacher1.id,
        moderated_grading: true,
        grader_comments_visible_to_graders: true,
        anonymous_grading: true,
        graders_anonymous_to_graders: true,
        grader_names_visible_to_final_grader: false
      )
    end

    it "anonymizes grader names in provisional grade details", priority: "2" do
      @moderated_anonymous_assignment.grade_student(@student1, grade: "2", grader: @teacher2, provisional: true)
      @moderated_anonymous_assignment.grade_student(@student1, grade: "3", grader: @teacher3, provisional: true)

      @moderated_anonymous_assignment.grade_student(@student2, grade: "2", grader: @teacher2, provisional: true)
      @moderated_anonymous_assignment.grade_student(@student2, grade: "3", grader: @teacher3, provisional: true)

      user_session(@teacher1)
      Speedgrader.visit(@course.id, @moderated_anonymous_assignment.id)
      Speedgrader.show_details_button.click

      expect(Speedgrader.grading_details_container.text).to include "Grader 1"
      expect(Speedgrader.grading_details_container.text).to include "Grader 2"
    end
  end
end
