package org.nstart.dep265.requestservice.controller

import org.nstart.dep265.requestservice.dto.ErrorDetailDto
import org.nstart.dep265.requestservice.dto.ErrorResponseDto
import org.nstart.dep265.requestservice.service.InvalidRequestListSortException
import org.nstart.dep265.requestservice.service.RequestAlreadyExistsException
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.http.converter.HttpMessageNotReadableException
import org.springframework.web.bind.MethodArgumentNotValidException
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.bind.annotation.RestControllerAdvice

@RestControllerAdvice(assignableTypes = [RequestController::class])
class RequestApiExceptionHandler {
    @ExceptionHandler(MethodArgumentNotValidException::class)
    fun handleValidationError(exception: MethodArgumentNotValidException): ResponseEntity<ErrorResponseDto> {
        val details = exception.bindingResult.fieldErrors.map { error ->
            ErrorDetailDto(
                field = error.field,
                message = error.defaultMessage ?: "Некорректное значение",
            )
        }
        return ResponseEntity
            .status(HttpStatus.BAD_REQUEST)
            .body(
                ErrorResponseDto(
                    code = "VALIDATION_ERROR",
                    message = "Ошибка валидации запроса",
                    details = details,
                ),
            )
    }

    @ExceptionHandler(HttpMessageNotReadableException::class)
    fun handleNotReadable(exception: HttpMessageNotReadableException): ResponseEntity<ErrorResponseDto> {
        return ResponseEntity
            .status(HttpStatus.BAD_REQUEST)
            .body(
                ErrorResponseDto(
                    code = "VALIDATION_ERROR",
                    message = exception.mostSpecificCause.message ?: "Некорректный JSON-запрос",
                ),
            )
    }

    @ExceptionHandler(RequestAlreadyExistsException::class)
    fun handleRequestAlreadyExists(exception: RequestAlreadyExistsException): ResponseEntity<ErrorResponseDto> {
        return ResponseEntity
            .status(HttpStatus.CONFLICT)
            .body(
                ErrorResponseDto(
                    code = "REQUEST_ALREADY_EXISTS",
                    message = "Заявка с таким id уже существует",
                ),
            )
    }

    @ExceptionHandler(InvalidRequestListSortException::class)
    fun handleInvalidRequestListSort(exception: InvalidRequestListSortException): ResponseEntity<ErrorResponseDto> {
        return ResponseEntity
            .status(HttpStatus.BAD_REQUEST)
            .body(
                ErrorResponseDto(
                    code = "VALIDATION_ERROR",
                    message = exception.message ?: "Некорректный параметр sort",
                ),
            )
    }
}
