package com.jjt.calc.controller;

import com.jjt.calc.domain.TwinCalcStop;
import com.jjt.calc.service.ITwinCalcStopService;
import com.jjt.calc.vo.StopCalcVO;
import com.jjt.calc.vo.TpsVO;
import com.jjt.common.annotation.Log;
import com.jjt.common.core.controller.BaseController;
import com.jjt.common.core.domain.AjaxResult;
import com.jjt.common.core.domain.R;
import com.jjt.common.core.page.TableDataInfo;
import com.jjt.common.enums.BusinessType;
import com.jjt.common.utils.poi.ExcelUtil;
import com.jjt.utils.Tools;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 停机数据统计Controller
 *
 * @author wukai
 * @date 2025-01-18
 */
@Api(tags = "停机数据统计")
@RestController
@RequestMapping("/calc/calcStop")
public class TwinCalcStopController extends BaseController {
    @Resource
    private ITwinCalcStopService twinCalcStopService;

    /**
     * 查询停机数据统计列表
     */
    @ApiOperation("查询停机数据统计列表")
    @PreAuthorize("@ss.hasPermi('calc:calcStop:list')")
    @GetMapping("/list")
    public TableDataInfo list(TwinCalcStop twinCalcStop) {
        startPage();
        List<TwinCalcStop> list = twinCalcStopService.selectTwinCalcStopList(twinCalcStop);
        return getDataTable(list);
    }

    @ApiOperation("停机统计")
    @GetMapping("/calc")
    public R calc(TwinCalcStop twinCalcStop) {
        List<TwinCalcStop> list = twinCalcStopService.selectTwinCalcStopList(twinCalcStop);
        Map<Integer, List<TwinCalcStop>> stopDeviceGroup = list.stream().collect(Collectors.groupingBy(TwinCalcStop::getStopType, LinkedHashMap::new, Collectors.toList()));
        int stopSize = 7;
        Integer[] stopNum = new Integer[stopSize];
        int totalNum = 0;
        //停机时间
        Long[] stopTime = new Long[stopSize];
        //设备数量
        Integer[] deviceNum = new Integer[stopSize];
        Arrays.fill(stopTime, 0L);
        AtomicReference<Long> totalTime = new AtomicReference<>(0L);
        List<TpsVO> tpsVOS = new ArrayList<>();
        for (Map.Entry<Integer, List<TwinCalcStop>> entry : stopDeviceGroup.entrySet()) {
            Integer stopType = entry.getKey();
            if (stopType > 7) {
                //目前有个 停机状态为8的，暂时屏蔽掉
                continue;
            }
            int pos = stopType - 1;
            List<TwinCalcStop> stops = entry.getValue();
            Map<Long, List<TwinCalcStop>> deviceGroup = stops.stream().collect(Collectors.groupingBy(TwinCalcStop::getDeviceId, LinkedHashMap::new, Collectors.toList()));
            stops.sort(Comparator.comparing(TwinCalcStop::getDataDate).thenComparing(TwinCalcStop::getHour));
            Map<Date, Map<Integer, List<TwinCalcStop>>> stopHourGroup = stops.stream().collect(
                    Collectors.groupingBy(TwinCalcStop::getDataDate, LinkedHashMap::new,
                            Collectors.groupingBy(TwinCalcStop::getHour, LinkedHashMap::new, Collectors.toList())));
            for (Map.Entry<Date, Map<Integer, List<TwinCalcStop>>> entry2 : stopHourGroup.entrySet()) {
                Map<Integer, List<TwinCalcStop>> map = entry2.getValue();
                for (Map.Entry<Integer, List<TwinCalcStop>> entry1 : map.entrySet()) {
                    List<TwinCalcStop> stopList = entry1.getValue();
                    TpsVO tps = new TpsVO();
                    tps.setType(stopType);
                    tps.setDate(entry2.getKey());
                    tps.setHour(entry1.getKey());
                    Map<Long, List<TwinCalcStop>> yarnDeviceGroup = stopList.stream().collect(Collectors.groupingBy(TwinCalcStop::getDeviceId, LinkedHashMap::new, Collectors.toList()));
                    tps.setTps(yarnDeviceGroup.size());
                    int num = stopList.size();
                    tps.setNum(num);
                    //0.最小，1.最大,2.总时间
                    final long[] time = {999999L, 0, 0};
                    //6.设备断纱停机详情
                    for (TwinCalcStop stop : stopList) {
                        long t = (stop.getEndTime().getTime() - stop.getStartTime().getTime()) / 1000;
                        if (t < time[0]) {
                            time[0] = t;
                        }
                        if (t > time[1]) {
                            time[1] = t;
                        }
                        time[2] += t;
                    }

                    tps.setMax(time[1]);
                    tps.setMin(time[0]);
                    BigDecimal avg = BigDecimal.valueOf(time[2]).divide(BigDecimal.valueOf(num), 2, RoundingMode.HALF_UP);
                    tps.setAvg(avg);

                    tpsVOS.add(tps);
                }
            }

            deviceNum[pos] = deviceGroup.size();
            stopNum[pos] = stops.size();
            totalNum += stops.size();
            stops.forEach(stop -> {
                long t = (stop.getEndTime().getTime() - stop.getStartTime().getTime()) / 1000;
                stopTime[pos] += t;
                totalTime.updateAndGet(v -> v + t);
            });
        }

        List<StopCalcVO> calcList = new ArrayList<>();
        for (int i = 0; i < stopNum.length; i++) {
            if (stopNum[i] == null) {
                continue;
            }
            StopCalcVO vo = new StopCalcVO();
            vo.setType(i + 1);
            vo.setNum(stopNum[i]);
            vo.setDevice(deviceNum[i]);
            vo.setTime(Tools.convertHMS(stopTime[i]));
            long avg = stopTime[i] / totalNum;
            vo.setAvgTime(Tools.convertHMS(avg));
            BigDecimal percentNum = BigDecimal.valueOf(stopNum[i]).divide(BigDecimal.valueOf(totalNum), 4, RoundingMode.HALF_UP);
            BigDecimal percentTimes = BigDecimal.valueOf(stopTime[i]).divide(BigDecimal.valueOf(totalTime.get()), 4, RoundingMode.HALF_UP);
            vo.setPercentNum(percentNum);
            vo.setPercentTimes(percentTimes);
            calcList.add(vo);
        }

        Map<String, Object> result = new HashMap<>(16);
        result.put("calc", calcList);
        result.put("tps", tpsVOS);

        return R.success(result);
    }

