package com.zhengmeng.ocrplatform.common;

import com.zhengmeng.ocrplatform.task.TaskNotFoundException;
import com.zhengmeng.ocrplatform.task.TaskAccessDeniedException;
import com.zhengmeng.ocrplatform.task.TaskResultExpiredException;
import com.zhengmeng.ocrplatform.engine.OcrEngineNotFoundException;
import com.zhengmeng.ocrplatform.form.FormTemplateNotFoundException;
import com.zhengmeng.ocrplatform.integration.PluginAuthException;
import com.zhengmeng.ocrplatform.integration.RateLimitExceededException;
import com.zhengmeng.ocrplatform.llm.LlmModelNotFoundException;
import org.springframework.http.HttpStatus;
import org.springframework.orm.ObjectOptimisticLockingFailureException;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.dao.DataIntegrityViolationException;

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(TaskNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ApiResponse<Void> handleTaskNotFound(TaskNotFoundException ex) {
        return ApiResponse.error("TASK_NOT_FOUND", ex.getMessage());
    }

    @ExceptionHandler(TaskAccessDeniedException.class)
    @ResponseStatus(HttpStatus.FORBIDDEN)
    public ApiResponse<Void> handleTaskAccessDenied(TaskAccessDeniedException ex) {
        return ApiResponse.error("TASK_ACCESS_DENIED", ex.getMessage());
    }

    @ExceptionHandler(TaskResultExpiredException.class)
    @ResponseStatus(HttpStatus.GONE)
    public ApiResponse<Void> handleTaskResultExpired(TaskResultExpiredException ex) {
        return ApiResponse.error("TASK_RESULT_EXPIRED", ex.getMessage());
    }

    @ExceptionHandler(FormTemplateNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ApiResponse<Void> handleFormTemplateNotFound(FormTemplateNotFoundException ex) {
        return ApiResponse.error("FORM_TEMPLATE_NOT_FOUND", ex.getMessage());
    }

    @ExceptionHandler(LlmModelNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ApiResponse<Void> handleLlmModelNotFound(LlmModelNotFoundException ex) {
        return ApiResponse.error("LLM_MODEL_NOT_FOUND", ex.getMessage());
    }

    @ExceptionHandler(OcrEngineNotFoundException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ApiResponse<Void> handleEngineNotFound(OcrEngineNotFoundException ex) {
        return ApiResponse.error("OCR_ENGINE_NOT_AVAILABLE", ex.getMessage());
    }

    @ExceptionHandler(PluginAuthException.class)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public ApiResponse<Void> handlePluginAuth(PluginAuthException ex) {
        return ApiResponse.error("PLUGIN_AUTH_FAILED", ex.getMessage());
    }

    @ExceptionHandler(RateLimitExceededException.class)
    @ResponseStatus(HttpStatus.TOO_MANY_REQUESTS)
    public ApiResponse<Void> handleRateLimitExceeded(RateLimitExceededException ex) {
        return ApiResponse.error("RATE_LIMIT_EXCEEDED", ex.getMessage());
    }

    @ExceptionHandler({
            MethodArgumentNotValidException.class,
            MissingServletRequestParameterException.class,
            MissingServletRequestPartException.class
    })
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ApiResponse<Void> handleBadRequest(Exception ex) {
        return ApiResponse.error("BAD_REQUEST", ex.getMessage());
    }

    @ExceptionHandler({
            MethodArgumentTypeMismatchException.class,
            DataIntegrityViolationException.class,
            ObjectOptimisticLockingFailureException.class
    })
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ApiResponse<Void> handleConstraintViolation(Exception ex) {
        return ApiResponse.error("BAD_REQUEST", ex.getMessage());
    }

    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ApiResponse<Void> handleIllegalArgument(IllegalArgumentException ex) {
        return ApiResponse.error("BAD_REQUEST", ex.getMessage());
    }

    @ExceptionHandler(IllegalStateException.class)
    @ResponseStatus(HttpStatus.CONFLICT)
    public ApiResponse<Void> handleIllegalState(IllegalStateException ex) {
        return ApiResponse.error("TASK_STATE_CONFLICT", ex.getMessage());
    }
}
