# frozen_string_literal: true

#
# Copyright (C) 2011 - 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 Polling
  class Poll < ActiveRecord::Base
    belongs_to :user
    has_many :poll_choices, -> { order(:position) }, class_name: "Polling::PollChoice", dependent: :destroy
    has_many :poll_submissions, class_name: "Polling::PollSubmission", dependent: :destroy
    has_many :poll_sessions, class_name: "Polling::PollSession", dependent: :destroy

    validates :question, :user, presence: true
    validates :question, length: { maximum: 255, allow_nil: true }
    validates :description, length: { maximum: 255, allow_nil: true }

    set_policy do
      given { |user| self.user.present? && self.user == user }
      can :update and can :read and can :delete

      given { |user| TeacherEnrollment.active.where(user_id: user).exists? }
      can :create

      given do |user, http_session|
        poll_sessions.shard(self).preload(:course).any? do |session|
          session.course.grants_right?(user, http_session, :manage_course_content_add)
        end
      end
      can :read and can :submit

      given do |user, http_session|
        poll_sessions.shard(self).preload(:course).any? do |session|
          session.course.grants_right?(user, http_session, :manage_course_content_edit)
        end
      end
      can :read and can :update

      given do |user, http_session|
        poll_sessions.shard(self).preload(:course).any? do |session|
          session.course.grants_right?(user, http_session, :manage_course_content_delete)
        end
      end
      can :read and can :delete

      given do |user|
        can_read = false
        poll_sessions.shard(self).activate do |scope|
          if scope.where(["course_id IN (?) AND (course_section_id IS NULL OR course_section_id IN (?))",
                          Enrollment.where(user_id: user).active.select(:course_id),
                          Enrollment.where(user_id: user).active.select(:course_section_id)]).exists?
            can_read = true
            break
          end
        end
        can_read
      end
      can :read
    end

    delegate :associated_shards, to: :user

    def closed_and_viewable_for?(user)
      poll_sessions.shard(self).activate do |scope|
        return true if scope
                       .joins(:poll_submissions)
                       .where(["polling_poll_submissions.user_id = ? AND is_published=? AND course_id IN (?) AND (course_section_id IS NULL OR course_section_id IN (?))",
                               user,
                               false,
                               Enrollment.where(user_id: user).active.select(:course_id),
                               Enrollment.where(user_id: user).active.select(:course_section_id)])
                       .order("polling_poll_sessions.created_at DESC")
                       .limit(1)
                       .exists?
      end
      false
    end

    def total_results
      poll_submissions.shard(self).group("poll_choice_id").count
    end
  end
end
