package com.jjt.biz.controller;

import com.jjt.biz.domain.TwinDevice;
import com.jjt.biz.service.ITwinDeviceService;
import com.jjt.biz.vo.*;
import com.jjt.calc.domain.TwinCalcDay;
import com.jjt.calc.service.ITwinCalcDayService;
import com.jjt.common.constant.CacheConstants;
import com.jjt.common.core.controller.BaseController;
import com.jjt.common.core.domain.R;
import com.jjt.common.core.redis.RedisCache;
import com.jjt.common.utils.DateUtils;
import com.jjt.utils.AsyncService;
import com.jjt.utils.Tools;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;

/**
 * swagger 用户测试方法
 *
 * @author ruoyi
 */
@Api(tags = "数据接口")
@RestController
@Slf4j
public class ApiController extends BaseController {
    @Resource
    private ITwinCalcDayService twinCalcDayService;
    @Resource
    private ITwinDeviceService deviceService;
    @Resource
    private AsyncService asyncService;
    @Resource
    private RedisCache redisCache;

    @ApiOperation("在线设备")
    @GetMapping("/api/device/online")
    @CrossOrigin(origins = "*")
    public R<List<String>> online() {
        TwinDevice searchDevice = new TwinDevice();
        searchDevice.setOnline("1");
        List<TwinDevice> list = deviceService.selectTwinDeviceList(searchDevice);
        List<String> devices = new ArrayList<>();
        list.forEach(d -> devices.add(d.getDeviceCode()));
        return R.success(devices);
    }

    @ApiOperation("首页统计数据")
    @GetMapping("/api/index")
    @CrossOrigin(origins = "*")
    public R<IndexData> index() {
        return R.success(redisCache.getCacheObject(CacheConstants.INDEX_CALC));
    }

    @ApiOperation("首页告警数据")
    @GetMapping("/api/alarm")
    @CrossOrigin(origins = "*")
    public R<IndexData> alarm() {
        return R.success(redisCache.getCacheObject(CacheConstants.INDEX_ALARM));
    }

