class Csv::EdFi::Indiana::StaffService < Csv::ApplicationService
  include EdFi::IndianaHelper

  def initialize(school_id)
    @school_id = school_id
  end

  def call
    CSV.generate do |csv|
      csv << headers
      unsyncing_employees = []
      string = 'Employees with open positions NOT mapped to a State Staff Classification.'\
        ' These Employees will not sync.'
      employees.decorate.each do |employee|
        employee_positions_in_range[employee.id].each do |position|
          if position.position.edfi_id.blank?
            unsyncing_employees << employee if position.exit_date.nil?
            next
          end
          csv << content(employee, position)
        end
      end
      if unsyncing_employees.present?
        csv << []
        csv << []
        csv << [string]
        unsyncing_employees.each do |employee|
          employee_positions_in_range[employee.id].each do |position|
            next if position.position.edfi_id.present?

            csv << content(employee, position)
          end
        end
      end
    end
  end

  private
    def school
      @school ||= School.find(@school_id)
    end

    def school_year
      school.school_years.current
    end

    def employees
      school.employees
        .preload(:state_id, :detail, :race, :oldest_position)
        .joins(:positions, :state_id)
        .position_within_date_range(semester_range)
        .distinct
    end

    def employee_positions_in_range
      @employee_positions_in_range ||= school.employee_positions
        .within_date_range(semester_range)
        .decorate
        .group_by(&:employee_id)
    end

    def semester_range
      semester = school.school_config.trimesters? ? 2 : school_year.current_semester
      school_year.semester_date_range(semester)
    end

    def employment_descriptors
      descriptor_service(
        school_year.id,
        descriptor: :employmentStatusDescriptors
      )
    end

    def state_staff_descriptors
      @state_staff_descriptors ||= descriptor_service(
        school_year.id,
        descriptor: :staffClassificationDescriptors
      )
        .map { |d| [d['id'], d['description']] }
        .to_h
    end

    def employment_statuses
      @employment_statuses ||= employment_descriptors.map { |d| [d['id'], d['description']] }.to_h
    end

    def headers
      [
        'Staff State ID',
        'First Name',
        'Last Name',
        'DOB',
        'Gender',
        'Ethnicity',
        'Years-Prior Professional Experience',
        'Last 4 SSN',
        'Race',
        'Email',
        'Employment Status',
        'Hire Date',
        'School Position',
        'Full Time',
        'Staff Classification',
        'Start Date',
        'End Date'
      ]
    end

    def content(employee, position)
      oldest_position = employee.oldest_position.decorate
      staff_descriptor = position.position.edfi_id

      [
        employee&.state_id&.number,
        employee.first_name,
        employee.last_name,
        employee.birth_date,
        employee.gender_label,
        employee.ethnicity == 'unspecified' ? nil : employee.ethnicity,
        employee.service_years,
        employee.social_security_number_number,
        employee.race_name,
        employee.email,
        employment_statuses[position.employment_descriptor],
        oldest_position.hire_date,
        position.position.name,
        employee.detail&.ncea_status&.titleize || 'No Status',
        staff_descriptor ? state_staff_descriptors[staff_descriptor] : nil,
        position.hire_date,
        position.exit_date
      ]
    end
end
