# frozen_string_literal: true

#
# Copyright (C) 2014-2016 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 "apis/api_spec_helper"

describe GradingPeriodsController, type: :request do
  let(:now) { Time.zone.now.change(usec: 0) }

  context "A grading period is associated with a course." do
    before :once do
      course_with_teacher active_all: true
      grading_period_group = @course.grading_period_groups.create!(title: "A Group")
      @grading_period = grading_period_group.grading_periods.create! do |period|
        period.title = "A Period"
        period.start_date = 1.month.from_now(now)
        period.end_date   = 2.months.from_now(now)
        period.weight     = 33.33
      end
    end

    describe "GET show" do
      def get_show(raw = false)
        helper = method(raw ? :raw_api_call : :api_call)
        helper.call(
          :get,
          "/api/v1/courses/#{@course.id}/grading_periods/#{@grading_period.id}",
          {
            controller: "grading_periods",
            action: "show",
            format: "json",
            course_id: @course.id,
            id: @grading_period.id,
          },
          {}
        )
      end

      it "retrieves the grading period specified" do
        json = get_show
        period = json["grading_periods"].first
        expect(period["id"]).to eq(@grading_period.id.to_s)
        expect(period["weight"]).to eq(@grading_period.weight)
        expect(period["title"]).to eq(@grading_period.title)
        expect(period["permissions"]).to include(
          "read" => true,
          "create" => false,
          "delete" => true,
          "update" => true
        )
      end

      it "doesn't return deleted grading periods" do
        @grading_period.destroy
        get_show(true)
        expect(response).to have_http_status :not_found
      end
    end

    describe "PUT update" do
      def put_update(params, raw = false)
        helper = method(raw ? :raw_api_call : :api_call)

        helper.call(
          :put,
          "/api/v1/courses/#{@course.id}/grading_periods/#{@grading_period.id}",
          {
            controller: "grading_periods",
            action: "update",
            format: "json",
            course_id: @course.id,
            id: @grading_period.id
          },
          { grading_periods: [params] }
        )
      end

      it "updates a grading period successfully" do
        new_weight = @grading_period.weight + 11.11
        put_update(weight: new_weight)
        expect(@grading_period.reload.weight).to eql(new_weight)
      end

      it "doesn't update deleted grading periods" do
        @grading_period.destroy
        put_update({ weight: 80 }, true)
        expect(response).to have_http_status :not_found
      end
    end

    describe "DELETE destroy" do
      def delete_destroy
        raw_api_call(
          :delete,
          "/api/v1/courses/#{@course.id}/grading_periods/#{@grading_period.id}",
          {
            controller: "grading_periods",
            action: "destroy",
            format: "json",
            course_id: @course.id,
            id: @grading_period.id.to_s
          }
        )
      end

      it "deletes a grading period successfully" do
        delete_destroy

        expect(response).to have_http_status :no_content
        expect(@grading_period.reload).to be_deleted
      end
    end
  end
end
