package ru.soune.no_copy.controller; import jakarta.annotation.PostConstruct; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.ApplicationContext; import org.springframework.http.ResponseEntity; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import org.springframework.web.bind.annotation.*; import ru.soune.no_copy.dto.BaseRequest; import ru.soune.no_copy.dto.BaseResponse; import ru.soune.no_copy.dto.MessageCode; import ru.soune.no_copy.dto.RegAnswer; import ru.soune.no_copy.exception.NotValidFieldException; import ru.soune.no_copy.exception.ValidationException; import ru.soune.no_copy.handler.LoginRequestHandler; import ru.soune.no_copy.handler.RegRequestHandler; import ru.soune.no_copy.handler.RequestHandler; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @Slf4j @RestController @RequestMapping("/api") @RequiredArgsConstructor public class ApiController { private final ApplicationContext applicationContext; private Map handlers = new HashMap<>(); @PostConstruct public void init() { RegRequestHandler regHandler = applicationContext.getBean(RegRequestHandler.class); LoginRequestHandler loginHandler = applicationContext.getBean(LoginRequestHandler.class); handlers.put(20002, regHandler); handlers.put(20001, loginHandler); } @PostMapping("/v{version}/data") public ResponseEntity handlePostRequest(@RequestBody BaseRequest request, @PathVariable("version") int version) { Integer msgId = request.getMsgId(); BaseResponse response; try { RequestHandler handler = handlers.get(msgId); if (handler == null) { response = new BaseResponse(msgId, MessageCode.MSG_ID_NOT_FOUND.getCode(), MessageCode.MSG_ID_NOT_FOUND.getDescription(), new HashMap<>()); } else { response = handler.handle(request); } return ResponseEntity.ok().body(response); } catch (ValidationException e) { return createValidationErrorResponse(e.getBindingResult(), e.getMsgId()); } catch (NotValidFieldException e) { throw e; } catch (Exception e) { log.error("Handler execution failed for msgId: {}", msgId, e); throw new RuntimeException("Handler execution failed", e); } } private ResponseEntity createValidationErrorResponse(BindingResult bindingResult, Integer msgId) { List> fieldErrors = bindingResult.getFieldErrors() .stream() .map(this::createErrorDetail) .collect(Collectors.toList()); RegAnswer regAnswer = new RegAnswer(); regAnswer.setFieldErrors(fieldErrors); return ResponseEntity.ok().body(new BaseResponse(msgId, MessageCode.INVALID_FIELD.getCode(), MessageCode.INVALID_FIELD.getDescription(), regAnswer)); } private Map createErrorDetail(FieldError fieldError) { Map errorDetail = new HashMap<>(); errorDetail.put("field", fieldError.getField()); errorDetail.put("code", fieldError.getCode() != null ? fieldError.getCode() : "VALIDATION_ERROR"); errorDetail.put("message", fieldError.getDefaultMessage()); if (fieldError.getRejectedValue() != null && !fieldError.getField().toLowerCase().contains("password")) { errorDetail.put("rejected_value", fieldError.getRejectedValue().toString()); } return errorDetail; } }