class EdFi::Indiana::V2026::IdentityService < EdFi::Indiana::V2026::ApplicationService
  def search
    response = rest_client_request(:post, "#{url}/search", body: student_props.to_json)
    response[:success] ? response[:body] : []
  end

  def find(id)
    response = rest_client_request(:get, "#{url}/#{id}")
    response[:success] ? response[:body] : {}
  end

  def create
    return if missing_information.any?

    path = "#{url}/create"
    response = rest_client_request(:post, path, body: student_props(__method__).to_json)
    return response unless response[:success]

    # Create state number when 200 response otherwise create identity (202 response)
    response[:data] = if response[:http_code] == 200
      state_number = student.find_or_build_state_number
      state_number.update(number: response[:body]['studentTestNumber'])
      state_number
    else
      update_identity(response[:body])
      identity
    end
    response
  end

  def processing_status
    return {} if identity.request_id.blank?

    response = rest_client_request(:get, "#{url}/create/#{identity.request_id}")
    update_identity(response[:body])
    identity
  end

  def missing_information
    [].tap do |props|
      fields  = [:last_name, :first_name, :gender, :date_of_birth]
      fields.each { |f| props << f if student.send(f).blank? }
      props << :race if student.races.empty?
      props << :language_code if student.language.blank? || student.language_id == 0
    end
  end

  private
    def api_url
      "#{base_url}/#{school_year.academic_year}/IDOEIdentity/v2/idoe"
    end

    def endpoint
      :student
    end

    def student
      @student ||= @params[:student]
    end

    def identity
      @identity ||= student.find_or_build_ed_fi_identity
    end

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

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

    def update_identity(data)
      identity.school_year = school_year
      identity.request_id = data['requestId']
      identity.status = data['requestStatus'].downcase
      identity.processed_at = data['dateProcessed']
      identity.state_id = data['studentTestNumber']
      identity.save
    end

    def student_props(method_name=:search)
      {}.tap do |props|
        props[:lastSurname] = student.last_name
        props[:firstName] = student.first_name
        return props unless method_name == :create

        props[:middleName] = student.middle_name
        props[:birthDate] = student.date_of_birth
        props[:nameSuffix] = student.suffix
        props[:sex] = student.decorate.gender_label

        # Grab the first race from the student, since Indiana only accepts 1
        race_id = student.race_ids.first
        props[:race] = race_descriptors[race_id]

        language_id = student.find_or_build_language.language_id
        props[:languageCode] = language_descriptors[language_id]
      end
    end

    # TODO: Move this to the ApplicationService and update the other services
    def rest_client_request(method, path, body: {})
      response = RestClient::Request.execute(
        method: method,
        url: path,
        headers: headers,
        payload: body
      )
      http_code = response.code
      response = JSON.parse(response.body)

      { success: true, body: response, http_code: http_code }
    rescue RestClient::Exception => e
      { success: false, error: e.response&.body, http_code: e.http_code }
    end
end
