class Csv::Admissions::Applicants::Service < Csv::ApplicationService
  def initialize(school, options)
    @school = school
    @school_year_id = options['school_year_id']
    @application_id = options['application_id']
    @grade = options['grades']
    @system_status = options['status']
    @returning = options['student_type']
    @enrollment = options['enrollment']
    @review = options['review']
    @tags = options['tags']
  end

  def call
    CSV.generate do |csv|
      csv << headers
      applicants.each do |applicant|
        csv << content(applicant)
      end
    end
  end

  private
    def school_year
      @school.school_years.find(@school_year_id)
    end

    def associations
      [:family, :status, :tags]
    end

    def applicants
      @applicants ||= school_year.admission_applicants
        .includes(associations)
        .where(admission_applications: { enrollment: @enrollment })
        .with_application(@application_id)
        .with_grade(@grade)
        .with_system_status(@system_status)
        .with_returning(@returning)
        .by_review(@review)
        .with_tags(@tags)
        .ordered
        .decorate
        .to_a
    end

    def family_tags
      @family_tags ||= school_year.admission_families.includes(:tags).index_by(&:family_id)
    end

    def grade_levels
      @grade_levels ||= @school.grades_hash
    end

    def headers
      [
        'Student Code',
        'Student ID',
        'Student First Name',
        'Student Last Name',
        'DOB',
        'Gender',
        'Application Grade Code',
        'Application Grade Label',
        'Application Name',
        'Created Date',
        'Submitted Date',
        'Family Code',
        'Family Name',
        'Status',
        'Applicant Tags',
        'Family Tags'
      ]
    end

    def content(applicant)
      [
        applicant.student&.code,
        applicant.student&.id,
        applicant.reviewed_prop(:first_name),
        applicant.reviewed_prop(:last_name),
        applicant.reviewed_prop(:birth_date),
        applicant.reviewed_prop(:gender_label),
        applicant.grade,
        grade_levels[applicant.grade],
        applicant.application.name,
        applicant.created_date,
        applicant.submission_date,
        applicant.family.code,
        applicant.family.name,
        applicant.system_status,
        applicant.tags.map(&:name).join(', '),
        family_tags[applicant.family_id]&.tags&.map(&:name)&.join(', ')
      ]
    end
end
