package com.njcn.gather.aireport.testreport.component;

import cn.hutool.core.util.StrUtil;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;
import lombok.Data;
import org.apache.poi.ss.usermodel.DataFormatter;
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.ss.usermodel.WorkbookFactory;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.Map;

@Component
public class TestReportPointExcelParser {

    private static final String NODE_INFO_SHEET_NAME = "节点信息";

    public ParsedPoint parse(String fileName, InputStream inputStream) {
        try (Workbook workbook = WorkbookFactory.create(inputStream)) {
            Sheet sheet = workbook.getSheet(NODE_INFO_SHEET_NAME);
            if (sheet == null) {
                throw new BusinessException(CommonResponseEnum.FAIL, "原始Excel缺少节点信息sheet");
            }
            return parseNodeInfoSheet(fileName, sheet);
        } catch (BusinessException exception) {
            throw exception;
        } catch (IOException exception) {
            throw new BusinessException(CommonResponseEnum.FAIL, "读取原始Excel失败");
        } catch (Exception exception) {
            throw new BusinessException(CommonResponseEnum.FAIL, "解析原始Excel失败");
        }
    }

    private ParsedPoint parseNodeInfoSheet(String fileName, Sheet sheet) {
        Map<String, String> keyValueMap = new LinkedHashMap<String, String>();
        DataFormatter formatter = new DataFormatter();
        for (Row row : sheet) {
            short lastCellNum = row.getLastCellNum();
            if (lastCellNum < 2) {
                continue;
            }
            for (int i = 0; i < lastCellNum - 1; i++) {
                String key = trim(formatter.formatCellValue(row.getCell(i)));
                String value = trim(formatter.formatCellValue(row.getCell(i + 1)));
                if (StrUtil.isNotBlank(key) && StrUtil.isNotBlank(value) && !keyValueMap.containsKey(key)) {
                    keyValueMap.put(key, value);
                }
            }
        }

        ParsedPoint point = new ParsedPoint();
        point.setExcelAttachmentName(fileName);
        point.setSubstationName(requireAny(keyValueMap, "变电站", "厂站名称", "变电站名称"));
        point.setPointName(requireAny(keyValueMap, "监测点名称", "节点名称", "监测点"));
        point.setMonitorTime(optionalAny(keyValueMap, "监测时间", "录波时间", "开始时间"));
        point.setVoltageLevel(optionalAny(keyValueMap, "电压等级", "电压"));
        point.setPtRatio(optionalAny(keyValueMap, "PT变比", "PT"));
        point.setCtRatio(optionalAny(keyValueMap, "CT变比", "CT"));
        point.setBaseShortCircuitCapacity(optionalAny(keyValueMap, "基准短路容量"));
        point.setMinShortCircuitCapacity(optionalAny(keyValueMap, "最小短路容量"));
        point.setProtocolCapacity(optionalAny(keyValueMap, "用户协议容量"));
        point.setPowerSupplyCapacity(optionalAny(keyValueMap, "供电设备容量"));
        return point;
    }

    private String requireAny(Map<String, String> keyValueMap, String... candidateKeys) {
        String value = optionalAny(keyValueMap, candidateKeys);
        if (StrUtil.isBlank(value)) {
            throw new BusinessException(CommonResponseEnum.FAIL, "节点信息sheet缺少必要字段");
        }
        return value;
    }

    private String optionalAny(Map<String, String> keyValueMap, String... candidateKeys) {
        for (String candidateKey : candidateKeys) {
            String value = keyValueMap.get(candidateKey);
            if (StrUtil.isNotBlank(value)) {
                return value;
            }
        }
        return null;
    }

    private String trim(String value) {
        return StrUtil.trimToNull(value);
    }

    @Data
    public static class ParsedPoint {
        private String excelAttachmentName;
        private String substationName;
        private String pointName;
        private String monitorTime;
        private String voltageLevel;
        private String ptRatio;
        private String ctRatio;
        private String baseShortCircuitCapacity;
        private String minShortCircuitCapacity;
        private String protocolCapacity;
        private String powerSupplyCapacity;
    }
}
