class Admin::Admissions::Applicants::Student::AdditionalValuesController <
  Admin::Admissions::Controller
  include Admin::Admissions::ApplicantScoped

  def index
    render_success :ok, json: groups.map { |group| group_props(group) }
  end

  def update
    objects = []
    fields_by_id = current_school.student_additional_fields.where(admissions: 1).index_by(&:id)
    params[:additional_values].each do |param|
      additional_value = student.student_additional_values
        .find_or_initialize_by(student_additional_field_id: param[:field_id])

      if fields_by_id[param[:field_id]].date?
        additional_value.value_date = param[:value] || ''
      else
        additional_value.value = param[:value] || ''
      end

      objects << additional_value
    end

    if transactional_save(objects)
      render_success :ok, object: 'Additional values'
    else
      render_error :unprocessable_entity, errors: multi_errors(objects)
    end
  end

  def fields
    render_success :ok, json: additional_fields.map { |f| field_props(f) }
  end

  private
    def student
      @student ||= applicant.student
    end

    def additional_fields
      current_school.student_additional_fields
        .by_admission
        .joins_application_fields(applicant.application_id, display?)
    end

    def group_fields
      @group_fields ||= additional_fields.ordered.group_by(&:group_id)
    end

    def groups
      query = current_school.student_additional_groups
        .by_admissions(true)
        .with_admission_application_fields(applicant.application_id, display?)
        .ordered
        .distinct

      group_fields.key?(0) ? query.with_default_group : query
    end

    def additional_values
      @additional_values ||= student.student_additional_values
        .index_by(&:student_additional_field_id)
    end

    def display?
      params.key?(:display) ? params[:display].to_bool : true
    end

    def group_props(group)
      {}.tap do |prop|
        prop[:id] = group.id
        prop[:name] = group.name
        prop[:order] = group.order
        prop[:description] = group.description
        prop[:fields] = (group_fields[group.id] || []).map { |f| field_props(f) }
      end
    end

    def field_props(field)
      {}.tap do |props|
        props[:id] = field.id
        props[:name] = field.name
        props[:type] = field.type
        props[:description] = field.description
        props[:choices] = field.choices
        additional_value = additional_values[field.id]
        props[:value] = field.date? ? additional_value&.value_date : additional_value&.value
      end
    end
end
