package com.tofly.spire.utils;

import com.alibaba.fastjson.JSONObject;
import com.tofly.spire.common.Constants;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author HaiQiu
 * @since 2022/11/10
 */
@Slf4j
@Component
public class SpireUtils {

    @Autowired
    private SpireMTLogin spireMTLogin;

    @Autowired
    private SpireApis apis;
    @Resource
    private RedisTemplate redisTemplate;

    /**
     * 定时刷新token
     *
     * @param param 无
     * @return token缓存到redis
     * @throws Exception
     */
    @XxlJob("refreshToken")
    public ReturnT<String> refreshToken(String param) throws Exception {
        String data = login();
        log.info("重新获取 Spire登录信息：{}", data);
        redisTemplate.opsForValue().set(Constants.SPIRE_MT_TOKEN_KEY, data, Constants.EXPIRE_TIME_TOKEN_KEY, TimeUnit.SECONDS);
        return ReturnT.SUCCESS;
    }


    /**
     * 登录的方法
     *
     * @return 登录
     */
    public String login() {
        log.info("----------------重新登录----------------");
        BeanMap params = BeanMap.create(spireMTLogin);
        log.info("----------------重新登录----{}------{}------",spireMTLogin.getUrl(),params);
        try {
            Object o = ApiClient.postRest(spireMTLogin.getUrl(), params);
            log.info("----------------获取重新登录返回结果----{}------------",o);
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(o));
            System.out.println(jsonObject);
            return jsonObject.toJSONString();
        }catch (Exception e){
            e.printStackTrace();
            log.info("请求出现错误:{}",e.getMessage());
        }
        return null;
    }


    /**
     * 获取token
     *
     * @return token
     */
    @SneakyThrows
    public String getToken() {
        log.info("正在获取到临时登录的token信息");
        refreshToken(null);
        Object o = redisTemplate.opsForValue().get(Constants.SPIRE_MT_TOKEN_KEY);
        log.info("获取到临时登录的token信息:{}",o);
        return JSONObject.parseObject(o.toString()).get("token").toString();
    }


    /**
     * 大表（管网）数据接口-此接口用户获取主网表具数据信息以及日志信息
     *
     * @param sn   不传获取所有表具的最新信息，
     *             传入获取对应表号的所有信息
     * @param date 不传获取所有表具的最新信息，
     *             传入返回传入日期到当前时间的日志信息
     * @return
     */
    public ResultScada getBulkMeterData(String sn, String date) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("sn", sn);
        jsonObject.put("date", date);
        String params = transformationParams(jsonObject);
        log.info("正在请求数据：{}{}",apis.getAddress() + apis.getGetBulkMeterData(), params);
        Object o = ApiClient.getReset(apis.getAddress() + apis.getGetBulkMeterData(), params);
        ResultScada resultScada = getResultScada(apis.getAddress() + apis.getGetBulkMeterData(), o);
        log.info("接口请求成功");
        return resultScada;
    }

    /**
     * 小表（户表）数据接口-通过此接口获取表端上传的数据信息以及日志信息。
     *
     * @param sn   不传获取所有表具的最新信息，
     *             传入获取对应表号的所有信息
     * @param date 不传获取所有表具的最新信息，
     *             传入返回传入日期到当前时间的日志信息
     * @return
     */
    public ResultScada getMeterData(String sn, String date) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("sn", sn);
        jsonObject.put("date", date);
        String params = transformationParams(jsonObject);
        Object o = ApiClient.getReset(apis.getAddress() + apis.getGetMeterData(), params);
        ResultScada resultScada = getResultScada(apis.getAddress() + apis.getGetBulkMeterData(), o);
        return resultScada;
    }


    /**
     * 小表（户表）信息接口-通过接口获取表具基本信息以及用户基本信息。
     *
     * @param sn 不传获取所有表具的最新信息，
     *           传入获取对应表号的所有信息
     * @return
     */
    public ResultScada getUserInfo(String sn) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("sn", sn);
        String params = transformationParams(jsonObject);
        Object o = ApiClient.getReset(apis.getAddress() + apis.getGetUserInfo(), params);
        ResultScada resultScada = getResultScada(apis.getAddress() + apis.getGetBulkMeterData(), o);
        return resultScada;
    }


    /**
     * 小表（户表）阀门控制-通过此接口控制表具阀门的开关(需要表端支持阀门控制)
     *
     * @param sn   表号
     * @param flag true=开阀 false=关阀
     * @return
     */
    public ResultScada valveControl(String sn, boolean flag) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("sn", sn);
        jsonObject.put("flag", flag);
        String params = transformationParams(jsonObject);
        Object o = ApiClient.getReset(apis.getAddress() + apis.getValveControl(), params);
        ResultScada resultScada = JSONObject.parseObject(JSONObject.toJSONString(o), ResultScada.class);
        return resultScada;
    }

    /**
     * 获取接口调用数据转换
     *
     * @param o
     * @return
     */
    private ResultScada getResultScada(String url, Object o) {
        ResultScada resultScada = JSONObject.parseObject(JSONObject.toJSONString(o), ResultScada.class);
        if (!Constants.HTTP_OK.equals(resultScada.getHttpCode())) {
            log.error("调用接口:{},返回结果:{}", url, o);
            throw new RuntimeException(o.toString());
        }
        return resultScada;
    }


    /**
     * get请求参数转换
     *
     * @param map map集合参数
     * @return 字符参数
     */
    public String transformationParams(Map<String, Object> map) {
        log.info("正在组装数据----------------------------------");
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(Constants.TOKEN).append("=").append(getToken());
        log.info("正在组装数据------------------token----------------");
        if (ObjectUtils.isEmpty(map)) {
            return stringBuffer.toString();
        }
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if (entry.getValue() != null && entry.getValue() != "") {
                stringBuffer.append(Constants.GET_MERGE_SYMBOL)
                        .append(entry.getKey())
                        .append("=")
                        .append(entry.getValue());
            }
        }
        log.info("正在组装数据------------------success------ data：{}----------",stringBuffer.toString());
        return stringBuffer.toString();
    }
}
