class EdFi::Indiana::Sandbox::StudentEducationAssociationService <
  EdFi::Indiana::Sandbox::ApplicationService
  def call
    data = school_year_students
      .includes(student: [:family, :language, :race_students])
      .where('ExitDate = ? OR ExitDate >= ?', '0000-00-00', Date.current)

    data.each { |s| create(s) }
  end

  def endpoint
    'ed-fi/studenteducationorganizationassociations'
  end

  private
    def language_descriptors
      @language_descriptors ||= EdFi::Descriptor
        .by_language_descriptor(school)
        .map { |l| [l.key, l.code] }
        .to_h
    end

    def race_descriptors
      @race_descriptors ||= EdFi::Descriptor
        .by_race_descriptor(school)
        .map { |r| [r.key, r.code] }
        .to_h
    end

    def english_proficiency_descriptors
      @english_proficiency_descriptors ||= EdFi::Descriptor
        .by_descriptor(school, 'limitedEnglishProficiency')
        .pluck(:key, :code)
        .to_h
    end

    def latest_school_year_student(student)
      student.school_year_students.max_by { |s| s&.entry_date || Date.new }
    end

    def props(year)
      student = year.student
      family = student.family
      detail = student.detail
      student_language = student.language
      language_id = student_language&.language_id? ? student_language.language_id : 1
      language = language_descriptors[language_id]
      language_use = student_language&.use || 'Home language'
      english_proficiency_code = english_proficiency_descriptors[detail&.english_proficiency]
      english_proficiency_descriptor = if english_proficiency_code.present?
        "uri://doe.in.gov/LimitedEnglishProficiencyDescriptor##{english_proficiency_code}"
      end
      ell_instrument_descriptor = if detail&.decorate&.edfi_indiana_ell_instrument_used
        split = detail.decorate.edfi_indiana_ell_instrument_used.split('.xml/')
        "uri://doe.in.gov/ELLInstrumentUsedDescriptor##{split[1]}"
      end

      {
        educationOrganizationReference: {
          educationOrganizationId: organization_id.number
        },
        studentReference: {
          studentUniqueId: student.state_number&.number
        },
        addresses: [
          addressTypeDescriptor: 'uri://ed-fi.org/AddressTypeDescriptor#Home',
          streetNumberName: family.address.strip,
          stateAbbreviationDescriptor:
            "uri://ed-fi.org/StateAbbreviationDescriptor##{family.state.strip}",
          city: family.city.strip,
          postalCode: family.zip.strip,
          nameOfCounty: family.county,
          periods: [
            beginDate: latest_school_year_student(student)&.entry_date,
            endDate: latest_school_year_student(student)&.exit_date
          ]
        ],
        hispanicLatinoEthnicity: student.hispanic?,
        languages: [
          {
            languageDescriptor: "uri://doe.in.gov/LanguageDescriptor##{language}",
            uses: [
              {
                languageUseDescriptor: "uri://ed-fi.org/LanguageUseDescriptor##{language_use}"
              }
            ]
          }
        ],
        limitedEnglishProficiencyDescriptor: english_proficiency_descriptor,
        races: student_races(student),
        sexDescriptor: "uri://ed-fi.org/SexDescriptor##{student.decorate.gender_label}",
        _ext: {
          IDOE: {
            ellInstrumentUsedDescriptor: ell_instrument_descriptor,
            usInitialSchoolEntry: detail&.init_school_entry_us&.to_date
          }
        }
      }
    end

    def student_races(student)
      doe_descriptors = ['Hispanic Ethnicity and of any race', 'Multiracial (two or more races)']
      student.race_students.map do |race|
        { raceDescriptor:
          if doe_descriptors.include?(race_descriptors[race.race_id])
            "uri://doe.in.gov/RaceDescriptor##{race_descriptors[race.race_id]}"
          else
            "uri://ed-fi.org/RaceDescriptor##{race_descriptors[race.race_id]}"
          end
        }
      end
    end

    def create(data)
      response = rest_client_request(:post, url, data.student, body: props(data).to_json)
      return unless response

      edfi_id = response.headers[:location].split('/').last
      data.student.update(edfi_id: edfi_id)
    end
end
