package com.jjt.rziot;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.jjt.JjtApplication;
import com.jjt.biz.domain.TwinDeviceYhj;
import com.jjt.biz.service.ITwinDeviceYhjService;
import com.jjt.calc.domain.TwinCalcHourYhj;
import com.jjt.calc.mapper.TwinCalcHourYhjMapper;
import com.jjt.calc.service.ITwinCalcDayYhjService;
import com.jjt.calc.service.ITwinCalcHourYhjService;
import com.jjt.common.utils.DateUtils;
import com.jjt.utils.IotService;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;
import java.io.FileOutputStream;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 印花机
 */
@SpringBootTest(classes = JjtApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class PrintingTest {
    @Resource
    private IotService iotService;
    @Resource
    private SqlSessionFactory factory;
    @Resource
    private ITwinDeviceYhjService yhjService;
    @Resource
    private ITwinCalcHourYhjService calcHourYhjService;
    @Resource
    private ITwinCalcDayYhjService calcDayYhjService;

    public static void main(String[] args) {
        Integer[] lines = {1, 2, 3, 4, 5, 6, 7, 8};
        List<String> lists = new ArrayList<>();
        String[] fields = {"Formula_data_set_1", "Formula_data_act_5"};
        String device = "yhj_line%s_PLC1.%s";
        for (int i = 0; i < lines.length; i++) {
            for (String field : fields) {
                String tmp = String.format(device, lines[i], field);
                lists.add(tmp);
            }
        }

        System.err.println(lists);
    }

    @Test
    void day() {
        String day = "2025-03-02";
        LocalDate localDate = LocalDate.parse(day);
        calcDayYhjService.day(localDate);
    }

    @Test
    void t2() {
        iotService.setToken();

        calcHourYhjService.calc2Curr();

//        String st = "2025-03-02";
//        String ed = "2025-03-06";
//        LocalDate localDate = LocalDate.parse(st);
//        LocalDate endDate = LocalDate.parse(ed);
//        LocalDateTime start = LocalDateTime.of(localDate, LocalTime.MIN);
//        LocalDateTime end = LocalDateTime.of(endDate, LocalTime.MIN).plusHours(23);
//        LocalDateTime curr = LocalDateTime.now();
//        if (end.isAfter(curr)) {
//            end = curr.minusHours(1);
//        }
//        do {
//            int i = start.getHour();
//            System.err.println(start.toLocalDate().toString() + "\t" + i);
//            calcHourYhjService.calc(start, start.plusHours(1));
////            if (i == 6) {
////                dayService.day(start.toLocalDate());
////            }
//            start = start.plusHours(1);
//        } while (!start.isAfter(end));
//        calcHourYhjService.calc();

    }

    @Test
    void t1() {
        iotService.setToken();
        List<TwinDeviceYhj> list = yhjService.selectTwinDeviceYhjList(new TwinDeviceYhj());
        List<TwinCalcHourYhj> calcList = new ArrayList<>();
        //  使用设备编码作为Map的key, 使用设备对象本身作为Map的value, 如果有重复的key，保留现有的value
        Map<String, TwinDeviceYhj> yhjMap = new HashMap<>();
        List<String> fieldList = new ArrayList<>();
        String prefix = "root.tl.suxi";
        String[] fields = {"Formula_data_set_1", "Formula_data_act_5"};
        for (TwinDeviceYhj yhj : list) {
            for (String field : fields) {
                String tmp = yhj.getDeviceCode() + "." + field;
                fieldList.add(tmp);
                yhjMap.put(prefix + "." + tmp, yhj);
            }
        }
        String sql = "select %s from " + prefix + " where time>%s and time <=%s";

        sql = String.format(sql, String.join(",", fieldList), "2025-03-02T00:00:00", "2025-03-02T01:00:00");
        JSONObject jsonObject = iotService.query(sql);
        JSONObject data = jsonObject.getJSONObject("data");
        JSONArray columnNames = data.getJSONArray("columnNames");
        JSONArray values = data.getJSONArray("values");
        JSONArray timestamps = data.getJSONArray("timestamps");
        //记录上一次记录的值
        Integer[] last = new Integer[columnNames.size()];
        //记录最后一次的值，防中间有数，后面没数
        Integer[] over = new Integer[columnNames.size()];
        //当前记录值
        Integer[] total = new Integer[columnNames.size()];
        //记录第一次记录的值，如果清0，则记录清零时刻的值
        Integer[] first = new Integer[columnNames.size()];
        //记录统计值
        Integer[] curr = new Integer[columnNames.size()];
        for (int i = 0; i < values.size(); i++) {
            JSONArray da = values.getJSONArray(i);
            da.toList(Integer.class).toArray(curr);
            if (i == 0) {
                cloneArray(curr, last);
                cloneArray(curr, first);
                cloneArray(curr, over);
                continue;
            }
            for (int j = 0; j < columnNames.size(); j++) {
                String name = columnNames.getStr(j);
                if (name.contains("Formula_data_set_1")) {
                    //如果是版距，则需要记录变化
                    if (curr[j] != null && last[j] != null && curr[j].intValue() != last[j].intValue()) {
                        //这里要用j+1才行
                        calc(j + 1, last, first, total);
                        combo(calcList, yhjMap.get(name), last[j], total[j + 1]);
                        total[j + 1] = 0;
                    }
                }
                if (name.contains("Formula_data_act_5")) {
                    //如果是米长，则需要记录是否清0
                    //如果当前值为小于上一个，且上一个值不为0，则计算
                    //因为会出现数据波动，停机再启动之后的第一个点不为0，为0.00几几几的
                    if (curr[j] != null && last[j] != null && curr[j] < last[j] && last[j] != 0) {
                        calc(j, last, first, total);
                        cloneArray(curr, first);
                    }
                }
            }
            //将本次的值，设为上一条记录了
            cloneArray(curr, last);
            cloneArray(curr, over);
            cloneArrayFirst(curr, first);
        }
        for (int j = 0; j < columnNames.size(); j++) {
            String name = columnNames.getStr(j);
            if (name.contains("Formula_data_set_1")) {
                calc(j + 1, over, first, total);
                combo(calcList, yhjMap.get(name), over[j], total[j + 1]);
            }
        }

        try (SqlSession sqlSession = factory.openSession(ExecutorType.BATCH, false)) {
            if (calcList.size() > 0) {
                TwinCalcHourYhjMapper mapper = sqlSession.getMapper(TwinCalcHourYhjMapper.class);
                calcList.forEach(mapper::insertTwinCalcHourYhj);
                sqlSession.commit();
            }
        }
        System.err.println(total);
    }

    void cloneArrayFirst(Integer[] arr, Integer[] target) {
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] != null && target[i] == null) {
                target[i] = arr[i];
            }
        }
    }

    void cloneArray(Integer[] arr, Integer[] target) {
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] != null) {
                target[i] = arr[i];
            }
        }
    }

    void combo(List<TwinCalcHourYhj> calcList, TwinDeviceYhj yhj, Integer distance, Integer length) {
        if (distance != null && length != null) {
            TwinCalcHourYhj calcHourYhj = new TwinCalcHourYhj();
            calcHourYhj.setDeviceId(yhj.getDeviceId());
            calcHourYhj.setDistance(distance);
            calcHourYhj.setLength(length);
            calcList.add(calcHourYhj);
        }
    }

    void calc(int j, Integer[] last, Integer[] first, Integer[] total) {
        if (last[j] != null && first[j] != null) {
            if (total[j] == null) {
                total[j] = 0;
            }
            total[j] += (last[j] - first[j]);
        }
    }


    /**
     * 印花设备数据
     */
    @Test
    void test() {
        iotService.setToken();
        Integer[] lines = {1, 2, 3, 4, 5, 6, 7, 8};
        List<String[]>[] lists = new ArrayList[8];
        String[] fields = {"Formula_data_set_1", "Formula_data_act_5"};
        for (int i = 0; i < lines.length; i++) {
            String table = "root.tl.suxi.yhj_line" + lines[i] + "_PLC1";
            lists[i] = new ArrayList<>();
            String st = "2025-03-03";
            LocalDate localDate = LocalDate.parse(st);
            LocalDateTime start = LocalDateTime.of(localDate, LocalTime.MIN).plusHours(7);
            LocalDateTime end = start.plusHours(23);
            do {
                LocalDateTime startTime = start;
                LocalDateTime endTime = start.plusHours(1);
                List<String[]> pList = get(table, startTime, endTime);
                lists[i].addAll(pList);
                start = start.plusHours(1);
            } while (!start.isAfter(end));
        }

        try (Workbook workbook = new XSSFWorkbook(); FileOutputStream outputStream = new FileOutputStream("D:\\SYSTEM\\Desktop\\temp\\excel\\印花机数据-明细" + System.currentTimeMillis() + ".xlsx")) {
            for (int i = 0; i < lines.length; i++) {
                Sheet sheet = workbook.createSheet(lines[i] + "线");
                toExcelNew(lists[i], sheet);
            }
            workbook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public List<String[]> get(String table, LocalDateTime start, LocalDateTime end) {
        List<String[]> list = new ArrayList<>();
        Long startTime = start.toInstant(ZoneOffset.of("+8")).toEpochMilli();
        Long endTime = end.toInstant(ZoneOffset.of("+8")).toEpochMilli();
        String[] fields = {"Formula_data_set_1", "Formula_data_set_3", "Formula_data_act_2", "Formula_data_act_3", "Formula_data_act_4", "Formula_data_act_5"};
        String sql = "select %s from %s where time>%s and time <=%s";
        sql = String.format(sql, String.join(",", fields), table, startTime, endTime);
        iotService.query(sql);
        JSONObject jsonObject = iotService.query(sql);
        JSONObject data = jsonObject.getJSONObject("data");
        JSONArray values = data.getJSONArray("values");
        JSONArray timestamps = data.getJSONArray("timestamps");
        for (int i = 0; i < values.size(); i++) {
            String[] temp = new String[fields.length + 1];
            temp[0] = timestamps.getStr(i);
            JSONArray da = values.getJSONArray(i);
            for (int j = 1; j < temp.length; j++) {
                temp[j] = da.getStr(j - 1);
            }
            list.add(temp);
        }
        return list;
    }

    public void toExcelNew(List<String[]> list, Sheet sheet) {
        String[] names = {"时间", "版距 0.01mm", "贴布轮速度1%", "生产速度0.01m/m", "生产速度0.1t/m", "产量次数计数器 1次", "产量长度计数器  1M"};

        Row title = sheet.createRow(0);
        for (int i = 0; i < names.length; i++) {
            Cell cell = title.createCell(i);
            cell.setCellValue(names[i]);
        }
        AtomicInteger index = new AtomicInteger(1);
        list.forEach(d -> {
            Row row = sheet.createRow(index.get());
            Long time = Long.parseLong(d[0]);
            String date = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, new Date(time));
            Cell cell = row.createCell(0);
            cell.setCellValue(date);
            for (int j = 1; j < d.length; j++) {
                cell = row.createCell(j);
                cell.setCellValue(Float.parseFloat(d[j]));

            }
            index.getAndIncrement();
        });
    }
}
