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

describe ObserverPairingCodesApiController, type: :request do
  include Api

  describe "#create" do
    before :once do
      @student = student_in_course(active_all: true).user
      @course.account.enable_self_registration
      @path = "/api/v1/users/#{@student.id}/observer_pairing_codes"
      @params = { user_id: @student.to_param,
                  controller: "observer_pairing_codes_api",
                  action: "create",
                  format: "json" }
    end

    it "does not permit pairing code generation if self-registration is disabled" do
      ap = @course.account.canvas_authentication_provider
      ap.self_registration = "none"
      ap.save!
      api_call_as_user(@student, :post, @path, @params)
      expect(response).to have_http_status :forbidden
    end

    it "students can create pairing codes for themselves" do
      json = api_call_as_user(@student, :post, @path, @params)
      expect(json["user_id"]).to eq @student.id
      expect(json["expires_at"].between?(6.days.from_now, 7.days.from_now)).to be true
      expect(json["workflow_state"]).to eq "active"
      expect(json["code"].length).to eq 6
    end

    it "errors if user_id passed in isnt a student" do
      user = user_model
      params = @params.merge(user_id: user.to_param)
      path = "/api/v1/users/#{user.id}/observer_pairing_codes"
      api_call_as_user(user, :post, path, params)
      expect(response).to have_http_status :forbidden
    end

    it "teacher cannot generate code by default" do
      teacher = teacher_in_course(course: @course, active_all: true).user
      json = api_call_as_user(teacher, :post, @path, @params)
      expect(response).to have_http_status :forbidden
      expect(json["code"]).to be_nil
    end

    it "works for teachers in courses that are not published yet" do
      course_factory
      course_with_teacher(course: @course)
      course_with_student(course: @course)
      @course.account.role_overrides.create!(permission: :generate_observer_pairing_code, enabled: true, role: teacher_role)

      path = "/api/v1/users/#{@student.id}/observer_pairing_codes"
      params = @params.merge(user_id: @student.to_param)
      api_call_as_user(@teacher, :post, path, params)
      expect(response).to have_http_status :ok
    end

    it "does not work for deleted courses" do
      course_factory
      course_with_teacher(course: @course)
      course_with_student(course: @course)
      @course.destroy

      path = "/api/v1/users/#{@student.id}/observer_pairing_codes"
      params = @params.merge(user_id: @student.to_param)
      api_call_as_user(@teacher, :post, path, params)
      expect(response).to have_http_status :forbidden
    end

    it "admin can generate code" do
      admin = account_admin_user(account: Account.default)
      json = api_call_as_user(admin, :post, @path, @params)
      expect(response).to have_http_status :ok
      expect(json["code"]).not_to be_nil
    end

    it "errors if current_user isnt the student or a teacher/admin" do
      api_call_as_user(user_model, :post, @path, @params)
      expect(response).to have_http_status :forbidden
    end

    describe "sub_accounts" do
      before :once do
        @sub_account = Account.create! root_account: Account.default
        @student = course_with_student(account: @sub_account, active_all: true).user
        @sub_admin = account_admin_user(account: @sub_account)
        @path = "/api/v1/users/#{@student.id}/observer_pairing_codes"
        @params = { user_id: @student.to_param,
                    controller: "observer_pairing_codes_api",
                    action: "create",
                    format: "json" }
      end

      it "sub_account admin can generate code" do
        json = api_call_as_user(@sub_admin, :post, @path, @params)
        expect(response).to have_http_status :ok
        expect(json["code"]).not_to be_nil
      end

      it "sub_account admin cant generate code for students in other sub accounts" do
        other_sub_account = Account.create! root_account: Account.default
        other_student = course_with_student(account: other_sub_account, active_all: true).user
        path = "/api/v1/users/#{other_student.id}/observer_pairing_codes"
        params = { user_id: other_student.to_param,
                   controller: "observer_pairing_codes_api",
                   action: "create",
                   format: "json" }
        api_call_as_user(@sub_admin, :post, path, params)
        expect(response).to have_http_status :forbidden
      end
    end
  end
end
