package com.xydl.cac.excel;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.xydl.cac.entity.*;
import com.xydl.cac.entity.constants.Constants;
import com.xydl.cac.repository.ModevTypePointRepository;
import com.xydl.cac.service.NSensorService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.stream.Collectors;

import static com.xydl.cac.entity.constants.Constants.YaoCe;
import static com.xydl.cac.entity.constants.Constants.YaoXin;

public class CacExcelListener extends AnalysisEventListener<CacLine> {

    NSensorService sensorService;
    ModevTypePointRepository typePointRepository;
    HashMap<String, ModevType> typeMap = new HashMap<>();
    int base = 16385;
    int type;
    LinkedHashMap<String, NSensor> sensorList = new LinkedHashMap<>();
    List<String> errorList = new ArrayList<>();
    HashMap<String, String> doneMap = new HashMap<>();

    public CacExcelListener(NSensorService service, ModevTypePointRepository pointRepository,
                            List<ModevType> modevTypeList) {
        sensorService = service;
        typePointRepository = pointRepository;
        for (ModevType type : modevTypeList) {
            typeMap.put(type.getTablename(), type);
        }
    }

    @Override
    public void invoke(CacLine line, AnalysisContext analysisContext) {
        int rowidx = analysisContext.readRowHolder().getRowIndex();
        if (rowidx > 1) {
            if (line.getPointId().contains("遥测")) {
                type = YaoCe;
            } else if (line.getPointId().contains("遥信")) {
                type = YaoXin;
            } else {
                processLine(line, rowidx + 1);
            }
        }

    }

    private void processLine(CacLine line, int row) {
        if (StringUtils.isNotBlank(line.getSensorCode()) && StringUtils.isNotBlank(line.getField())) {
            NSensor sensor = sensorList.get(line.getSensorCode());
            if (sensor == null) {
                sensor = new NSensor();
                sensor.setSensorCode(line.getSensorCode());

                if (StringUtils.isBlank(line.getEquipmentCode())) {
                    errorList.add("第" + row + "行的被监测设备的唯一标识不能为空");
                }
                sensor.setEquipmentId(line.getEquipmentCode());
                if (StringUtils.isBlank(line.getTableName())) {
                    errorList.add("第" + row + "行的表名不能为空");
                } else {

                    ModevType modevType = typeMap.get(line.getTableName());
                    if (modevType == null) {
                        if (!doneMap.containsKey(line.getTableName())) {
                            errorList.add("第" + row + "行的表名" + line.getTableName() + "未找到对应的监测设备类型");
                            doneMap.put(line.getTableName(), "done");
                        }
                    } else {
                        sensor.setTypeId(modevType.getId());
                    }
                }
                sensor.setTableName(line.getTableName());
                if (StringUtils.isBlank(line.getDevid())) {
                    errorList.add("第" + row + "行的装置ID不能为空");
                } else {
                    try {
                        sensor.setDevId(Integer.parseInt(line.getDevid()));
                    } catch (Exception ignore) {
                        errorList.add("第" + row + "行的装置ID不是正确的数字类型");
                    }
                }

                if (StringUtils.isNotBlank(line.getParentName()) && StringUtils.isNotBlank(line.getShortName())) {
                    sensor.setName(line.getParentName() + line.getShortName());
                } else {
                    sensor.setName(line.getLongName());
                }
                sensor.setPhase(line.getPhase());
                sensor.setStatus(Constants.NORMAL);

                N103Sensor n103Sensor = new N103Sensor();
                sensor.setN103Sensor(n103Sensor);
                if (StringUtils.isNotBlank(line.getGrpNo())) {
                    try {
                        n103Sensor.setGrpNo(Integer.parseInt(line.getGrpNo()));
                    } catch (Exception ignore) {
                        errorList.add("第" + row + "行的组号不是正确的数字类型");
                    }
                }
                sensorList.put(line.getSensorCode(), sensor);
            }


            Integer pointId = Integer.parseInt(line.getPointId()) + base;
            if (StringUtils.isBlank(line.getField())) {
                errorList.add("第" + row + "行的字段名不能为空");
            }
            NPoint point = NPoint.builder()
                    .pointId(pointId)
                    .field(line.getField())
                    .fieldDesc(line.getFieldDesc())
                    .type(type)
                    .row(row)
                    .build();
            N103Point n103Point = N103Point.builder()
                    .sadr(line.getPointId())
                    .itemNo(line.getItemNo())
                    .paramindex(line.getParamindex())
                    .partName(line.getShortName())
                    .build();
            point.setN103Point(n103Point);
            String err = sensor.addPoint(point);
            if (StringUtils.isNotBlank(err)) {
                errorList.add(err);
            }
            if (type == YaoCe) {
                ModevType modevType = typeMap.get(line.getTableName());
                if (modevType != null) {
                    String key = modevType.getTablename() + point.getField();
                    if (!doneMap.containsKey(key)) {
                        List<ModevTypePoint> list = typePointRepository.findByModevtypeIdAndField(modevType.getId(), point.getField());
                        if (CollectionUtils.isEmpty(list)) {
                            errorList.add("第" + row + "行的字段" + point.getField() + "需要到监测设备类型(" + modevType.getMc() + ")" + modevType.getTablename() + "下增加相同的属性点配置");
                        }
                        doneMap.put(key, "done");
                    }
                }
            }
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        if (errorList.size() > 0) {
            String msg = errorList.stream().collect(Collectors.joining(","));
            throw new RuntimeException(msg);
        } else {
            sensorService.importFrom(sensorList.values());
        }
    }
}
