package com.ruoyi.project.statistics.controller;

import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.project.check.domain.TCheckLawitems;
import com.ruoyi.project.check.service.ITCheckLawitemsService;
import com.ruoyi.project.statistics.domain.Statistics;
import com.ruoyi.project.statistics.service.IStatisticsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

@RestController
@RequestMapping("/statistics/statistics")
public class StatisticsController extends BaseController {

    @Autowired
    private IStatisticsService statisticsService;

    @Autowired
    private ITCheckLawitemsService tCheckLawitemsService;

    @GetMapping("/list")
    public AjaxResult list(Statistics statistics) {
        List<Statistics> resultList = new ArrayList<>();
        // 根据装查询
        List<Statistics> countPlant = statisticsService.countPlant(statistics);
        for (Statistics plant : countPlant) {
            Statistics result = new Statistics();
            setStatistics(result);
            result.setPlantName(plant.getPlantName());
            result.setPlantCount(plant.getCount());
//            统计设备数量
            Statistics countDevice = statisticsService.countDevice(plant);
            result.setDevCount(countDevice.getCount());
//            根据密封点类型统计数量
            int qyljCount = 0;//取样连接系统
            for (Statistics countPoint : statisticsService.countPoint(plant)) {
                switch (countPoint.getContent()) {
                    case "泵":
                        result.setbCount(countPoint.getCount());
                        break;
                    case "阀门":
                        result.setFmCount(countPoint.getCount());
                        break;
                    case "法兰":
                        result.setFlCount(countPoint.getCount());
                        break;
                    case "搅拌器":
                        result.setJbqCount(countPoint.getCount());
                        break;
                    case "连接件":
                        result.setLjjCount(countPoint.getCount());
                        break;
                    case "泄压设备":
                        result.setXysbCount(countPoint.getCount());
                        break;
                    case "压缩机":
                        result.setYsjCount(countPoint.getCount());
                        break;
                    case "开口阀或开口管线":
                        result.setKkfCount(countPoint.getCount());
                        break;
                    case "取样连接系统（开口取样-无残液置换、处置措施）":
                    case "取样连接系统（密闭取样-取样瓶长期与取样口连接）":
                    case "取样连接系统（开口取样-有残液置换、处置措施）":
                    case "取样连接系统（密闭取样-取样瓶不与取样口连接）":
                        qyljCount += countPoint.getCount();
                        break;
                    case "其他":
                        result.setQtCount(countPoint.getCount());
                        break;
                }
            }
            result.setQyljCount(qyljCount);
//            计算总数量
            result.setPointCount(result.getbCount() + result.getYsjCount() + result.getJbqCount() + result.getFmCount() + result.getXysbCount() + result.getLjjCount() + result.getFlCount() + result.getKkfCount() + result.getQyljCount() + result.getQtCount());
//            根据泄露程度统计
            statistics.setPlantId(plant.getPlantId());
            for (Statistics countXlcd : statisticsService.countXlcd(statistics)) {
                switch (countXlcd.getContent()) {
                    case "1":
                        result.setWxlCount(countXlcd.getCount());
                        break;
                    case "2":
                        result.setYbxlCount(countXlcd.getCount());
                        break;
                    case "3":
                        result.setYzxlCount(countXlcd.getCount());
                        break;
                }
            }
//            未检测数量统计
            result.setWjcCount((result.getPointCount() - result.getWxlCount() - result.getYbxlCount() - result.getYzxlCount()));
//            总数统记
            result.setXlcdCount(result.getPointCount());
//            查询所有检测点的净检测值
            List<Statistics> countPfl = statisticsService.countPfl(statistics);

            resultList.add(getCountValue(countPfl, result));
        }

        Statistics total = new Statistics();
        setStatistics(total);
        total.setPlantName("合计");
        for (Statistics item : resultList) {
            total.setPlantCount(item.getPlantCount() + total.getPlantCount());
            total.setDevCount(item.getDevCount() + total.getDevCount());
            total.setbCount(item.getbCount() + total.getbCount());
            total.setYsjCount(item.getYsjCount() + total.getYsjCount());
            total.setJbqCount(item.getJbqCount() + total.getJbqCount());
            total.setFmCount(item.getFmCount() + total.getFmCount());
            total.setXysbCount(item.getXysbCount() + total.getXysbCount());
            total.setLjjCount(item.getLjjCount() + total.getLjjCount());
            total.setFlCount(item.getFlCount() + total.getFlCount());
            total.setKkfCount(item.getKkfCount() + total.getKkfCount());
            total.setQyljCount(item.getQyljCount() + total.getQyljCount());
            total.setQtCount(item.getQtCount() + total.getQtCount());
            total.setPointCount(item.getPointCount() + total.getPointCount());
            total.setWxlCount(item.getWxlCount() + total.getWxlCount());
            total.setYbxlCount(item.getYbxlCount() + total.getYbxlCount());
            total.setYzxlCount(item.getYzxlCount() + total.getYzxlCount());
            total.setWjcCount(item.getWjcCount() + total.getWjcCount());
            total.setXlcdCount(item.getXlcdCount() + total.getXlcdCount());
            total.setXll(new BigDecimal(item.getXll()).add(new BigDecimal(total.getXll())).toString());
            total.setJpl(new BigDecimal(item.getJpl()).add(new BigDecimal(total.getJpl())).toString());
            total.setPfl(new BigDecimal(item.getPfl()).add(new BigDecimal(total.getPfl())).toString());
            total.setSjpfl(new BigDecimal(item.getSjpfl()).add(new BigDecimal(total.getSjpfl())).toString());
        }
        resultList.add(total);
        return AjaxResult.success(resultList);
    }

