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

require_relative "../common"

describe "admin settings tab" do
  include_context "in-process server selenium tests"
  let(:account) { Account.default }
  let(:sub_account) { account.sub_accounts.create!(name: "sub-account") }

  before do
    user_logged_in(user: site_admin_user(account:))
  end

  def get_settings_page(account)
    get "/accounts/#{account.id}/settings"
  end

  def set_checkbox(id, checked)
    checkbox = f(id)
    checkbox.click if is_checked(checkbox) != checked
  end

  def set_checkbox_via_label(id, checked)
    # Use this method for checkboxes that are hidden by their label (ic-Checkbox)
    checkbox = f(id)
    label = f("label[for=\"#{id[1..]}\"]")
    scroll_into_view(label)
    label.click if is_checked(checkbox) != checked
  end

  def get_checkbox(id)
    checkbox = f(id)
    is_checked(checkbox)
  end

  def click_submit
    expect_new_page_load do
      f("#account_settings button[type=submit]").click
    end
  end

  context "SIS Agent Token Authentication" do
    let(:sis_token) { "too much tuna" }

    it "tests SIS Agent Token Authentication with post_grades feature enabled", priority: "2" do
      user = account_admin_user({ active_user: true }.merge(account: Account.site_admin))
      course_with_admin_logged_in(account: Account.default, user:)
      account.enable_feature!(:post_grades)

      get_settings_page(account)
      expect(f("#add_sis_app_token")).to be_displayed
      expect(f("#account_settings_sis_app_token")).to be_displayed
      f("#account_settings_sis_app_token").send_keys(sis_token)
      click_submit
      token = f("#account_settings_sis_app_token")
      expect(token).to have_value(sis_token)
    end

    it "tests SIS Agent Token Authentication with post_grades feature disabled", priority: "2" do
      user = account_admin_user({ active_user: true }.merge(account: Account.site_admin))
      course_with_admin_logged_in(account: Account.default, user:)
      get_settings_page(account)
      expect(f("#add_sis_app_token")).to be_displayed
      expect(f("#account_settings_sis_app_token")).to be_displayed
      f("#account_settings_sis_app_token").send_keys(sis_token)
      click_submit
      token = f("#account_settings_sis_app_token")
      expect(token).to have_value(sis_token)
    end
  end

  context "SIS Integration Settings" do
    let(:allow_sis_import) { "#account_allow_sis_import" }
    let(:sis_syncing) { "#account_settings_sis_syncing_value" }
    let(:sis_syncing_locked) { "#account_settings_sis_syncing_locked" }
    let(:default_grade_export) { "#account_settings_sis_default_grade_export_value" }
    let(:require_assignment_due_date) { "#account_settings_sis_require_assignment_due_date_value" }
    let(:sis_name) { "#account_settings_sis_name" }
    let(:assignment_name_length) { "#account_settings_sis_assignment_name_length_value" }
    let(:assignment_name_length_input) { "#account_settings_sis_assignment_name_length_input_value" }

    def test_checkbox_on(id)
      set_checkbox_via_label(id, true)
      click_submit
      expect(get_checkbox(id)).to be_truthy
    end

    def test_checkbox_off(id)
      set_checkbox_via_label(id, false)
      click_submit
      expect(get_checkbox(id)).to be_falsey
    end

    context ":new_sis_integrations => false" do
      before do
        account.set_feature_flag! :new_sis_integrations, "off"
      end

      it "persists SIS import settings is on" do
        get_settings_page(account)
        test_checkbox_on(allow_sis_import)
      end

      it "persists SIS import setting is off" do
        get_settings_page(account)
        test_checkbox_off(allow_sis_import)
      end

      it "does not display SIS syncing setting" do
        get_settings_page(account)
        expect(f("body")).not_to contain_css(sis_syncing)
      end

      context "SIS post grades disabled" do
        before do
          account.set_feature_flag! "post_grades", "off"
          get_settings_page(account)
        end

        it "does not display 'Sync Grades to SIS'" do
          expect(f("body")).not_to contain_css(default_grade_export)
        end
      end

      context "SIS post grades enabled" do
        before do
          account.set_feature_flag! "post_grades", "on"
          get_settings_page(account)
        end

        it "persists 'Sync Grades to SIS' on" do
          test_checkbox_on(default_grade_export)
        end

        it "persists 'Sync Grades to SIS' off" do
          test_checkbox_off(default_grade_export)
        end
      end
    end

    context ":new_sis_integrations => true (sub account)" do
      before do
        account.set_feature_flag! :new_sis_integrations, "on"
        get_settings_page(sub_account)
      end

      it "has SIS name setting disabled for sub accounts" do
        name_setting = f(sis_name)
        expect(name_setting.displayed?).to be_truthy
        expect(name_setting.enabled?).to be_falsey
      end
    end

    context ":new_sis_integrations => true (root account)" do
      before do
        account.set_feature_flag! :new_sis_integrations, "on"
      end

      it "persists custom SIS name" do
        get_settings_page(account)
        custom_sis_name = "PowerSchool"
        f(sis_name).send_keys(custom_sis_name)
        click_submit
        expect(f(sis_name)).to have_value(custom_sis_name)
      end

      it "persists SIS import setting is on" do
        get_settings_page(account)
        test_checkbox_on(allow_sis_import)
      end

      it "persists SIS import setting is off" do
        get_settings_page(account)
        test_checkbox_off(allow_sis_import)
      end

      context "SIS post grades disabled" do
        before do
          account.set_feature_flag! "post_grades", "off"
          get_settings_page(account)
        end

        it "does not display SIS Syncing option" do
          expect(f("body")).not_to contain_css(sis_syncing)
        end

        it "does not display the 'Sync Grades to SIS' option" do
          expect(f("body")).not_to contain_css(default_grade_export)
        end
      end

      context "SIS post grades enabled" do
        before do
          account.set_feature_flag! "post_grades", "on"
        end

        it "persists SIS import setting is on" do
          get_settings_page(account)
          test_checkbox_on(sis_syncing)
        end

        it "persists SIS import setting is off" do
          get_settings_page(account)
          test_checkbox_off(sis_syncing)
        end

        context "SIS syncing => false" do
          before do
            account.settings = { sis_syncing: { value: false } }
            account.save
            get_settings_page(account)
          end

          it "does not display the 'Sync Grades to SIS' option" do
            expect(f(default_grade_export)).not_to be_displayed
          end
        end

        context "SIS syncing => true" do
          before do
            account.settings = { sis_syncing: { value: true } }
            account.save
            get_settings_page(account)
          end

          it { test_checkbox_off(sis_syncing_locked) }
          it { test_checkbox_on(sis_syncing_locked) }

          it "toggles assignment name length on" do
            set_checkbox_via_label(default_grade_export, true)
            test_checkbox_on(assignment_name_length)
          end

          it "toggles assignment name length off" do
            set_checkbox_via_label(default_grade_export, true)
            test_checkbox_off(assignment_name_length)
          end

          it "tests sis assignment name length" do
            set_checkbox_via_label(default_grade_export, true)
            set_checkbox_via_label(assignment_name_length, true)
            name_length = 123
            f("#account_settings_sis_assignment_name_length_input_value").send_keys(name_length)
            click_submit
            expect(f("#account_settings_sis_assignment_name_length_input_value")).to have_value(name_length.to_s)
          end

          it "persists 'Sync Grades to SIS' on" do
            test_checkbox_on(default_grade_export)
          end

          it "persists 'Sync Grades to SIS' off" do
            test_checkbox_off(default_grade_export)
          end
        end
      end

      context "root and sub-accounts" do
        before do
          account.set_feature_flag! "post_grades", "on"
        end

        context "unlocked for sub-accounts" do
          before do
            account.settings = { sis_syncing: { value: true, locked: false } }
            account.save
          end

          it "allows SIS integration settings to change in sub-account" do
            get_settings_page(sub_account)
            expect(f(sis_syncing)).not_to be_disabled
            expect(f(sis_syncing_locked)).not_to be_disabled
            expect(f(require_assignment_due_date)).not_to be_disabled
            expect(f(assignment_name_length)).not_to be_disabled
            expect(f(default_grade_export)).not_to be_disabled
          end
        end

        context "locked for sub-accounts" do
          before do
            account.settings = { sis_syncing: { value: true, locked: true } }
            account.save
          end

          it "doesn't allow SIS integration settings to change in sub-account" do
            get_settings_page(sub_account)
            expect(f(sis_syncing)).to be_disabled
            expect(f(sis_syncing_locked)).to be_disabled
            expect(f(require_assignment_due_date)).to be_disabled
            expect(f(assignment_name_length)).to be_disabled
            expect(f(default_grade_export)).to be_disabled
          end
        end
      end
    end
  end
end