    /**
     * 导出停机数据统计列表
     */
    @ApiOperation("导出停机数据统计列表")
    @PreAuthorize("@ss.hasPermi('calc:calcStop:export')")
    @Log(title = "停机数据统计", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, TwinCalcStop twinCalcStop) {
        List<TwinCalcStop> list = twinCalcStopService.selectTwinCalcStopList(twinCalcStop);
        ExcelUtil<TwinCalcStop> util = new ExcelUtil<TwinCalcStop>(TwinCalcStop.class);
        util.exportExcel(response, list, "停机数据统计数据");
    }

    /**
     * 获取停机数据统计详细信息
     */
    @ApiOperation("获取停机数据统计详细信息")
    @PreAuthorize("@ss.hasPermi('calc:calcStop:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return success(twinCalcStopService.selectTwinCalcStopById(id));
    }

    /**
     * 新增停机数据统计
     */
    @ApiOperation("新增停机数据统计")
    @PreAuthorize("@ss.hasPermi('calc:calcStop:add')")
    @Log(title = "停机数据统计", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody TwinCalcStop twinCalcStop) {
        return toAjax(twinCalcStopService.insertTwinCalcStop(twinCalcStop));
    }

    /**
     * 修改停机数据统计
     */
    @ApiOperation("修改停机数据统计")
    @PreAuthorize("@ss.hasPermi('calc:calcStop:edit')")
    @Log(title = "停机数据统计", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody TwinCalcStop twinCalcStop) {
        return toAjax(twinCalcStopService.updateTwinCalcStop(twinCalcStop));
    }

    /**
     * 删除停机数据统计
     */
    @ApiOperation("删除停机数据统计")
    @PreAuthorize("@ss.hasPermi('calc:calcStop:remove')")
    @Log(title = "停机数据统计", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(twinCalcStopService.deleteTwinCalcStopByIds(ids));
    }
}