    private void setStatistics(Statistics total) {
        total.setPlantCount(0);
        total.setDevCount(0);
        total.setbCount(0);
        total.setYsjCount(0);
        total.setJbqCount(0);
        total.setFmCount(0);
        total.setXysbCount(0);
        total.setLjjCount(0);
        total.setFlCount(0);
        total.setKkfCount(0);
        total.setQyljCount(0);
        total.setQtCount(0);
        total.setPointCount(0);
        total.setWxlCount(0);
        total.setYbxlCount(0);
        total.setYzxlCount(0);
        total.setWjcCount(0);
        total.setXlcdCount(0);
        total.setXll("0");
        total.setJpl("0");
        total.setPfl("0");
        total.setSjpfl("0");
    }

    private Statistics getCountValue(List<Statistics> countPfl, Statistics result) {
        //            设置当年时间
        Calendar nc = Calendar.getInstance();//当年的1月1日
        nc.set(nc.get(Calendar.YEAR), 0, 1, 0, 0, 0);
        nc.set(Calendar.MILLISECOND, 0);//设置毫秒值为0否则会减掉 一天
        Calendar nm = Calendar.getInstance();//次年的1月1日
        nm.set(nm.get(Calendar.YEAR), 12, 1, 0, 0, 0);
        nm.set(Calendar.MILLISECOND, 0);//设置毫秒值为0否则会减掉 一天
        double zpfl = 0;//初始排放量
        double sjpfl = 0;//实际排放量
        double zxll = 0;//总泄漏量
        long pid = 0;
        double temp = 0;
        Map<String, String> testValues = getTestValue();
        for (int i = 0; i < countPfl.size(); i++) {
            Statistics point = countPfl.get(i);
            double netTestValue = Double.parseDouble(point.getNetTestValue());
            if (netTestValue < Integer.parseInt(testValues.get(point.getPointType()))) {
                if (i == 0 || !Objects.equals(countPfl.get(i - 1).getPointId(), point.getPointId())) {//如果是第一条||前一条和当前这条不是是同一个点
                    sjpfl += getETOC(netTestValue, point.getPointType()) * DateUtils.differentDaysByMillisecond(nc.getTime(), point.getCheckDate()) * 24;
                } else if (Objects.equals(countPfl.get(i - 1).getPointId(), point.getPointId())) {//如果前一条和当前这条是同一个点
                    if (new BigDecimal(countPfl.get(i - 1).getNetTestValue()).compareTo(new BigDecimal(Integer.parseInt(testValues.get(point.getPointType())))) < 0) { // 如果前一条检测值小于泄漏标准
                        sjpfl += getETOC(netTestValue, point.getPointType()) * DateUtils.differentDaysByMillisecond(point.getCheckDate(), countPfl.get(i - 1).getCheckDate()) * 24;
                    }
                }
                if (i + 1 == countPfl.size() || !Objects.equals(countPfl.get(i + 1).getPointId(), point.getPointId())) {//如果下一条和当前这条不是同一个点
                    sjpfl += getETOC(netTestValue, point.getPointType()) * (DateUtils.differentDaysByMillisecond(nm.getTime(), point.getCheckDate())) * 24;
                }
            } else {
                if (i == 0 || !Objects.equals(countPfl.get(i - 1).getPointId(), point.getPointId())) {//如果是第一条||前一条和当前这条不是是同一个点
                    sjpfl += getETOC(netTestValue, point.getPointType()) * DateUtils.differentDaysByMillisecond(nc.getTime(), point.getCheckDate()) * 24;
                } else if (Objects.equals(countPfl.get(i - 1).getPointId(), point.getPointId())) {//如果前一条和当前这条是同一个点
                    sjpfl += getETOC(netTestValue, point.getPointType()) * DateUtils.differentDaysByMillisecond(point.getCheckDate(), countPfl.get(i - 1).getCheckDate()) * 24;
                }
                if (i + 1 == countPfl.size() || !Objects.equals(countPfl.get(i + 1).getPointId(), point.getPointId())) {//如果下一条和当前这条不是同一个点
                    sjpfl += getETOC(netTestValue, point.getPointType()) * (DateUtils.differentDaysByMillisecond(nm.getTime(), point.getCheckDate())) * 24;
                } else {
                    sjpfl += getETOC(netTestValue, point.getPointType()) * (DateUtils.differentDaysByMillisecond(countPfl.get(i + 1).getCheckDate(), point.getCheckDate())) * 24;
                }
            }
            if (pid == point.getPointId()) {
                continue;
            }
            if (netTestValue >= Integer.parseInt(testValues.get(point.getPointType()))) {
                pid = point.getPointId();
                if (i == 0 || !Objects.equals(countPfl.get(i - 1).getPointId(), point.getPointId())) {//如果是第一条||前一条和当前这条不是是同一个点
                    double pfl = getETOC(netTestValue, point.getPointType()) * DateUtils.differentDaysByMillisecond(nc.getTime(), nm.getTime()) * 24;
                    zxll += pfl;
                    zpfl += pfl;
                } else {
                    double pfl = getETOC(netTestValue, point.getPointType()) * DateUtils.differentDaysByMillisecond(countPfl.get(i - 1).getCheckDate(), nm.getTime()) * 24;
                    zxll += pfl + (zpfl - temp);
                    zpfl += pfl;
                    temp = 0;
                }
            } else {
                if (i == 0 || !Objects.equals(countPfl.get(i - 1).getPointId(), point.getPointId())) {//如果是第一条||前一条和当前这条不是是同一个点
                    temp = zpfl;
                    zpfl += getETOC(netTestValue, point.getPointType()) * DateUtils.differentDaysByMillisecond(nc.getTime(), point.getCheckDate()) * 24;
                } else if (Objects.equals(countPfl.get(i - 1).getPointId(), point.getPointId())) {//如果前一条和当前这条是同一个点
                    zpfl += getETOC(netTestValue, point.getPointType()) * DateUtils.differentDaysByMillisecond(point.getCheckDate(), countPfl.get(i - 1).getCheckDate()) * 24;
                }
                if (i + 1 == countPfl.size() || !Objects.equals(countPfl.get(i + 1).getPointId(), point.getPointId())) {//如果下一条和当前这条不是同一个点
                    zpfl += getETOC(netTestValue, point.getPointType()) * (DateUtils.differentDaysByMillisecond(nm.getTime(), point.getCheckDate())) * 24;
                }
            }
        }
        // 排放量(t/年)
        result.setPfl(new BigDecimal(String.valueOf(zpfl)).divide(new BigDecimal("1000"), 4, RoundingMode.HALF_UP).stripTrailingZeros().toString());
        // 泄漏量(t/年)
        result.setXll(new BigDecimal(String.valueOf(zxll)).divide(new BigDecimal("1000"), 4, RoundingMode.HALF_UP).stripTrailingZeros().toString());
        // 减排量(t/年)
        result.setJpl(new BigDecimal(String.valueOf(zpfl - sjpfl)).divide(new BigDecimal("1000"), 4, RoundingMode.HALF_UP).stripTrailingZeros().toString());
        result.setSjpfl(new BigDecimal(String.valueOf(sjpfl)).divide(new BigDecimal("1000"), 4, RoundingMode.HALF_UP).stripTrailingZeros().toString());
        return result;
    }

