class EdFi::StateProgram < ApplicationRecord
  audited

  enum program: {
    curricular_material_reimbursement: 0,
    multilingual_learners: 1,
    foreign_exchange: 2,
    school_food_services: 3,
    virtual_education: 4,
    special_education: 5
  }

  belongs_to :student, inverse_of: :ed_fi_state_programs
  belongs_to :school_year, inverse_of: :ed_fi_state_programs

  has_many :siblings, ->(record) { where(program: record.program).where.not(id: record.id) },
    class_name: '::EdFi::StateProgram', foreign_key: :student_id, primary_key: :student_id

  associations_for namespace: 'EdFi' do |a|
    a.has_many :logs, as: :associated, inverse_of: :associated

    a.has_one :id, as: :associated, inverse_of: :associated, dependent: :destroy
  end

  before_save :remove_empty_string, if: :exit_descriptor

  before_destroy :remove_from_ed_fi, if: :ed_fi_id, prepend: true

  validates :program_descriptor, :start_date, presence: true
  validates :exit_descriptor, presence: true, if: :end_date
  validates :disability_descriptor, presence: true, if: :special_education?

  validate :dates_outside_school_year
  validate :end_after_start_date, if: :end_date?

  scope :ordered, -> { order(end_date: :asc, start_date: :asc) }
  scope :by_program, ->(program) { where(program: program) if program }
  scope :by_year, ->(year) { where(school_year: year) if year }

  private
    def dates_outside_school_year
      unless school_year.date_in_range(start_date)
        errors.add(:start_date, 'cannot be outside of the selected school year')
      end

      return if end_date.nil? || school_year.date_in_range(end_date)

      errors.add(:end_date, 'cannot be outside of the selected school year')
    end

    def end_after_start_date
      return if end_date >= start_date

      errors.add(:end_date, 'cannot be before the begin date.')
    end

    def remove_from_ed_fi
      return unless ed_fi_id && school_year.current?

      service = case program
      when 'special_education'
        'EdFi::Indiana::Sandbox::StudentSpecialEducationProgramAssociationsService'
      else
        'EdFi::Indiana::Sandbox::StudentProgramAssociationsService'
      end
      resp = service.constantize.new(
        school_year.id,
        id: ed_fi_id.number,
        program: self
      ).delete
      throw(:abort) unless resp&.code
    end

    def remove_empty_string
      self.exit_descriptor = nil if exit_descriptor.blank?
    end
end
