package kz.konturai.parser.controller;

import kz.konturai.parser.exception.ClaudeApiException;
import kz.konturai.parser.exception.TargetingCampaignNotFoundException;
import kz.konturai.parser.exception.ValidationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.web.servlet.resource.NoResourceFoundException;

@RestControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(ValidationException.class)
    public ResponseEntity<Map<String, Object>> handleValidationException(ValidationException e) {
        logger.warn("Ошибка валидации: field={}, value={}, message={}", e.getField(), e.getValue(), e.getMessage());
        Map<String, Object> body = new LinkedHashMap<>();
        body.put("error", "VALIDATION_ERROR");
        body.put("message", e.getMessage());
        if (e.getField() != null) {
            body.put("field", e.getField());
            body.put("value", e.getValue());
        }
        return ResponseEntity.badRequest().body(body);
    }

    @ExceptionHandler(ClaudeApiException.class)
    public ResponseEntity<Map<String, Object>> handleClaudeApi(ClaudeApiException e) {
        logger.error("Ошибка Claude API: {}", e.getMessage());
        return ResponseEntity.status(502).body(errorBody("CLAUDE_API_ERROR",
                "Ошибка AI-сервиса: " + e.getMessage()));
    }

    @ExceptionHandler(TargetingCampaignNotFoundException.class)
    public ResponseEntity<Map<String, Object>> handleNotFound(TargetingCampaignNotFoundException e) {
        logger.warn("Кампания не найдена: {}", e.getMessage());
        return ResponseEntity.status(404).body(errorBody("NOT_FOUND", e.getMessage()));
    }

    @ExceptionHandler(IllegalStateException.class)
    public ResponseEntity<Map<String, Object>> handleIllegalState(IllegalStateException e) {
        logger.error("Ошибка обработки AI: {}", e.getMessage());
        return ResponseEntity.status(500).body(errorBody("AI_PROCESSING_ERROR", e.getMessage()));
    }

    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<Map<String, Object>> handleIllegalArgument(IllegalArgumentException e) {
        logger.warn("Некорректный аргумент: {}", e.getMessage());
        return ResponseEntity.badRequest().body(errorBody("INVALID_ARGUMENT", e.getMessage()));
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, Object>> handleValidation(MethodArgumentNotValidException e) {
        Map<String, String> fieldErrors = e.getBindingResult().getFieldErrors()
                .stream()
                .collect(Collectors.toMap(
                        FieldError::getField,
                        fe -> fe.getDefaultMessage() != null ? fe.getDefaultMessage() : "Некорректное значение",
                        (existing, duplicate) -> existing
                ));
        Map<String, Object> body = new LinkedHashMap<>();
        body.put("error", "VALIDATION_ERROR");
        body.put("message", "Ошибка валидации запроса");
        body.put("fields", fieldErrors);
        return ResponseEntity.badRequest().body(body);
    }

    @ExceptionHandler(NoResourceFoundException.class)
    public ResponseEntity<Map<String, Object>> handleNoResourceFound(NoResourceFoundException e) {
        logger.warn("Ресурс не найден: {}", e.getResourcePath());
        return ResponseEntity.status(404).body(errorBody("NOT_FOUND", "Ресурс не найден"));
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<Map<String, Object>> handleGeneral(Exception e) {
        logger.error("Неожиданная ошибка", e);
        return ResponseEntity.status(500).body(errorBody("INTERNAL_ERROR",
                "Внутренняя ошибка сервера. Обратитесь в поддержку."));
    }

    private Map<String, Object> errorBody(String code, String message) {
        Map<String, Object> body = new LinkedHashMap<>();
        body.put("error", code);
        body.put("message", message);
        return body;
    }
}