    @GetMapping("/xlcdByPoint")
    public AjaxResult xlcdByPoint(Statistics statistics) {
        Map<String, Statistics> map = new HashMap<>();
        List<Statistics> xlcdByPoint = statisticsService.countXlcdByPoint(statistics);
        Statistics result = null;
        for (Statistics point : xlcdByPoint) {
            String pointType = point.getPointType();
            if (pointType.contains("取样连接系统")) {
                pointType = "取样连接系统";
            }
            Integer count = point.getCount();
            if (map.get(pointType) == null) {
                result = new Statistics();
            }
            switch (point.getContent()) {
                case "1":
                    result.setWxlCount(count);
                    break;
                case "2":
                    result.setYbxlCount(count);
                    break;
                case "3":
                    result.setYzxlCount(count);
                    break;
            }
            result.setPointType(pointType);
            map.put(pointType, result);
        }
        return AjaxResult.success(map.values());
    }

    @GetMapping("/pflByPoint")
    public AjaxResult pflByPoint(Statistics statistics) {
        List<Statistics> resultList = new ArrayList<>();
        // 根据装查询
        List<Statistics> countPlant = statisticsService.countPlant(statistics);
        Map<String, String> testValues = getTestValue();
        for (Statistics plant : countPlant) {

            statistics.setPlantId(plant.getPlantId());
            List<Statistics> countPfl = statisticsService.countPfl(statistics);

            // 设置当年时间
            Calendar nc = Calendar.getInstance();//当年的1月1日
            nc.set(nc.get(Calendar.YEAR), 0, 1, 0, 0, 0);
            nc.set(Calendar.MILLISECOND, 0);//设置毫秒值为0否则会减掉 一天
            Calendar nm = Calendar.getInstance();//次年的1月1日
            nm.set(nm.get(Calendar.YEAR), 12, 1, 0, 0, 0);
            nm.set(Calendar.MILLISECOND, 0);//设置毫秒值为0否则会减掉 一天
            Statistics result = null;
            double zpfl = 0;//初始排放量
            double sjpfl = 0;//实际排放量
            double zxll = 0;//总泄漏量
            long pid = 0;
            double temp = 0;
            for (int i = 0; i < countPfl.size(); i++) {
                Statistics item = countPfl.get(i);
                //如果是第一条或者下一条的密封点类型和当前的密封点类型不一致
                if (i == 0 || !countPfl.get(i).getPointType().equals(result.getPointType())) {
                    result = new Statistics();
                    result.setPointType(item.getPointType());
                    zpfl = 0;//初始排放量
                    sjpfl = 0;//实际排放量
                    zxll = 0;//总泄漏量
                }
                result.setPlantName(plant.getPlantName());
                double netTestValue = Double.parseDouble(item.getNetTestValue());
                if (netTestValue < Integer.parseInt(testValues.get(item.getPointType()))) {
                    if (i == 0 || !Objects.equals(countPfl.get(i - 1).getPointId(), item.getPointId())) {//如果是第一条||前一条和当前这条不是是同一个点
                        sjpfl += getETOC(netTestValue, item.getPointType()) * DateUtils.differentDaysByMillisecond(nc.getTime(), item.getCheckDate()) * 24;
                    } else if (Objects.equals(countPfl.get(i - 1).getPointId(), item.getPointId())) {//如果前一条和当前这条是同一个点
                        if (new BigDecimal(countPfl.get(i - 1).getNetTestValue()).compareTo(new BigDecimal(Integer.parseInt(testValues.get(item.getPointType())))) < 0) { // 如果前一条检测值小于泄漏标准
                            sjpfl += getETOC(netTestValue, item.getPointType()) * DateUtils.differentDaysByMillisecond(item.getCheckDate(), countPfl.get(i - 1).getCheckDate()) * 24;
                        }
                    }
                    if (i + 1 == countPfl.size() || !Objects.equals(countPfl.get(i + 1).getPointId(), item.getPointId())) {//如果下一条和当前这条不是同一个点
                        sjpfl += getETOC(netTestValue, item.getPointType()) * (DateUtils.differentDaysByMillisecond(nm.getTime(), item.getCheckDate())) * 24;
                    }
                } else {
                    if (i == 0 || !Objects.equals(countPfl.get(i - 1).getPointId(), item.getPointId())) {//如果是第一条||前一条和当前这条不是是同一个点
                        sjpfl += getETOC(netTestValue, item.getPointType()) * DateUtils.differentDaysByMillisecond(nc.getTime(), item.getCheckDate()) * 24;
                    } else if (Objects.equals(countPfl.get(i - 1).getPointId(), item.getPointId())) {//如果前一条和当前这条是同一个点
                        sjpfl += getETOC(netTestValue, item.getPointType()) * DateUtils.differentDaysByMillisecond(item.getCheckDate(), countPfl.get(i - 1).getCheckDate()) * 24;
                    }
                    if (i + 1 == countPfl.size() || !Objects.equals(countPfl.get(i + 1).getPointId(), item.getPointId())) {//如果下一条和当前这条不是同一个点
                        sjpfl += getETOC(netTestValue, item.getPointType()) * (DateUtils.differentDaysByMillisecond(nm.getTime(), item.getCheckDate())) * 24;
                    } else {
                        sjpfl += getETOC(netTestValue, item.getPointType()) * (DateUtils.differentDaysByMillisecond(countPfl.get(i + 1).getCheckDate(), item.getCheckDate())) * 24;
                    }
                }
                if (pid == item.getPointId()) {
                    if (i != 0 && (i + 1 == countPfl.size() || !countPfl.get(i + 1).getPointType().equals(item.getPointType()))) {
                        // 排放量(t/年)
                        result.setPfl(new BigDecimal(String.valueOf(zpfl)).divide(new BigDecimal("1000"), 8, RoundingMode.HALF_UP).stripTrailingZeros().toString());
                        // 泄漏量(t/年)
                        result.setXll(new BigDecimal(String.valueOf(zxll)).divide(new BigDecimal("1000"), 8, RoundingMode.HALF_UP).stripTrailingZeros().toString());
                        // 减排量(t/年)
                        result.setJpl(new BigDecimal(String.valueOf(zpfl - sjpfl)).divide(new BigDecimal("1000"), 8, RoundingMode.HALF_UP).stripTrailingZeros().toString());
                        resultList.add(result);
                    }
                    continue;
                }
                if (netTestValue >= Integer.parseInt(testValues.get(item.getPointType()))) {
                    pid = item.getPointId();
                    if (i == 0 || !Objects.equals(countPfl.get(i - 1).getPointId(), item.getPointId())) {//如果是第一条||前一条和当前这条不是是同一个点
                        double pfl = getETOC(netTestValue, item.getPointType()) * DateUtils.differentDaysByMillisecond(nc.getTime(), nm.getTime()) * 24;
                        zxll += pfl;
                        zpfl += pfl;
                    } else {
                        double pfl = getETOC(netTestValue, item.getPointType()) * DateUtils.differentDaysByMillisecond(countPfl.get(i - 1).getCheckDate(), nm.getTime()) * 24;
                        zxll += pfl + (zpfl - temp);
                        zpfl += pfl;
                        temp = 0;
                    }
                } else {
                    if (i == 0 || !Objects.equals(countPfl.get(i - 1).getPointId(), item.getPointId())) {//如果是第一条||前一条和当前这条不是是同一个点
                        temp = zpfl;
                        zpfl += getETOC(netTestValue, item.getPointType()) * DateUtils.differentDaysByMillisecond(nc.getTime(), item.getCheckDate()) * 24;
                    } else if (Objects.equals(countPfl.get(i - 1).getPointId(), item.getPointId())) {//如果前一条和当前这条是同一个点
                        zpfl += getETOC(netTestValue, item.getPointType()) * DateUtils.differentDaysByMillisecond(item.getCheckDate(), countPfl.get(i - 1).getCheckDate()) * 24;
                    }
                    if (i + 1 == countPfl.size() || !Objects.equals(countPfl.get(i + 1).getPointId(), item.getPointId())) {//如果下一条和当前这条不是同一个点
                        zpfl += getETOC(netTestValue, item.getPointType()) * (DateUtils.differentDaysByMillisecond(nm.getTime(), item.getCheckDate())) * 24;
                    }
                }
                if (i != 0 && (i + 1 == countPfl.size() || !countPfl.get(i + 1).getPointType().equals(item.getPointType()))) {
                    // 排放量(t/年)
                    result.setPfl(new BigDecimal(String.valueOf(zpfl)).divide(new BigDecimal("1000"), 8, RoundingMode.HALF_UP).stripTrailingZeros().toString());
                    // 泄漏量(t/年)
                    result.setXll(new BigDecimal(String.valueOf(zxll)).divide(new BigDecimal("1000"), 8, RoundingMode.HALF_UP).stripTrailingZeros().toString());
                    // 减排量(t/年)
                    result.setJpl(new BigDecimal(String.valueOf(zpfl - sjpfl)).divide(new BigDecimal("1000"), 8, RoundingMode.HALF_UP).stripTrailingZeros().toString());
                    resultList.add(result);
                }
            }
        }
        return AjaxResult.success(resultList);
    }

