package com.inspect.job.task;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.inspect.base.core.exception.ServiceException;
import com.inspect.base.core.service.SyncDataToUpstreamService;
import com.inspect.base.core.utils.StringUtils;
import com.inspect.base.core.web.domain.AjaxResult;
import com.inspect.base.redis.service.RedisService;
import com.inspect.job.client.MontQueryClient;
import com.inspect.job.mapper.PatrolDeviceStateMapper;
import com.inspect.job.vo.TimeIntervalData;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;

import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component("upTask")
public class UpTask {
    @Resource
    SyncDataToUpstreamService syncDataToUpstreamService;
    public String timeIntervalKey = "time_interval_up_system_setting";
    Logger logger = LoggerFactory.getLogger(UpTask.class);
    public String lastTaskTimeKey = "last_up_data_task_time";
    public String envLastTimeKey = "env_last_time";
    public String deviceLastTimeKey = "device_last_time";
    public String deviceStatisticsTimeKey = "device_statistics_last_time";
    public String nestLastTimeKey = "nest_last_time";
    public String INIT_PATROL_DEVICE_STATE_LOCK_PRE = "init_patrol_device_state_lock_";
    public static final int SECOND_MILLS = 1000;
    public static JSONArray deviceStateConfig = new JSONArray();
    @Resource
    RedisService redisService;
    @Resource
    MontQueryClient montQueryClient;
    @Resource
    PatrolDeviceStateMapper mapper;

    public void timerTaskData() {
        this.logger.info("********************** UpTask timerTaskData ******************************");
        Object timeIntervalData = this.redisService.getCacheObject(this.timeIntervalKey);
        if(timeIntervalData == null) {
            this.logger.info("未设置上报数据执行间隔，可能的原因是，tcpClient未成功连接上级系统");
        } else {
            if(timeIntervalData instanceof JSONObject) {
                TimeIntervalData intervalData = ((JSONObject) timeIntervalData).toJavaObject(TimeIntervalData.class);
                this.logger.info("timeIntervalData1: " + JSONUtil.toJsonStr(intervalData));
                this.upData(intervalData);
            } else if(timeIntervalData instanceof String) {
                TimeIntervalData intervalData = JSONObject.parseObject((String)timeIntervalData, TimeIntervalData.class);
                this.logger.info("timeIntervalData2: " + JSONUtil.toJsonStr(intervalData));
                this.upData(intervalData);
            }
        }
    }

    public void upDeviceStatisticsTask() {
        this.logger.info("********************** UpTask upDeviceStatisticsTask ******************************");
        this.upDeviceStatisticsData();
    }

    public void initPatrolDeviceStateTask() {
        this.logger.info("********************** UpTask initPatrolDeviceStateTask ******************************");
        this.initPatrolDeviceState();
    }

    private void initPatrolDeviceState() {
        String today = DateUtil.format(new Date(), "yyyy-MM-dd");
        String lock = this.redisService.getCacheObject(this.INIT_PATROL_DEVICE_STATE_LOCK_PRE + today);
        if (null != lock) {
            this.logger.info("今日已经执行过初始化巡视设备状态初始化，取消操作");
        } else {
            synchronized (this) {
                lock = (String) this.redisService.getCacheObject(this.INIT_PATROL_DEVICE_STATE_LOCK_PRE + today);
                if (null != lock) {
                    this.logger.info("今日已经执行过初始化巡视设备状态初始化，取消操作");
                } else {
                    this.mapper.initData();
                    this.mapper.initDataInfo();
                    this.logger.info("今日巡视设备状态初始化已完成");
                    this.redisService.setCacheObject(this.INIT_PATROL_DEVICE_STATE_LOCK_PRE + today, "lock", 1L, TimeUnit.DAYS);
                }
            }
        }
    }

    public void upData(TimeIntervalData intervalData) {
        this.upEnvData(intervalData);
        this.upNestData(intervalData);
        this.upDeviceRunInfoData(intervalData);
    }

    public boolean needDo(String key, Integer timeInterval) {
        Long lastTime = (Long) this.redisService.getCacheMapValue(this.lastTaskTimeKey, key);
        return lastTime == null || (int) (System.currentTimeMillis() - lastTime) >= timeInterval * 1000;
    }

    public void updateLastTime(String key) {
        this.redisService.setCacheMapValue(this.lastTaskTimeKey, key, System.currentTimeMillis());
    }

    public void upEnvData(TimeIntervalData intervalData) {
        if (this.needDo(this.envLastTimeKey, intervalData.getWeather())) {
            this.logger.info("上报环境数据执行");

            try {
                String msg = this.getInfo("21");
                this.sendMsg(msg);
            } catch (Exception e) {
                e.printStackTrace();
            }

            this.updateLastTime(this.envLastTimeKey);
        }
    }