    @ApiOperation("设备具体数据")
    @GetMapping("/api/query/{device}")
    @CrossOrigin(origins = "*")
    public R<Map> query(@PathVariable String device, String week) {
        TwinDevice info = deviceService.selectTwinDeviceByCode(device);
        if (info == null) {
            return R.fail("该设备未接入");
        }
        Map<String, Map<String, Object>> curr = redisCache.getCacheObject(CacheConstants.DEVICE_CURRENT);
        Map<String, Object> result = new HashMap<>(16);
        Map<String, Object> map = curr.get(device);
        if (map == null) {
            return R.fail("该设备暂无IOT数据");
        }
        if (device.startsWith("C_")) {
            float max1 = (float) map.get("Formula_data_26") == 0f ? 20000f : (float) map.get("Formula_data_26");
            float max2 = (float) map.get("Formula_data_27") == 0f ? 20000f : (float) map.get("Formula_data_27");
            float max3 = (float) map.get("Formula_data_28") == 0f ? 20000f : (float) map.get("Formula_data_28");
            float max4 = (float) map.get("Formula_data_29") == 0f ? 20000f : (float) map.get("Formula_data_29");
            float max5 = (float) map.get("Formula_data_30") == 0f ? 20000f : (float) map.get("Formula_data_30");
            int q1 = (int) map.get("Capacity_data_15");
            int q2 = (int) map.get("Capacity_data_16");
            int q3 = (int) map.get("Capacity_data_17");
            int q4 = (int) map.get("Capacity_data_18");
            int q5 = (int) map.get("Capacity_data_19");

            BigDecimal p1 = new BigDecimal(q1 * 100).divide(BigDecimal.valueOf(max1), 2, BigDecimal.ROUND_HALF_UP);
            BigDecimal p2 = new BigDecimal(q2 * 100).divide(BigDecimal.valueOf(max2), 2, BigDecimal.ROUND_HALF_UP);
            BigDecimal p3 = new BigDecimal(q3 * 100).divide(BigDecimal.valueOf(max3), 2, BigDecimal.ROUND_HALF_UP);
            BigDecimal p4 = new BigDecimal(q4 * 100).divide(BigDecimal.valueOf(max4), 2, BigDecimal.ROUND_HALF_UP);
            BigDecimal p5 = new BigDecimal(q5 * 100).divide(BigDecimal.valueOf(max5), 2, BigDecimal.ROUND_HALF_UP);


            map.put("p1", p1.floatValue() + "%");
            map.put("p2", p2.floatValue() + "%");
            map.put("p3", p3.floatValue() + "%");
            map.put("p4", p4.floatValue() + "%");
            map.put("p5", p5.floatValue() + "%");
        } else {
            int index = 10;
            int[] max = new int[index];
            float[] t = new float[index];
            float[] c = new float[index];
            int[] q = new int[index];

            for (int i = 0; i < index; i++) {
                max[i] = (int) map.get("Formula_data_" + (31 + i)) == 0 ? 20000 : (int) map.get("Formula_data_" + (31 + i));
                t[i] = BigDecimal.valueOf((float) map.get("Capacity_data_" + (71 + i))).setScale(2, RoundingMode.HALF_UP).floatValue();
                c[i] = BigDecimal.valueOf((float) map.get("Capacity_data_" + (3 + i))).setScale(2, RoundingMode.HALF_UP).floatValue();
                q[i] = (int) map.get("Capacity_data_" + (15 + i));
            }

            BigDecimal[] p = new BigDecimal[10];
            for (int i = 0; i < index; i++) {
                p[i] = new BigDecimal(q[i] * 100).divide(BigDecimal.valueOf(max[i]), 2, RoundingMode.HALF_UP);
            }

            for (int i = 0; i < 5; i++) {
                int j = i + 5;
                map.put("p" + (i + 1), String.format("A: %.2f%%&nbsp;&nbsp;&nbsp;&nbsp;B: %.2f%%", p[i].floatValue(), p[j].floatValue()));
                map.put("Capacity_data_" + (5 + i), "A: " + t[i] + "&nbsp;&nbsp;&nbsp;&nbsp;B: " + t[j]);
                map.put("Capacity_data_" + (10 + i), "A: " + c[i] + "&nbsp;&nbsp;&nbsp;&nbsp;B: " + c[j]);
                map.put("Capacity_data_" + (15 + i), "A: " + q[i] + "&nbsp;&nbsp;&nbsp;&nbsp;B: " + q[j]);
            }


        }

        result.put("data", map);
        if (week != null) {
            //7点前是属于前一生产天,所以这里直接减7小时即可
            LocalDateTime ldt = LocalDateTime.now().minusHours(7);
            //获取前面7天的数据
            LocalDate localDate = ldt.toLocalDate().minusDays(7);
            Date date = Date.from(localDate.atStartOfDay(ZoneOffset.of("+8")).toInstant());
            List<TwinCalcDay> list = twinCalcDayService.selectTwinCalcDayListByTime(date);
            List<Map<String, Object>> alarms = new ArrayList<>();
            Map<Date, List<TwinCalcDay>> stopDeviceGroup = list.stream().collect(Collectors.groupingBy(TwinCalcDay::getTime, LinkedHashMap::new, Collectors.toList()));
            for (Map.Entry<Date, List<TwinCalcDay>> entry : stopDeviceGroup.entrySet()) {
                Map<String, Object> temp = new HashMap<>(16);
                TwinCalcDay day = new TwinCalcDay(entry.getKey());
                List<TwinCalcDay> days = entry.getValue();
                day.calcDays(days);
                temp.put("time", DateUtils.parseDateToStr(entry.getKey()));
                temp.put("value", day.getAlarm());
                alarms.add(temp);
            }
            result.put("alarms", alarms);
        }
        return R.success(result);
    }


    @ApiOperation("平方米克重")
    @GetMapping("/api/gram-mass/total")
    @CrossOrigin(origins = "*")
    public R<List<GramMass>> gramMass() {
        return R.success(redisCache.getCacheObject(CacheConstants.INDEX_GRAM_MASS));
    }

    @ApiOperation("平方米克重详情")
    @GetMapping("/api/gram-mass/detail/{gramMass}")
    @CrossOrigin(origins = "*")
    public R<List<GramMassDetail>> gramMassDetail(@PathVariable Float gramMass) {
        List<GramMassDetail> list = redisCache.getCacheObject(CacheConstants.INDEX_GRAM_MASS_DETAIL);
        if (list != null) {
            list = list.stream().filter(detail -> detail.getGramMass().equals(gramMass)).collect(Collectors.toList());
            return R.success(list);
        } else {
            return R.fail();
        }
    }

