class Admission::Applicants::AdditionalFieldService < ApplicationService
  def initialize(applicant, application)
    @applicant = applicant
    @application = application
  end

  def props
    additional_groups.map do |group|
      {
        id: group.id,
        name: group.name,
        order: group.order,
        description: group.description,
        fields: fields_by_group[group.id]&.map do |field|
          {
            id: field.id,
            name: field.name,
            type: field.type,
            description: field.description,
            choices: field.choices,
            value: find_or_build_additional_value(field.id).value,
            required: application_additional_field_status[field.id]
          }
        end
      }
    end
  end

  def available?
    @application.additional_fields.by_display.exists?
  end

  def fields_present?
    @application.school.student_additional_fields.by_admission.exists?
  end

  private
    def additional_groups
      query = @application.school.student_additional_groups
        .with_admission_application_fields(@application.id)
        .distinct

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

    def fields_by_group
      @fields_by_group ||= @application.school.student_additional_fields
        .joins_application_fields(@application.id)
        .by_admission
        .ordered
        .group_by(&:group_id)
    end

    def additional_values_by_field
      @additional_values_by_field ||= @applicant.additional_values
        .index_by(&:student_additional_field_id)
    end

    def find_or_build_additional_value(field_id)
      additional_values_by_field[field_id] ||
        @applicant.additional_values.build(student_additional_field_id: field_id)
    end

    def application_additional_field_status
      @application_additional_field_status ||= @application.additional_fields
        .pluck(:student_additional_field_id, :required)
        .to_h
    end
end
