class EdFi::Indiana::Sandbox::CourseSectionStaffService < EdFi::Indiana::Sandbox::ApplicationService
  def call
    ed_fi_classes.each { |c| props(c) }
    class_subjects.each { |c| props(c) }
  end

  def endpoint
    'ed-fi/staffsectionassociations'
  end

  private
    def ed_fi_classes
      school.classrooms
        .preload(:class_periods, :employees)
        .joins(:school_state_classroom)
        .by_type([:period_long])
        .where.not(course_number: ['', ' '])
    end

    def class_subjects
      school.class_subjects
        .preload(classroom: [:class_periods, :employees])
        .joins(classroom: :school_state_classroom)
        .merge(Classroom.by_type([:day_long, :preschool]))
        .where.not(code: ['', ' '])
    end

    def periods
      @periods ||= school.periods.index_by(&:id)
    end

    def begin_and_end_days_by_semester
      @begin_and_end_days_by_semester ||= school_year.begin_and_end_days_by_semester
    end

    def position_descriptors
      @position_descriptors ||= descriptor_service(:classroompositiondescriptors)
        .map { |d| [d['id'], d['codeValue']] }
        .to_h
    end

    def position_descriptor(descriptor_id)
      descriptor = position_descriptors[descriptor_id]
      "uri://doe.in.gov/ClassroomPositionDescriptor##{descriptor}"
    end

    def terms
      @terms ||= if school.school_config.semesters?
        { 1 => 'Fall Semester', 2 => 'Spring Semester', year_round: 'Year Round' }
      else
        {
          1 => 'First Trimester',
          2 => 'Second Trimester',
          3 => 'Third Trimester',
          year_round: 'Year Round'
        }
      end
    end

    # Classroom is Year Round if it is not credit bearing and
    # is either a preschool or day long classroom.
    def year_round_classroom?(classroom)
      return false if classroom.credit.positive?

      ['preschool', 'day_long'].include?(classroom.type)
    end

    def props(object)
      if object.is_a?(Classroom)
        classroom = object
        code = object.course_number
      else
        classroom = object.classroom
        code = object.code
      end

      period_id = classroom.class_periods.min_by(&:day)&.period_id
      period = classroom.preschool? ? periods.values.first : periods[period_id]
      employee = classroom.primary_teacher

      terms.each_key do |semester|
        # Send record once for year round classrooms
        next if year_round_classroom?(classroom) && semester != :year_round
        # Skip year_round semester when classroom is not year round
        next if semester == :year_round && !year_round_classroom?(classroom)

        full_year_or_year_round = semester == :year_round || classroom.semester == :full_year
        next unless full_year_or_year_round || classroom.semester == semester

        if semester == :year_round
          # Grab first and last day of entire school year
          begin_dates = begin_and_end_days_by_semester[school_config.semesters.keys.first]
          end_dates = begin_and_end_days_by_semester[school_config.semesters.keys.last]
        else
          begin_dates = begin_and_end_days_by_semester[semester]
          end_dates = begin_and_end_days_by_semester[semester]
        end

        data = {
          sectionReference: {
            schoolId: state_id.number,
            localCourseCode: code,
            sessionName: "#{school_year.academic_year} #{terms[semester]}",
            schoolYear: school_year.academic_year,
            sectionIdentifier: classroom.period_long? ? classroom.id : object.id
          },
          staffReference: {
            staffUniqueId: employee&.state_id&.number
          },
          beginDate: begin_dates[:begin].date.strftime('%Y-%m-%d'),
          endDate: end_dates[:end].date.strftime('%Y-%m-%d'),
          classroomPositionDescriptor: position_descriptor(classroom.classroom_position_type_id)
        }

        rest_client_request(:post, url, employee, body: data.to_json)
      end
    end
end
