package top.imwork.commons.core.base;

import com.google.gson.Gson;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
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.client.HttpClientErrorException;
import top.imwork.commons.core.enums.HttpStatusCodeEnum;
import top.imwork.commons.core.exception.BusinessException;
import top.imwork.commons.core.pojo.ResponseMsg;
import top.imwork.commons.core.utils.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * Copyright (C), 2015-2021
 * FileName: BaseController
 * Author(作者姓名):   jiangxiaowei
 * CreateDate(创建时间):     2021/8/2 15:24
 * UpdateDate(修改时间):     2021/8/2 15:24
 * Description(功能描述):    基础控制器
 * Since(版本号)  1.0.0
 * History:
 */
@Controller
@ControllerAdvice
public class BaseController {
    Logger log = LoggerFactory.getLogger(BaseController.class);
    /**
     * HttpClientErrorException
     *
     * @return org.springframework.web.client.HttpClientErrorException$Unauthorized: 401
     */
    @ResponseBody
    @ExceptionHandler({HttpClientErrorException.class})
    public ResponseMsg httpClientErrorException(Exception e) {
        log.error(e.getMessage());
        return ResponseMsg.buildResponse(HttpStatusCodeEnum.UNAUTHORIZED.getCode(), HttpStatusCodeEnum.UNAUTHORIZED.getZmsg(), "error:refresh_token 过期无效");
    }

    /**
     * HTTP请求参数转换异常
     *
     * @param exception HTTP请求参数转换异常
     * @return 响应错误信息
     */
    @ResponseBody
    @ExceptionHandler({HttpMessageNotReadableException.class})
    public ResponseMsg httpMessageNotReadableException(Exception exception, HttpServletRequest request, HttpServletResponse response) {
        errorMsg(exception, request, response);
        return ResponseMsg.buildResponse(HttpStatusCodeEnum.BAD_REQUEST.getCode(), HttpStatusCodeEnum.BAD_REQUEST.getZmsg(), null);
    }

    /**
     * @param exception 捕获的异常
     * @param request   请求参数
     * @return 响应
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    protected ResponseMsg exception(Exception exception, HttpServletRequest request, HttpServletResponse response) {
        int statusCode = response.getStatus();
        errorMsg(exception, request, response);
        if (statusCode == 200) {
            statusCode = HttpStatusCodeEnum.BAD_REQUEST.getCode();
        }
        return ResponseMsg.buildResponse(statusCode,
                StringUtils.isEmpty(exception.toString()) ? Objects.requireNonNull(HttpStatusCodeEnum.fromTypeCode(statusCode)).getZmsg() : exception.toString(), null);
    }

    private void errorMsg(Exception exception, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> details = new HashMap<>();
        details.put("code", response.getStatus());
        details.put("msg", exception.getMessage());
        details.put("url", request.getRequestURI());

        Map<String, String[]> parameterMap = request.getParameterMap();
        Gson gson = new Gson();
        String json = gson.toJson(parameterMap);
        details.put("params", json);
        if (response.getStatus() == 200) {
            details.put("code", HttpStatusCodeEnum.BAD_REQUEST.getCode());
        }
        log.error(details.toString());
    }

    /**
     * 业务异常
     *
     * @param exception 捕获的异常
     * @return 响应
     */
    @ResponseBody
    @ExceptionHandler({BusinessException.class})
    public ResponseMsg exceptionParam(BusinessException exception) {
        log.error("业务异常:{}", exception.getMessage());
        return ResponseMsg.error("业务异常:" + exception.getMessage());
    }

    /**
     * 缺少参数的异常处理
     *
     * @param exception 捕获的异常
     * @return 响应
     */
    @ResponseBody
    @ExceptionHandler({MissingServletRequestParameterException.class})
    public ResponseMsg exceptionParam(MissingServletRequestParameterException exception) {
        log.error(exception.getMessage());
        return ResponseMsg.error(exception.getMessage());
    }

    /**
     * 参数校验异常处理
     *
     * @param exception 捕获的异常
     * @return 响应
     */
    @ResponseBody
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseMsg methodArgumentNotValidException(MethodArgumentNotValidException exception) {
        BindingResult bindingResult = exception.getBindingResult();
        if (bindingResult.hasErrors()) {
            FieldError error = bindingResult.getFieldError();
            if (error != null) {
                log.error("{}{}", error.getField(), error.getDefaultMessage());
                return ResponseMsg.error(error.getField() + error.getDefaultMessage());
            }
        }
        log.error(exception.getMessage());
        return ResponseMsg.error(exception.getMessage());
    }
}
