package dp.kotul.solrapiapplication.service

import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper
import feign.Response
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.stereotype.Service

interface ApiResponseService {
    fun getSelectResponseEntity(solrResponse: Response): ResponseEntity<JsonNode?>
    fun getUpdateResponseEntity(solrResponse: Response): ResponseEntity<JsonNode?>
}

@Service
class ApiResponseServiceImpl(val mapper: ObjectMapper) : ApiResponseService {

    override fun getSelectResponseEntity(solrResponse: Response): ResponseEntity<JsonNode?> {
        return getResponseEntity(solrResponse, listOf("response", "docs"))
    }

    override fun getUpdateResponseEntity(solrResponse: Response): ResponseEntity<JsonNode?> {
        return getResponseEntity(solrResponse)
    }

    private fun getResponseEntity(response: Response, pathToField: List<String> = listOf()): ResponseEntity<JsonNode?> {
        if (HttpStatus.valueOf(response.status()) != HttpStatus.OK) {
            return getError(response)
        }

        if (pathToField.isEmpty()) {
            return ResponseEntity(HttpStatus.valueOf(response.status()))
        }

        return getDocuments(response, pathToField)
    }

    private fun getDocuments(response: Response, path: List<String>): ResponseEntity<JsonNode?> {
        val responseBody = getResponseBody(response)

        val documents = getToThePath(responseBody, path)

        val responseJson = mapper.createObjectNode()

        val responseHeader: JsonNode? = responseBody?.get("responseHeader")
        responseHeader?.let { responseJson.putPOJO("responseHeader", it) }

        val responseCount: JsonNode? = responseBody?.get("response")?.get("numFound")
        responseCount?.let { responseJson.putPOJO("numFound", it) }

        responseJson.putPOJO("documents", documents)

        return ResponseEntity(responseJson, HttpStatus.valueOf(response.status()))
    }

    private fun getError(response: Response): ResponseEntity<JsonNode?> {
        val responseBody = getToThePath(getResponseBody(response), listOf("error", "msg"))
        return ResponseEntity(mapper.createObjectNode().putPOJO("error", responseBody), HttpStatus.valueOf(response.status()))
    }

    private fun getResponseBody(response: Response): JsonNode? {
        return mapper.readTree(response.body().asInputStream())
    }

    private fun getToThePath(json: JsonNode?, path: List<String>): JsonNode? {
        var tempJson = json
        path.forEach {
            tempJson = tempJson?.get(it)
        }
        return tempJson
    }
}
