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.GridRebuildAlreadyRunningException
import org.nstart.dep265.requestservice.service.InvalidGridSettingsException
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 = [GridManagementController::class])
class GridManagementApiExceptionHandler {
    @ExceptionHandler(MethodArgumentNotValidException::class)
    fun handleValidationError(exception: MethodArgumentNotValidException): ResponseEntity<ErrorResponseDto> {
        val details = exception.bindingResult.fieldErrors.map { error ->
            ErrorDetailDto(
                field = error.field,
                message = error.defaultMessage ?: "Некорректное значение",
            )
        }
        return validationError("Ошибка валидации запроса", details)
    }

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

    @ExceptionHandler(InvalidGridSettingsException::class)
    fun handleInvalidGridSettings(exception: InvalidGridSettingsException): ResponseEntity<ErrorResponseDto> {
        return validationError(exception.message ?: "Некорректные настройки сетки")
    }

    @ExceptionHandler(GridRebuildAlreadyRunningException::class)
    fun handleGridRebuildAlreadyRunning(exception: GridRebuildAlreadyRunningException): ResponseEntity<ErrorResponseDto> {
        return ResponseEntity
            .status(HttpStatus.CONFLICT)
            .body(
                ErrorResponseDto(
                    code = "GRID_REBUILD_ALREADY_RUNNING",
                    message = exception.message ?: "Grid rebuild is already running",
                ),
            )
    }

    private fun validationError(
        message: String,
        details: List<ErrorDetailDto>? = null,
    ): ResponseEntity<ErrorResponseDto> {
        return ResponseEntity
            .status(HttpStatus.BAD_REQUEST)
            .body(
                ErrorResponseDto(
                    code = "VALIDATION_ERROR",
                    message = message,
                    details = details,
                ),
            )
    }
}
