# 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/>.
#

require "feedjira"

describe AnnouncementsController do
  before :once do
    course_with_student(active_all: true)
  end

  def course_announcement(opts = {})
    @announcement = @course.announcements.create!({
      title: "some announcement",
      message: "some message"
    }.merge(opts))
  end

  describe "GET 'index'" do
    it "returns unauthorized without a valid session" do
      get "index", params: { course_id: @course.id }
      assert_unauthorized
    end

    it "redirects 'disabled', if disabled by the teacher" do
      user_session(@user)
      @course.update_attribute(:tab_configuration, [{ "id" => 14, "hidden" => true }])
      get "index", params: { course_id: @course.id }
      expect(response).to be_redirect
      expect(flash[:notice]).to match(/That page has been disabled/)
    end

    it "returns new bundle for group announcements" do
      user_session(@user)
      @course.group_categories.create!(name: "My Group Category")
      group = @course.groups.create!(name: "My Group", group_category: @course.group_categories.first)
      group.add_user(@user)
      group.save!
      get "index", params: { group_id: group.id }
      expect(response).to be_successful
      expect(assigns[:js_bundles].length).to eq 1
      expect(assigns[:js_bundles].first).to include :announcements
      expect(assigns[:js_bundles].first).not_to include :announcements_index
    end

    it "returns new bundle for course announcements if section specific enabled" do
      user_session(@user)
      @course.announcements.create!(message: "hello!")
      get "index", params: { course_id: @course.id }
      expect(response).to be_successful
      expect(assigns[:js_bundles].length).to eq 1
      expect(assigns[:js_bundles].first).to include :announcements
      expect(assigns[:js_bundles].first).not_to include :announcements_index
    end
  end

  describe "GET 'public_feed.atom'" do
    before :once do
      @context = @course
      announcement_model
    end

    it "requires authorization" do
      get "public_feed", format: "atom", params: { feed_code: @enrollment.feed_code + "x" }
      expect(assigns[:problem]).to match(/The verification code does not match/)
    end

    it "includes absolute path for rel='self' link" do
      get "public_feed", format: "atom", params: { feed_code: @enrollment.feed_code }
      feed = Feedjira.parse(response.body)
      expect(feed).not_to be_nil
      expect(feed.feed_url).to match(%r{http://})
    end

    it "includes an author for each entry" do
      get "public_feed", format: "atom", params: { feed_code: @enrollment.feed_code }
      feed = Feedjira.parse(response.body)
      expect(feed).not_to be_nil
      expect(feed.entries).not_to be_empty
      expect(feed.entries.all? { |e| e.author.present? }).to be_truthy
    end

    it "shows the 15 most recent announcements" do
      announcement_ids = []
      16.times { announcement_ids << course_announcement.id }
      announcement_ids.shift # Drop first announcement so we have the 15 most recent

      get "public_feed", format: "atom", params: { feed_code: @enrollment.feed_code }

      feed_entries = Feedjira.parse(response.body).entries
      feed_entry_ids = feed_entries.map { |e| e.id.gsub(/.*topic_/, "").to_i }
      expect(feed_entry_ids).to match_array(announcement_ids)
    end

    it "shows the 15 most recent announcements when posted_at is nil" do
      announcement_ids = []
      16.times { announcement_ids << course_announcement.id }
      Announcement.where(id: announcement_ids).update_all(posted_at: nil)
      announcement_ids.shift # Drop first announcement so we have the 15 most recent
      get "public_feed", format: "atom", params: { feed_code: @enrollment.feed_code }

      feed_entries = Feedjira.parse(response.body).entries
      feed_entry_ids = feed_entries.map { |e| e.id.gsub(/.*topic_/, "").to_i }
      expect(feed_entry_ids).to match_array(announcement_ids)
    end

    it "only shows announcements that are visible to the caller" do
      normal_ann = @a # from the announcement_model in the before block
      closed_for_comments_ann = course_announcement(locked: true)
      post_delayed_ann = @course.announcements.build({
                                                       title: "hi",
                                                       message: "blah",
                                                       delayed_post_at: 1.day.from_now
                                                     })
      post_delayed_ann.workflow_state = "post_delayed"
      post_delayed_ann.save!
      deleted_ann = course_announcement
      deleted_ann.destroy

      expect(closed_for_comments_ann).to be_locked
      expect(post_delayed_ann).to be_post_delayed
      expect(deleted_ann).to be_deleted
      visible_announcements = [normal_ann, closed_for_comments_ann]

      get "public_feed", format: "atom", params: { feed_code: @enrollment.feed_code }

      feed_entries = Feedjira.parse(response.body).entries
      feed_entry_ids = feed_entries.map { |e| e.id.gsub(/.*topic_/, "").to_i }
      expect(feed_entry_ids).to match_array(visible_announcements.map(&:id))
    end
  end
end
