package ru.nbch.credit_tracker.config.rest;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
import ru.nbch.credit_tracker.entities.user_response.errors.*;
import ru.nbch.credit_tracker.enums.SignalError;
import ru.nbch.credit_tracker.exceptions.SignalClientException;
import ru.nbch.credit_tracker.exceptions.SignalException;
import ru.nbch.credit_tracker.exceptions.SignalServerException;
import ru.nbch.credit_tracker.utils.error.SimpleMessageResolver;

import java.nio.charset.Charset;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    private final SimpleMessageResolver messageResolver = new SimpleMessageResolver();
    private final String encoding;

    public GlobalExceptionHandler(CreditTrackerSettings settings) {
        this.encoding = settings.getEncoding();
    }

    @ExceptionHandler(value = MaxUploadSizeExceededException.class, produces = MediaType.APPLICATION_XML_VALUE)
    public ResponseEntity<MonitoringError> handleMaxUploadSizeExceeded(MaxUploadSizeExceededException ex) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(new MediaType("application", "xml", Charset.forName(encoding)));

        MonitoringError error = new MonitoringError();
        error.setStatus("error");
        error.setErrorCode(SignalError.ERROR_009.getCode());
        error.setErrorText(SignalError.ERROR_009.getKey());

        return new ResponseEntity<>(error, headers, HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(value = SignalException.class, produces = MediaType.APPLICATION_XML_VALUE)
    public ResponseEntity<CommonError> handleClientException(SignalException ex) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(new MediaType("application", "xml", Charset.forName(encoding)));

        String errorText = messageResolver.resolve(ex.getErrorMessage());

        CommonError commonError = getCommonError(ex);
        commonError.setStatus("error");
        commonError.setErrorCode(ex.getErrorMessage().getSubject().getCode());
        commonError.setErrorText(errorText);

        if (ex instanceof SignalClientException) {
            log.warn("Response error: {}", errorText);
            return new ResponseEntity<>(commonError, headers, HttpStatus.BAD_REQUEST);
        } else {
            Exception cause = ((SignalServerException) ex).getCause();
            log.error(cause.getMessage(), cause);
            return new ResponseEntity<>(commonError, headers, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    private static CommonError getCommonError(SignalException ex) {
        CommonError commonError;
        switch (ex.getErrorFormat()) {
            case MonitoringError -> commonError = new MonitoringError();
            case MonitoringActivePackagesError -> commonError = new MonitoringActivePackagesError();
            case MonitoringDownloadError -> commonError = new MonitoringDownloadError();
            case MonitoringReportListError -> commonError = new MonitoringReportListError();
            case MonitoringPackageDeleteError -> commonError = new MonitoringPackageDeleteError();
            default -> throw new IllegalStateException("Unsupported error format: " + ex.getErrorFormat());
        }
        return commonError;
    }
}