    public void upDeviceStatisticsData() {
        this.logger.info("上报巡视设备统计信息");
        List<HashMap<String, Object>> list = this.mapper.queryData();
        if (CollectionUtils.isEmpty(list)) {
            this.logger.info("上报巡视设备统计信息定时任务，查询巡视设备状态表为空");
        } else {
            JSONArray jsonArray = JSONArray.parseArray(JSONArray.toJSONString(list));
            JSONArray items = this.handleItems(jsonArray);
            JSONObject result = new JSONObject();
            String stationCode = this.mapper.queryStationCode();
            result.put("Code", stationCode);
            result.put("Type", 81);
            result.put("Items", items);
            this.sendMsg(result.toJSONString());
        }
    }

    private JSONArray handleItems(JSONArray jsonArray) {
        JSONArray items = new JSONArray();

        for (int i = 0; i < jsonArray.size(); ++i) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            String patrolDeviceCode = jsonObject.getString("patrolDeviceCode");
            String patrolDeviceName = jsonObject.getString("patrolDeviceName");
            Integer totalDays = jsonObject.getInteger("totalDays");
            Integer taskDays = jsonObject.getInteger("taskDays");
            BigDecimal attendance = BigDecimal.valueOf((long) taskDays).divide(BigDecimal.valueOf(totalDays), 3, RoundingMode.HALF_UP);
            jsonObject.put("attendance", attendance);

            for (int j = 0; j < deviceStateConfig.size(); ++j) {
                JSONObject json = new JSONObject();
                JSONObject config = deviceStateConfig.getJSONObject(j);
                Integer type = config.getInteger("index");
                String unit = config.getString("unit");
                String col = config.getString("col");
                String value = jsonObject.getString(col);
                Date date = jsonObject.getDate("commission_time");
                String commission_time = "";
                if (date != null) {
                    commission_time = DateUtil.format(date, "yyyy-MM-dd HH:mm:ss");
                }

                json.put("patrolDeviceCode", patrolDeviceCode);
                json.put("patrolDeviceName", patrolDeviceName);
                json.put("commissionTime", commission_time);
                json.put("reportTime", DateUtil.format(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss"));
                json.put("type", type);
                json.put("value", value);
                json.put("unit", unit);
                json.put("valueUnit", value + unit);
                items.add(json);
            }
        }

        return items;
    }

    public void upDeviceRunInfoData(TimeIntervalData intervalData) {
        if (this.needDo(this.deviceLastTimeKey, intervalData.getPatrolDevice())) {
            this.logger.info("上报设备运行数据");
            String msg = this.getInfo("2");
            this.sendMsg(msg);
            this.updateLastTime(this.deviceLastTimeKey);
        }
    }

    public void upNestData(TimeIntervalData intervalData) {
        if (this.needDo(this.nestLastTimeKey, intervalData.getNest())) {
            this.upNestRunInfoData();
            this.upNestStateInfoData();
            this.updateLastTime(this.nestLastTimeKey);
        }
    }

    public void upNestRunInfoData() {
        this.logger.info("上报无人机机巢运行数据");
        String msg = this.getInfo("10004");
        this.sendMsg(msg);
    }

    public void upNestStateInfoData() {
        this.logger.info("上报无人机机巢状态数据");
        String msg = this.getInfo("20001");
        this.sendMsg(msg);
    }

    public String getInfo(String type) {
        AjaxResult msgToZk = this.montQueryClient.getMsgToZk(Integer.parseInt(type));
        if (msgToZk == null) {
            return StringUtils.EMPTY;
        }
        this.logger.info("从基础服务中获取的数据：type:{},data:{}", type, msgToZk);
        Object data = msgToZk.get("data");
        JSONArray dataArr = JSONArray.parseArray(JSONObject.toJSONString(data));
        JSONObject result = new JSONObject();
        result.put("Type", type);
        result.put("Items", new JSONArray());

        for (int i = 0; i < dataArr.size(); ++i) {
            JSONObject jsonObject = dataArr.getJSONObject(i);
            JSONArray items = jsonObject.getJSONArray("Items");
            result.getJSONArray("Items").addAll(items);
        }

        return result.toJSONString();
    }

    public AjaxResult sendMsg(String msg) {
        try {
            JSONObject.parseObject(msg);
            return this.syncDataToUpstreamService.postMessage(msg);
        } catch (Exception e) {
            this.logger.error("error", e);
            throw e;
        }
    }

    static {
        String messageModel = " [\n             {\n                 \"index\":1,\n                 \"col\":\"onlineSum\",\n                 \"unit\":\"分\"\n             },\n             {\n                 \"index\":2,\n                 \"col\":\"offlineCount\",\n                 \"unit\":\"次\"\n             },\n             {\n                 \"index\":3,\n                 \"col\":\"nomalDays\",\n                 \"unit\":\"天\"\n             },\n             {\n                 \"index\":4,\n                 \"col\":\"taskDays\",\n                 \"unit\":\"天\"\n             },\n             {\n                 \"index\":5,\n                 \"col\":\"attendance\",\n                 \"unit\":\"%\"\n             },\n             {\n                 \"index\":6,\n                 \"col\":\"recordTime\",\n                 \"unit\":\"%\"\n             }\n\n         ]";
        deviceStateConfig = JSONArray.parseArray(messageModel);
    }
}