    @ApiOperation("送经量")
    @GetMapping("/api/warp-run-in")
    @CrossOrigin(origins = "*")
    public R<List<WarpRunIn>> wri() {
//        List<WarpRunIn> list = redisCache.getCacheObject(CacheConstants.INDEX_WARP_RUN_IN);
        return R.success(redisCache.getCacheObject(CacheConstants.INDEX_WARP_RUN_IN));
    }

    @ApiOperation("配方统计")
    @GetMapping("/api/formula/total")
    @CrossOrigin(origins = "*")
    public R<List<FormulaTotal>> formulaTotal() {
        return R.success(redisCache.getCacheObject(CacheConstants.INDEX_FORMULA_TOTAL));
    }

    @ApiOperation("配方详情")
    @GetMapping("/api/formula/detail/{height}")
    @CrossOrigin(origins = "*")
    public R<List<FormulaDetail>> formulaDetail(@PathVariable Float height) {
        List<FormulaDetail> list = redisCache.getCacheObject(CacheConstants.INDEX_FORMULA_DETAIL);
        if (list != null) {
            list = list.stream().filter(detail -> detail.getFormula_data_15().equals(height)).collect(Collectors.toList());
            return R.success(list);
        } else {
            return R.fail();
        }
    }

    @ApiOperation("导出当前停机明细")
    @GetMapping("/api/view/stop")
    @CrossOrigin(origins = "*")
    public R<Map> viewStop(HttpServletResponse response) throws ParseException {
        String[] stopStr = {"", "停经片停机", "断纱停机", "人工停机", "断电停机", "设备故障停机", "落布米数达到停机", "叫料停机"};
        TwinDevice searchDevice = new TwinDevice();
        searchDevice.setOnline("1");
        List<TwinDevice> deviceList = deviceService.selectTwinDeviceList(searchDevice);
        Map<String, Object> result = new HashMap<>();
        Object d = redisCache.getCacheObject(CacheConstants.STOP_DETAIL);
        if (d != null) {
            List<StopDetailVO> stopList = (List<StopDetailVO>) d;
            stopList.sort(Comparator.comparing(StopDetailVO::getDeviceId));
            int[] nums = new int[7];
            String[] devices = new String[7];
            List<Map<String, Object>> detailList = new ArrayList<>();
            for (StopDetailVO vo : stopList) {
                if (!vo.getHasData()) {
                    Tools.comboStop(6, nums, devices, vo.getDeviceId());
                    continue;
                }
                if (vo.getSpeed() > 0f || vo.getStop() == 0) {
                    Tools.comboStop(0, nums, devices, vo.getDeviceId());
                } else {
                    switch (vo.getStop()) {
                        case 0:
                            break;
                        case 1:
                            Tools.comboStop(1, nums, devices, vo.getDeviceId());
                            break;
                        case 2:
                            Tools.comboStop(2, nums, devices, vo.getDeviceId());
                            break;
                        case 6:
                            Tools.comboStop(3, nums, devices, vo.getDeviceId());
                            break;
                        case 7:
                            Tools.comboStop(4, nums, devices, vo.getDeviceId());
                            break;
                        default:
                            Tools.comboStop(5, nums, devices, vo.getDeviceId());
                    }
                }

                Map<String, Object> detailMap = new HashMap<>();
                detailMap.put("device", vo.getDeviceId());
                detailMap.put("speed", vo.getSpeed());
                detailMap.put("status", vo.getStop());
                if (vo.getStop() != null && vo.getStop() <= 7) {
                    detailMap.put("remark", stopStr[vo.getStop()]);
                }

                detailList.add(detailMap);
            }
            Map<String, Object> total = new HashMap<>(16);
            total.put("n1", deviceList.size());

            for (int i = 0; i < 7; i++) {
                total.put("n" + (i + 2), nums[i]);
                total.put("d" + (i + 2), devices[i]);
            }
            result.put("total", total);
            result.put("detail", detailList);
        }
        return R.success(result);
    }
}
