package org.springblade.common.aspect;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.http.ContentType;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springblade.common.utils.RedisTool;
import org.springblade.modules.api.response.VendingOrderRes;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 设备调用接口限流
 */
@Aspect
@Component
@Slf4j
public class VendingFlagAspect {

    @Resource
    private HttpServletRequest request;
    @Resource
    private HttpServletResponse response;
    @Resource
    private RedisTool redisTool;

    @Around("@annotation(org.springblade.common.aspect.VendingFlag)")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        //获取请求路径
        String requestURI = request.getRequestURI();
        //获取请求参数
        JSONObject reqParam = this.readReqParam(request);
        String machine_id =  reqParam.get("machine_id").toString();
        if (Objects.isNull(machine_id)) {
            return joinPoint.proceed();
        } else {
            boolean redisLock = redisTool.getRedisLock(machine_id + ":" + requestURI, "1");
            if (!redisLock) {
                VendingOrderRes vendingOrderRes = new VendingOrderRes();
                vendingOrderRes.setMachine_id(machine_id);
                vendingOrderRes.setSaleSn("");
                vendingOrderRes.setChannelNum("0");
                vendingOrderRes.setSaledata(new HashMap<>());
                this.notifyReturn(response, vendingOrderRes);
                log.info("设备：" + machine_id + "请求接口：" + requestURI + "被限流!");
                return response;
            }
            Object proceed;//请求过程
            try {
                proceed = joinPoint.proceed();
            } finally {
                //移除redis标识
                redisTool.unRedisLock(machine_id + ":" + requestURI);
            }
            return proceed;
        }

    }

    private JSONObject readReqParam(HttpServletRequest request) {
        BufferedReader br = null;
        StringBuilder sb = new StringBuilder("");
        try {
            br = request.getReader();
            String str;
            while ((str = br.readLine()) != null) {
                sb.append(str);
            }
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        JSONObject jsonObject = JSONUtil.parseObj(sb.toString());
        return jsonObject;
    }


    /**
     * 硬件接口通用响应
     *
     * @param response        HttpServletResponse
     * @param vendingOrderRes 返值
     */
    private void notifyReturn(HttpServletResponse response, VendingOrderRes vendingOrderRes) throws IOException {
        Map<String, Object> map = BeanUtil.beanToMap(vendingOrderRes);
        response.setHeader("Content-type", ContentType.JSON.toString());
        response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8));
        response.flushBuffer();
    }

}
