package com.icomsys.main_vm.biz.advice;

import com.icomsys.main_vm.biz.advice.excep.CustomNoSuchFieldException;
import com.icomsys.main_vm.biz.advice.excep.CustomRuntimeException;
import com.icomsys.main_vm.biz.advice.excep.CustomBadRequestException;
import com.icomsys.main_vm.biz.advice.excep.CustomNotFoundException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Objects;

@ControllerAdvice
@RequiredArgsConstructor
@Slf4j
public class AdviceHandler {

    private final MessageSource messageSource;

    @ExceptionHandler
    public String noHandlerFoundHandle(RuntimeException e) {
        log.error(e.getMessage());
        return "cmm/error/error";
    }

    @ExceptionHandler
    public ResponseEntity CustomRuntime(CustomRuntimeException e) {
        ErrorResult er = new ErrorResult();
        er.setCode(String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value()));
        er.setMessage(e.getMessage());
        log.info("excep - {}", e);
        return new ResponseEntity(er, HttpStatus.INTERNAL_SERVER_ERROR);
    }

//    @ExceptionHandler
//    public ResponseEntity DefaultNotFound(NotFoundException e) {
//        ErrorResult er = new ErrorResult();
//        er.setCode(String.valueOf(HttpStatus.NOT_FOUND.value()));
//        er.setMessage(messageSource.getMessage("info.nodata.msg", null, Locale.getDefault()));
//        log.info("excep - {}", messageSource.getMessage("info.nodata.msg", null, Locale.getDefault()));
//        return new ResponseEntity(er, HttpStatus.NOT_FOUND);
//    }

    @ExceptionHandler
    @ResponseBody
    public ResponseEntity DefaultNotFound(IllegalArgumentException e) {
        ErrorResult er = new ErrorResult();
        er.setCode(String.valueOf(HttpStatus.NOT_FOUND.value()));
        er.setMessage(messageSource.getMessage("info.nodata.msg", null, Locale.getDefault()));
        log.info("excep - {} {}", messageSource.getMessage("info.nodata.msg", null, Locale.getDefault()),e.getMessage());
        return new ResponseEntity(er, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler
    public ResponseEntity CustomNotFound(CustomNotFoundException e) {
        ErrorResult er = new ErrorResult();
        er.setCode(String.valueOf(HttpStatus.NOT_FOUND.value()));
        er.setMessage(e.getMessage());
        log.info("excep - {}", e.getMessage());
        return new ResponseEntity(er, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler
    public ResponseEntity CustomBadRequest(CustomBadRequestException e) {
        ErrorResult er = new ErrorResult();
        er.setCode(String.valueOf(HttpStatus.BAD_REQUEST.value()));
        er.setMessage(e.getMessage());
        log.info("excep - {}", e.getMessage());
        return new ResponseEntity(er, HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler
    public ResponseEntity CustomBadRequest(IllegalAccessException e) {
        ErrorResult er = new ErrorResult();
        er.setCode(String.valueOf(HttpStatus.BAD_REQUEST.value()));
        er.setMessage(messageSource.getMessage("fail.common.bad", null, Locale.getDefault()));
        log.info("excep - {}", messageSource.getMessage("fail.common.bad", null, Locale.getDefault()));
        return new ResponseEntity(er, HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler
    public ResponseEntity CustomBindEx(BindException ex) {
        ErrorResult er = new ErrorResult();
        log.info("bind 들어옴");
        String message = null;
        List<ObjectError> allErrors = ex.getBindingResult().getAllErrors();
        for (ObjectError error : allErrors) {
            message = Arrays.stream(Objects.requireNonNull(error.getCodes()))
                    .map(c -> {
                        Object[] arguments = error.getArguments();
                        Locale locale = LocaleContextHolder.getLocale();
                        try {
                            return messageSource.getMessage(c, arguments, locale);
                        } catch (NoSuchMessageException e) {
                            return null;
                        }
                    }).filter(Objects::nonNull)
                    .findFirst()
                    .orElse(error.getDefaultMessage());
        }
        log.error("error message: {}", message);
        er.setMessage(message);
        er.setCode(String.valueOf(HttpStatus.BAD_REQUEST.value()));
        return new ResponseEntity(er, HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler
    public ResponseEntity CustomNoSuchMessage(NoSuchMessageException e) {
        ErrorResult er = new ErrorResult();
        er.setCode(String.valueOf(HttpStatus.NOT_FOUND.value()));
        er.setMessage(e.getMessage());
        log.info("excep - {}", e.getMessage());
        return new ResponseEntity(er, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler
    public String CustomNoSuchFieldException(NoSuchFieldException e) {
        return "adm/signin/signin";
    }

    @ExceptionHandler
    public String CustomNoSuchFieldException(CustomNoSuchFieldException e) {
        return "adm/signin/signin";
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    public String noHandlerFoundHandle(NoHandlerFoundException e) {
        return "cmm/error/egovError";
    }

    @ExceptionHandler
    public ResponseEntity responseStatusException(ResponseStatusException e) {
        return ResponseEntity.status(e.getStatus()).build();
    }


}
