class Ecs::SaveGraduationRequirementeService < ApplicationService
  include AcceptsNestedAttributesHelper

  attr_reader :ec_year, :graduation_requirement, :params

  def initialize(graduation_requirement, params)
    @graduation_requirement = graduation_requirement
    @ec_year = graduation_requirement.ec_year
    @params  = params
  end

  def call
    set_graduation_subitems_position!

    graduation_requirement.position = params[:position].presence || ec_year.ec_graduation_requirements.count + 1
    graduation_requirement.content = params[:content].to_s.strip

    attributes = build_accepts_nested_attributes(
      graduation_requirement,
      graduation_requirement.ec_graduation_subitems,
      params[:graduation_subitems],
      &method(:graduation_subitem_params_handler!)
    )

    ActiveRecord::Base.transaction do
      graduation_requirement.assign_attributes(ec_graduation_subitems_attributes: attributes)

      resort_graduation_requirements_position!

      graduation_requirement.save!
    end

    graduation_requirement
  end

  private

  def set_graduation_subitems_position!
    params[:graduation_subitems].each_with_index do |item, index|
      item[:position] = index + 1
    end
  end

  def resort_graduation_requirements_position!
    # 新增时
    if graduation_requirement.new_record?
      # 插入数据时只需要后移
      ec_year.ec_graduation_requirements.where('position >= ?', graduation_requirement.position)
        .update_all('position = position + 1')
      return
    end

    # 编辑时
    new_position = graduation_requirement.position
    old_position = graduation_requirement.position_in_database

    if new_position > old_position # 前移
      ec_year.ec_graduation_requirements.where('position <= ? AND position > ?', new_position, old_position)
        .update_all('position = position - 1')
    elsif new_position < old_position # 后移
      ec_year.ec_graduation_requirements.where('position >= ? AND position < ?', new_position, old_position)
        .update_all('position = position + 1')
    end
  end

  def graduation_subitem_params_handler!(subitem)
    subitem[:content] = subitem[:content].to_s.strip
  end
end