package com.rera.mss.exceptions

import org.springframework.http.ResponseEntity
import org.springframework.security.authentication.BadCredentialsException
import org.springframework.web.bind.annotation.ControllerAdvice
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler

@ControllerAdvice
class RestResponseEntityExceptionHandler : ResponseEntityExceptionHandler() {
    @ExceptionHandler(value = [Exception::class])
    fun handleGeneralException(ex: Exception): ResponseEntity<ErrorDto> {
        logger.error(ex.message, ex)
        return ErrorDtoResponseEntityBuilder(ExceptionType.Unexpected)
                .withMessage("Internal server error")
                .buildResponseEntity()
    }

    @ExceptionHandler(value = [MonitoredAreaWithoutPvAreaException::class])
    fun handleMonitoredAreaWithoutPvAreaException(ex: MonitoredAreaWithoutPvAreaException): ResponseEntity<ErrorDto> {
        logger.error(ex.message, ex)
        return ErrorDtoResponseEntityBuilder(ExceptionType.MonitoredAreaWithoutPvAreaException)
                .withMessage(ex.message)
                .withDetail(ex.monitoredAreaId)
                .buildResponseEntity()
    }

    @ExceptionHandler(value = [PvAreaWithoutPvPanelException::class])
    fun handlePvAreaWithoutPvPanelException(ex: PvAreaWithoutPvPanelException): ResponseEntity<ErrorDto> {
        logger.error(ex.message, ex)
        return ErrorDtoResponseEntityBuilder(ExceptionType.PvAreaWithoutPvPanelException)
                .withMessage(ex.message)
                .withDetail("monitored area #${ex.monitoredAreaId} and corresponding Pv area #${ex.pvAreaId}")
                .buildResponseEntity()
    }

    @ExceptionHandler(value = [PvAreaWithZeroAreaException::class])
    fun handlePvAreaWithZeroAreaException(ex: PvAreaWithZeroAreaException): ResponseEntity<ErrorDto> {
        logger.error(ex.message, ex)
        return ErrorDtoResponseEntityBuilder(ExceptionType.PvAreaWithZeroAreaException)
                .withMessage(ex.message)
                .withDetail("monitored area #${ex.monitoredAreaId} and corresponding Pv area #${ex.pvAreaId}")
                .buildResponseEntity()
    }

    @ExceptionHandler(value = [BadCredentialsException::class])
    fun handleBadCredentialsException(ex: BadCredentialsException): ResponseEntity<ErrorDto> {
        logger.error(ex.message, ex)
        return ErrorDtoResponseEntityBuilder(ExceptionType.BadCredentialsException)
                .withMessage("Login failed. Wrong username or password.")
                .buildResponseEntity()
    }

    @ExceptionHandler(value = [NoInstrumentWithGivenIdException::class])
    fun handleNoInstrumentWithGivenIdException(ex: NoInstrumentWithGivenIdException): ResponseEntity<ErrorDto> {
        logger.error(ex.message, ex)
        return ErrorDtoResponseEntityBuilder(ExceptionType.NoInstrumentWithGivenIdException)
                .withMessage(ex.message)
                .buildResponseEntity()
    }

    @ExceptionHandler(value = [WrongMeasurementFormatException::class])
    fun handleWrongMeasurementFormatException(ex: WrongMeasurementFormatException): ResponseEntity<ErrorDto> {
        logger.error(ex.message, ex)
        return ErrorDtoResponseEntityBuilder(ExceptionType.WrongMeasurementFormatException)
                .withMessage(ex.message)
                .buildResponseEntity()
    }
}