<commit_before>class AssignmentsController < ApplicationController
  before_action :find_assignment, only: [:destroy, :edit, :update]
  before_action :require_admin_in_roster, only: %i(generate_rotation
                                                   rotation_generator)

  def create
    ass_params = params.require(:assignment)
                       .permit :start_date, :end_date,
                               :user_id, :roster_id
    assignment = Assignment.new ass_params
    unless @current_user.admin_in?(@roster) || taking_ownership?(ass_params)
      require_taking_ownership and return
    end
    if assignment.save
      confirm_change(assignment)
      assignment.notify :owner, of: :create, by: @current_user
      redirect_to roster_assignments_path(@roster, date: assignment.start_date)
    else report_errors(assignment)
    end
  end

  def destroy
    # TODO: should anyone be able to destroy any assignment?
    @assignment.notify :owner, of: :destroy, by: @current_user
    @assignment.destroy
    confirm_change(@assignment)
    redirect_to roster_assignments_path(@roster)
  end

  def edit
    @users = @roster.users.order :last_name
  end

  def generate_rotation
    start_date = Date.parse(params.require :start_date)
    end_date = Date.parse(params.require :end_date)
    user_ids = params.require :user_ids
    start_user = params.require :starting_user_id
    @roster.generate_assignments(user_ids, start_date,
                                 end_date, start_user).each do |assignment|
      assignment.notify :owner, of: :create, by: @current_user
    end
    # TODO: undo
    flash[:message] = 'Rotation has been generated.'
    redirect_to roster_assignments_path(@roster, date: start_date)
  end

  # rubocop:disable Metrics/AbcSize, MethodLength

  def index
    @month_date = if params[:date].present?
                    Date.parse params[:date]
                  else Date.today
                  end.beginning_of_month
    start_date = @month_date.beginning_of_week(:sunday)
    end_date = @month_date.end_of_month.end_of_week(:sunday)
    @weeks = (start_date..end_date).each_slice(7)
    @assignments = @current_user.assignments.in(@roster)
                                .upcoming
                                .order :start_date
    @current_assignment = @roster.assignments.current
    @switchover_hour = CONFIG[:switchover_hour]
    @fallback_user = @roster.fallback_user
  end

  # rubocop:enable Metrics/AbcSize, MethodLength

  def new
    @start_date = Date.parse(params.require :date)
    @end_date = @start_date + 6.days
    @users = @roster.users.order :last_name
  end

  def rotation_generator
    @users = User.order :last_name
    @start_date = Assignment.next_rotation_start_date
  end

  def update
    ass_params = params.require(:assignment)
                       .permit :start_date, :end_date, :user_id
    unless @current_user.admin_in?(@roster) || taking_ownership?(ass_params)
      require_taking_ownership and return
    end
    previous_owner = @assignment.user
    if @assignment.update ass_params
      confirm_change(@assignment)
      if @assignment.user == previous_owner
        @assignment.notify :owner, of: :update, by: @current_user
      else
        @assignment.notify :owner, of: :create, by: @current_user
        @assignment.notify previous_owner, of: :destroy, by: @current_user
      end
      redirect_to roster_assignments_path(@roster, date: @assignment.start_date)
    else report_errors(@assignment)
    end
  end

  private

  def find_assignment
    @assignment = Assignment.includes(:user).find(params.require :id)
  end

  def require_taking_ownership
    flash[:errors] = [<<-TEXT]
      You may only edit or create assignments such that you become on call.<commit_msg>[ci skip] A helpful comment<commit_after>class AssignmentsController < ApplicationController
  before_action :find_assignment, only: [:destroy, :edit, :update]
  before_action :require_admin_in_roster, only: %i(generate_rotation
                                                   rotation_generator)

  def create
    ass_params = params.require(:assignment)
                       .permit :start_date, :end_date,
                               :user_id, :roster_id
    assignment = Assignment.new ass_params
    unless @current_user.admin_in?(@roster) || taking_ownership?(ass_params)
      require_taking_ownership and return
    end
    if assignment.save
      confirm_change(assignment)
      assignment.notify :owner, of: :create, by: @current_user
      redirect_to roster_assignments_path(@roster, date: assignment.start_date)
    else report_errors(assignment)
    end
  end

  def destroy
    # TODO: should anyone be able to destroy any assignment?
    @assignment.notify :owner, of: :destroy, by: @current_user
    @assignment.destroy
    confirm_change(@assignment)
    redirect_to roster_assignments_path(@roster)
  end

  def edit
    @users = @roster.users.order :last_name
  end

  def generate_rotation
    start_date = Date.parse(params.require :start_date)
    end_date = Date.parse(params.require :end_date)
    user_ids = params.require :user_ids
    start_user = params.require :starting_user_id
    @roster.generate_assignments(user_ids, start_date,
                                 end_date, start_user).each do |assignment|
      assignment.notify :owner, of: :create, by: @current_user
    end
    # TODO: undo
    flash[:message] = 'Rotation has been generated.'
    redirect_to roster_assignments_path(@roster, date: start_date)
  end

  # rubocop:disable Metrics/AbcSize, MethodLength

  def index
    @month_date = if params[:date].present?
                    Date.parse params[:date]
                  else Date.today
                  end.beginning_of_month
    start_date = @month_date.beginning_of_week(:sunday)
    end_date = @month_date.end_of_month.end_of_week(:sunday)
    @weeks = (start_date..end_date).each_slice(7)
    @assignments = @current_user.assignments.in(@roster)
                                .upcoming
                                .order :start_date
    @current_assignment = @roster.assignments.current
    @switchover_hour = CONFIG[:switchover_hour]
    @fallback_user = @roster.fallback_user
  end

  # rubocop:enable Metrics/AbcSize, MethodLength

  def new
    @start_date = Date.parse(params.require :date)
    @end_date = @start_date + 6.days
    @users = @roster.users.order :last_name
  end

  def rotation_generator
    @users = User.order :last_name
    @start_date = Assignment.next_rotation_start_date
  end

  def update
    ass_params = params.require(:assignment)
                       .permit :start_date, :end_date, :user_id
    unless @current_user.admin_in?(@roster) || taking_ownership?(ass_params)
      require_taking_ownership and return
    end
    previous_owner = @assignment.user
    if @assignment.update ass_params
      confirm_change(@assignment)
      # If the user's being changed, we effectively inform of the change
      # by telling the previous owner they're not responsible anymore,
      # and telling the new owner that they're newly responsible now.
      if @assignment.user == previous_owner
        @assignment.notify :owner, of: :update, by: @current_user
      else
        @assignment.notify :owner, of: :create, by: @current_user
        @assignment.notify previous_owner, of: :destroy, by: @current_user
      end
      redirect_to roster_assignments_path(@roster, date: @assignment.start_date)
    else report_errors(@assignment)
    end
  end

  private

  def find_assignment
    @assignment = Assignment.includes(:user).find(params.require :id)
  end

  def require_taking_ownership
    flash[:errors] = [<<-TEXT]
      You may only edit or create assignments such that you become on call.
{'fraction_non_alphanumeric': 0.08496143958868894, 'fraction_numerical': 0.0005141388174807198, 'mean_word_length': 2.951752158456069, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '920088', 'n_tokens_mistral': 2368, 'n_tokens_neox': 2305, 'n_words': 527}