package com.njcn.gather.result.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.njcn.gather.detection.pojo.enums.DetectionCodeEnum;
import com.njcn.gather.detection.pojo.vo.DetectionData;
import com.njcn.gather.report.pojo.enums.ItemReportKeyEnum;
import com.njcn.gather.storage.pojo.po.SimAndDigNonHarmonicResult;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
 * 基波相位报告结果行装配：云南模板以电压相角为 0 度基准，取 I1A 的 A/B/C 三相电流相角填表。
 */
public final class AngleResultAssembler {

    private AngleResultAssembler() {
    }

    public static List<Map<String, String>> assembleRows(List<SimAndDigNonHarmonicResult> results) {
        List<Map<String, String>> rows = new ArrayList<>();
        if (CollUtil.isEmpty(results)) {
            return rows;
        }
        Map<Integer, List<SimAndDigNonHarmonicResult>> bySort = results.stream()
                .filter(result -> result.getSort() != null)
                .collect(Collectors.groupingBy(SimAndDigNonHarmonicResult::getSort, TreeMap::new, Collectors.toList()));
        for (List<SimAndDigNonHarmonicResult> sameSortResults : bySort.values()) {
            SimAndDigNonHarmonicResult currentAngle = firstCurrentAngle(sameSortResults);
            if (currentAngle == null) {
                continue;
            }
            DetectionData[] phases = phases(currentAngle);
            DetectionData primary = firstPresent(phases);
            if (primary == null) {
                continue;
            }
            Map<String, String> row = defaultAngleRow();
            row.put(ItemReportKeyEnum.STANDARD.getKey(), valueOrSlash(primary.getResultData()));
            putPhaseDetails(row, phases);
            row.put(ItemReportKeyEnum.ERROR_SCOPE.getKey(), errorScope(primary));
            row.put(ItemReportKeyEnum.RESULT.getKey(), overallResult(phases));
            rows.add(row);
        }
        return rows;
    }

    private static SimAndDigNonHarmonicResult firstCurrentAngle(List<SimAndDigNonHarmonicResult> results) {
        if (CollUtil.isEmpty(results)) {
            return null;
        }
        for (SimAndDigNonHarmonicResult result : results) {
            if (DetectionCodeEnum.I1A.getCode().equalsIgnoreCase(result.getAdType())) {
                return result;
            }
        }
        return null;
    }

    private static Map<String, String> defaultAngleRow() {
        Map<String, String> row = new LinkedHashMap<>();
        for (ItemReportKeyEnum key : Arrays.asList(
                ItemReportKeyEnum.STANDARD,
                ItemReportKeyEnum.TEST_A,
                ItemReportKeyEnum.TEST_B,
                ItemReportKeyEnum.TEST_C,
                ItemReportKeyEnum.ERROR_A,
                ItemReportKeyEnum.ERROR_B,
                ItemReportKeyEnum.ERROR_C,
                ItemReportKeyEnum.ERROR_SCOPE,
                ItemReportKeyEnum.RESULT,
                ItemReportKeyEnum.RESULT_A,
                ItemReportKeyEnum.RESULT_B,
                ItemReportKeyEnum.RESULT_C)) {
            row.put(key.getKey(), "/");
        }
        return row;
    }

    private static DetectionData[] phases(SimAndDigNonHarmonicResult result) {
        return new DetectionData[]{
                parse(result.getAValue()),
                parse(result.getBValue()),
                parse(result.getCValue())
        };
    }

    private static void putPhaseDetails(Map<String, String> row, DetectionData[] phases) {
        List<String> tests = Arrays.asList(ItemReportKeyEnum.TEST_A.getKey(),
                ItemReportKeyEnum.TEST_B.getKey(), ItemReportKeyEnum.TEST_C.getKey());
        List<String> errors = Arrays.asList(ItemReportKeyEnum.ERROR_A.getKey(),
                ItemReportKeyEnum.ERROR_B.getKey(), ItemReportKeyEnum.ERROR_C.getKey());
        List<String> results = Arrays.asList(ItemReportKeyEnum.RESULT_A.getKey(),
                ItemReportKeyEnum.RESULT_B.getKey(), ItemReportKeyEnum.RESULT_C.getKey());
        for (int i = 0; i < phases.length; i++) {
            DetectionData phase = phases[i];
            row.put(tests.get(i), phase == null ? "/" : valueOrSlash(phase.getData()));
            row.put(errors.get(i), phase == null || phase.getErrorData() == null ? "/" : format(phase.getErrorData()));
            row.put(results.get(i), phase == null ? "/" : resultText(phase.getIsData()));
        }
    }

    private static DetectionData firstPresent(DetectionData[] values) {
        for (DetectionData value : values) {
            if (value != null) {
                return value;
            }
        }
        return null;
    }

    private static DetectionData parse(String value) {
        if (StrUtil.isBlank(value)) {
            return null;
        }
        return JSONUtil.toBean(value, DetectionData.class);
    }

    private static String overallResult(DetectionData[] phases) {
        boolean hasResult = false;
        for (DetectionData phase : phases) {
            if (phase == null || phase.getIsData() == null) {
                continue;
            }
            hasResult = true;
            if (phase.getIsData() == 2) {
                return "不合格";
            }
        }
        return hasResult ? "合格" : "/";
    }

    private static String resultText(Integer isData) {
        if (isData == null) {
            return "/";
        }
        if (isData == 1) {
            return "合格";
        }
        if (isData == 2) {
            return "不合格";
        }
        return "/";
    }

    private static String errorScope(DetectionData primary) {
        String scope = dealErrorScope(primary.getRadius());
        if (StrUtil.isNotBlank(primary.getUnit()) && !"/".equals(scope)) {
            return scope + primary.getUnit();
        }
        return scope;
    }

    private static String dealErrorScope(String errorScope) {
        if (StrUtil.isBlank(errorScope)) {
            return "/";
        }
        if (errorScope.contains("~")) {
            String[] split = errorScope.split("~");
            String begin = split[0];
            if (begin.startsWith("-")) {
                begin = begin.substring(1);
            }
            if (split.length > 1 && split[1].equalsIgnoreCase(begin)) {
                return "±" + begin;
            }
        }
        return errorScope;
    }

    private static String valueOrSlash(Double value) {
        return value == null ? "/" : format(value);
    }

    private static String format(Double value) {
        return value == null ? "/" : BigDecimal.valueOf(value).setScale(4, RoundingMode.HALF_UP).toPlainString();
    }

    private static String format(BigDecimal value) {
        return value == null ? "/" : value.setScale(4, RoundingMode.HALF_UP).toPlainString();
    }
}