    /**
     * 计算排放速率（kg/h）
     *
     * @param netTestValue
     * @param pointType
     * @return
     */
    public double getETOC(double netTestValue, String pointType) {
        switch (pointType) {
            case "泵":
                if (netTestValue < 1) {
                    return 2.4 * Math.pow(10, -5);
                } else if (netTestValue >= 1 && netTestValue < 50000) {
                    return 5.03 * Math.pow(10, -5) * Math.pow(netTestValue, 0.61);
                } else {
                    return 0.16;
                }
            case "阀门":
                if (netTestValue < 1) {
                    return 7.8 * Math.pow(10, -6);
                } else if (netTestValue >= 1 && netTestValue < 50000) {
                    return 2.29 * Math.pow(10, -6) * Math.pow(netTestValue, 0.746);
                } else {
                    return 0.14;
                }
            case "法兰":
                if (netTestValue < 1) {
                    return 3.1 * Math.pow(10, -7);
                } else if (netTestValue >= 1 && netTestValue < 50000) {
                    return 4.61 * Math.pow(10, -6) * Math.pow(netTestValue, 0.703);
                } else {
                    return 0.084;
                }
            case "连接件":
                if (netTestValue < 1) {
                    return 7.5 * Math.pow(10, -6);
                } else if (netTestValue >= 1 && netTestValue < 50000) {
                    return 1.53 * Math.pow(10, -6) * Math.pow(netTestValue, 0.735);
                } else {
                    return 0.03;
                }
            case "开口阀或开口管线":
                if (netTestValue < 1) {
                    return 2 * Math.pow(10, -6);
                } else if (netTestValue >= 1 && netTestValue < 50000) {
                    return 2.2 * Math.pow(10, -6) * Math.pow(netTestValue, 0.704);
                } else {
                    return 0.079;
                }
            default://其他
                if (netTestValue < 1) {
                    return 4 * Math.pow(10, -6);
                } else if (netTestValue >= 1 && netTestValue < 50000) {
                    return 1.36 * Math.pow(10, -5) * Math.pow(netTestValue, 0.589);
                } else {
                    return 0.11;
                }
        }
    }

    private Map<String, String> getTestValue() {
        Map<String, String> map = new HashMap<>();
        List<TCheckLawitems> tCheckLawitems = tCheckLawitemsService.selectTCheckLawitemsByLawStatus();
        for (TCheckLawitems lawitem : tCheckLawitems) {
            map.put(lawitem.getPointType(), lawitem.getGeneral());
        }
        return map;
    }
}
