package com.xunhong.erp.turbo.web.handler;


import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import cn.dev33.satoken.exception.NotSafeException;
import com.alibaba.cola.dto.Response;
import com.alibaba.cola.dto.SingleResponse;
import com.xunhong.erp.turbo.base.exception.BizException;
import com.xunhong.erp.turbo.base.exception.ErrorCode;
import com.xunhong.erp.turbo.base.exception.SystemException;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;


/**
 * 接口异常统一处理
 *
 * @author shenyifei
 */
@Slf4j
@RestControllerAdvice
@Order(4)
public class GlobalExceptionHandler {

	@ResponseBody
	@ExceptionHandler(NullPointerException.class)
	public Response handleException(NullPointerException e) {
		log.error("********NullPointerException********: 空指针：{}", e.toString(), e);
		return SingleResponse.buildFailure(HttpStatus.BAD_REQUEST.value() + "", "空指针异常");
	}

	@ResponseBody
	@ExceptionHandler(BizException.class)
	public Response handleBizException(BizException e) {
		log.error("********BizException********: 业务异常：{}", e.toString(), e);
		ErrorCode errorCode = e.getErrorCode();
		String message = e.getMessage();
		if (Objects.isNull(message)) {
			message = errorCode.getMessage();
		}
		return SingleResponse.buildFailure(errorCode.getCode(), message);
	}


	@ExceptionHandler({NotLoginException.class})
	@ResponseStatus(value = HttpStatus.OK)
	public Response notLoginException(NotLoginException e) {
		return SingleResponse.buildFailure(HttpStatus.UNAUTHORIZED.value() + "", e.getMessage());
	}

	@ExceptionHandler({NotRoleException.class})
	@ResponseStatus(value = HttpStatus.OK)
	public Response notRoleException(NotRoleException e) {
		return SingleResponse.buildFailure(HttpStatus.FORBIDDEN.value() + "", e.getMessage());
	}

	@ExceptionHandler({NotPermissionException.class})
	@ResponseStatus(value = HttpStatus.OK)
	public Response notNotPermissionException(NotPermissionException e) {
		return SingleResponse.buildFailure(HttpStatus.FORBIDDEN.value() + "", e.getMessage());
	}

	@ExceptionHandler({NotSafeException.class})
	@ResponseStatus(value = HttpStatus.OK)
	public Response systemException(NotSafeException e) {
		Response response = Response.buildSuccess();
		response.setErrMessage("请完成二级认证后再次访问接口");
		response.setErrCode("401");
		response.setSuccess(true);

		return response;
	}

	@ExceptionHandler({MethodArgumentNotValidException.class})
	@ResponseStatus(value = HttpStatus.OK)
	public SingleResponse<Map<String, String>> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
		log.error("********MethodArgumentNotValidException********: 校验异常：{}", e.toString(), e);
		List<FieldError> allErrors = e.getBindingResult().getFieldErrors();
		Object target = e.getBindingResult().getTarget();

		HashMap<String, String> hashMap = new HashMap<>();

		allErrors.forEach(i -> {
			String fieldName = "";

			if (Objects.nonNull(target)) {
				try {
					Annotation[] annotations = target.getClass().getDeclaredField(i.getField()).getAnnotations();
					for (Annotation annotation : annotations) {
						if (annotation instanceof Schema data) {
							fieldName = data.title();
						}
					}
				} catch (NoSuchFieldException ignored) {
				}
			}

			hashMap.put(i.getField(), hashMap.getOrDefault(i.getField(), fieldName) + i.getDefaultMessage());
		});

		SingleResponse<Map<String, String>> singleResponse = SingleResponse.of(hashMap);
		singleResponse.setErrMessage(String.join(",", hashMap.values()));
		singleResponse.setErrCode(HttpStatus.BAD_REQUEST.value() + "");
		singleResponse.setSuccess(false);
		return singleResponse;

	}


	/**
	 * 自定义系统异常处理器
	 *
	 * @param systemException
	 * @return
	 */
	@ResponseBody
	@ExceptionHandler(SystemException.class)
	public Response systemExceptionHandler(SystemException systemException) {
		log.error("systemException occurred.", systemException);
		return SingleResponse.buildFailure(systemException.getErrorCode().getCode(), systemException.getErrorCode().getMessage());
	}

	/**
	 * 自定义系统异常处理器
	 *
	 * @param throwable
	 * @return
	 */
	@ResponseBody
	@ExceptionHandler(Throwable.class)
	public Response throwableHandler(Throwable throwable) {
		log.error("throwable occurred.", throwable);
		return SingleResponse.buildFailure("500", "哎呀，当前网络比较拥挤，请您稍后再试~");
	}
}
