package com.yonge.cooleshow.common.controller;

import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yonge.cooleshow.common.entity.HttpResponseResult;
import com.yonge.cooleshow.common.exception.BizException;
import com.yonge.toolset.base.exception.ThirdpartyException;
import com.yonge.toolset.utils.http.HttpUtil;

@ControllerAdvice
public class BaseController {

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

	public static <T> HttpResponseResult<T> succeed(T object) {
		return getResponseData(true, HttpStatus.OK, object, "");
	}

	public static <T> HttpResponseResult<T> succeed() {
		return getResponseData(true, HttpStatus.OK, null, "");
	}

	public static <T> HttpResponseResult<T> succeedData(T obj) {
		return getResponseData(true, HttpStatus.OK, obj, "操作成功");
	}

	public static <T> HttpResponseResult<T> warned(String message) {
		return failed(HttpStatus.MULTI_STATUS, message);
	}

	public static <T> HttpResponseResult<T> failed() {
		return failed("");
	}

	public static <T> HttpResponseResult<T> failed(String msg) {
		return failed(HttpStatus.INTERNAL_SERVER_ERROR, msg);
	}

	public static <T> HttpResponseResult<T> failed(HttpStatus statusCode, String msg) {
		return getResponseData(false, statusCode, null, msg);
	}
	public static <T> HttpResponseResult<T> failed(int code, String msg) {
		return getResponseData(false, code, null, msg);
	}

	public static <T> HttpResponseResult<T> status(boolean flag) {
			return flag ? succeed() : failed("操作失败");
	}

	public static <T> HttpResponseResult<T> failed(HttpStatus statusCode, T data, String msg) {
		return getResponseData(false, statusCode, data, msg);
	}

	private static <T> HttpResponseResult<T> getResponseData(boolean status, HttpStatus statusCode, T data, String message) {
		HttpResponseResult<T> obj = new HttpResponseResult<T>();
		obj.setStatus(status);
		obj.setCode(statusCode.value());
		obj.setData(data);
		obj.setMsg(message);
		return obj;
	}

	private static <T> HttpResponseResult<T> getResponseData(boolean status, int code, T data, String message) {
		HttpResponseResult<T> obj = new HttpResponseResult<T>();
		obj.setStatus(status);
		obj.setCode(code);
		obj.setData(data);
		obj.setMsg(message);
		return obj;
	}

	/**
	 * 处理一般异常
	 *
	 * @param ex
	 * @param request
	 * @return
	 */
	@ExceptionHandler(Exception.class)
	public HttpResponseResult<String> handleException(Exception ex, HttpServletRequest request) {
		Throwable e = ExceptionUtils.getRootCause(ex);
		if (e == null) {
			e = ex;
		}
		logger.error("System Error", ex);
		// return failed(e.getMessage());
		if (e instanceof BizException || e instanceof ThirdpartyException) {
			if(e.getMessage().equals("205")){
				return failed(HttpStatus.RESET_CONTENT,e.getMessage());
			}
			return failed(e.getMessage());
		} else if (e instanceof AccessDeniedException) {
			return failed("禁止访问");
		}else if(e instanceof BindException){
			String errors = ((BindException) e).getFieldErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining("\n"));
			return failed(errors);
		} else if(e instanceof MethodArgumentNotValidException){
            MethodArgumentNotValidException validException = (MethodArgumentNotValidException) ex;
            String errorMsg = validException.getBindingResult()
                    .getFieldErrors()
                    .stream()
                    .map(FieldError::getDefaultMessage)
                    .collect(Collectors.joining());
            return failed(errorMsg);
        }
		try {
			Map<String,Object> paramMap = new HashMap<>(2);
			JSONObject jsonObject = new JSONObject();
			jsonObject.put("content","系统繁忙请及时处理: " + request.getRequestURL() + "   " + e);
			paramMap.put("text",jsonObject.toJSONString());
			paramMap.put("msgtype","text");
			Map<String,String> headers = new HashMap<>(1);
			headers.put("Content-Type","application/json");
			HttpUtil.postForHttps(dingTalkRobotsSecurityParam(),JSON.toJSONString(paramMap),headers);
		}catch (Exception exception){
			logger.error("System Error", exception);
		}
        if (StringUtils.isNotBlank(e.getMessage())) {
            return failed(e.getMessage());
        }
		return failed("系统繁忙");
	}

	public String dingTalkRobotsSecurityParam() throws Exception{
		Long timestamp = System.currentTimeMillis();
		String secret = "SEC36b17ac2f4e201f962042fb05f4b6b827719bcf9b6bb7b672e61f99c752eb693";
		String stringToSign = timestamp + "\n" + secret;
		Mac mac = Mac.getInstance("HmacSHA256");
		mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
		byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
		String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)),"UTF-8");
		StringBuffer sb = new StringBuffer("https://api.dingtalk.com/robot/send?access_token=22d7b3b54ea7f1633c640dfdf17083d0731c3757719a84bd333740a8b18eb035&timestamp=");
		sb.append(timestamp).append("&sign=").append(sign);
		return sb.toString();
	}
}
