# frozen_string_literal: true

#
# Copyright (C) 2016 - 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/>.

module SpecComponents
  module Assignable
    attr_reader :id, :title

    def assign_to(_opts = {})
      raise NotImplementedError, 'You must implement the assign_to() method!'
    end

    def submit_as(_user)
      raise NotImplementedError, 'You must implement the submit_as() method!'
    end

    private

      def add_assignment_override(assignment, opts)
        raise ArgumentError, 'Missing argument for assignment override!' if opts[:user].nil? && opts[:section].nil? && opts[:group].nil?

        add_assignment_override_for_student(opts) if opts[:user]
        add_assignment_override_for_section(opts) if opts[:section]
        add_assignment_override_for_group(opts) if opts[:group]

        assignment.only_visible_to_overrides = true
        assignment.save!
        assignment.reload
      end

      def add_assignment_override_for_student(opts)
        assignment_override = create_assignment_override(opts)
        yield assignment_override

        assignment_override.title = 'Student Override'
        assignment_override.set_type = 'ADHOC'
        assignment_override.save!

        override_student = assignment_override.assignment_override_students.build
        override_student.user = opts[:user]
        override_student.save!
      end

      def add_assignment_override_for_section(opts)
        assignment_override = create_assignment_override(opts)
        yield assignment_override

        assignment_override.set = opts[:section]
        assignment_override.set_type = 'CourseSection'
        assignment_override.save!
      end

      def add_assignment_override_for_group(opts)
        # TODO: define this after DA for Groups is merged
      end

      def create_assignment_override(opts)
        assignment_override = AssignmentOverride.new()
        assignment_override.workflow_state = 'active'
        set_override_dates(assignment_override, opts)
        assignment_override
      end

      def set_override_dates(override, opts = {})
        override.due_at               = opts.fetch(:due_at, Time.zone.now.advance(days: 7))
        override.due_at_overridden    = true
        override.lock_at              = opts.fetch(:lock_at, Time.zone.now.advance(days: 7))
        override.lock_at_overridden   = true
        override.unlock_at            = opts.fetch(:unlock_at, Time.zone.now.advance(days: -1))
        override.unlock_at_overridden = true
      end
  end
end
