package jnpf.util;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.ImmutableList;
import jnpf.constant.MsgCode;
import jnpf.enums.*;
import jnpf.enums.UniverDataEnum;
import jnpf.exception.DataException;
import jnpf.model.DataQuery;
import jnpf.model.DataSortModel;
import jnpf.univer.chart.UniverChartModel;
import jnpf.univer.data.cell.UniverDataConfig;
import jnpf.univer.data.custom.UniverCustom;
import jnpf.univer.data.resource.UniverDrawing;
import jnpf.univer.model.UniverPreview;
import jnpf.univer.model.UniverWorkBook;
import jnpf.univer.resources.*;
import jnpf.univer.sheet.*;
import jnpf.ureport.build.Dataset;
import jnpf.ureport.build.ReportBuilder;
import jnpf.ureport.cell.down.DownCellbuilder;
import jnpf.ureport.cell.right.RightCellbuilder;
import jnpf.ureport.definition.*;
import jnpf.ureport.definition.value.*;
import jnpf.ureport.model.*;
import jnpf.ureport.utils.DataUtils;
import jnpf.util.type.SortType;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * @author ：JNPF开发平台组
 * @version: V3.1.0
 * @copyright 引迈信息技术有限公司
 * @date ：2024/5/11 下午4:35
 */
public class UniverConvert {


    //-------------------------------------解析数据------------------------------------------------

    public UniverPreview transform(String snapshot, String cells, String sort, Map<String, Map<String, List<Map<String, Object>>>> sheetData) {
        UniverWorkBook univerWorkBook = StringUtil.isNotEmpty(snapshot) ? JsonUtil.getJsonToBean(snapshot, UniverWorkBook.class) : new UniverWorkBook();
        UniverCustom custom = StringUtil.isNotEmpty(cells) ? JsonUtil.getJsonToBean(cells, UniverCustom.class) : new UniverCustom();
        List<DataQuery> sortListAll = StringUtil.isNotEmpty(sort) ? JsonUtil.getJsonToList(sort, DataQuery.class) : new ArrayList<>();
        //排序
        Map<String, Map<String, List<DataSortModel>>> sortMap = new HashMap<>();
        for (DataQuery dataQuery : sortListAll) {
            String sheetId = dataQuery.getSheet();
            Map<String, List<DataSortModel>> dataBaseMap = sortMap.get(sheetId) != null ? sortMap.get(sheetId) : new HashMap<>();
            List<DataSortModel> sortList = dataQuery.getSortList();
            for (DataSortModel dataModel : sortList) {
                DataSortModel sortModel = JsonUtil.getJsonToBean(dataModel, DataSortModel.class);
                String[] params = sortModel.getVModel().split("\\.");
                if (params.length == 2) {
                    String datasetName = params[0];
                    String property = params[1];
                    sortModel.setVModel(property);
                    List<DataSortModel> dataSortModels = dataBaseMap.get(datasetName) != null ? dataBaseMap.get(datasetName) : new ArrayList<>();
                    dataSortModels.add(sortModel);
                    dataBaseMap.put(datasetName, dataSortModels);
                }
            }
            sortMap.put(sheetId, dataBaseMap);
        }
        //图表
        Map<String, UniverDataConfig> floatEcharts = custom.getFloatEcharts();
        List<UniverResource> resources = univerWorkBook.getResources();
        Map<String, List<UniverDataConfig>> echartMap = drawing(resources, floatEcharts);
        List<UniverSheet> sheetList = new ArrayList<>();
        List<UniverChartModel> chartList = new ArrayList<>();
        for (String sheetOrder : univerWorkBook.getSheetOrder()) {
            UniverSheet univerSheet = univerWorkBook.getSheets().get(sheetOrder);
            Map<String, List<Map<String, Object>>> dataList = sheetData.get(sheetOrder) != null ? sheetData.get(sheetOrder) : new HashMap<>();
            Map<String, List<DataSortModel>> sortDataMap = sortMap.get(sheetOrder) != null ? sortMap.get(sheetOrder) : new HashMap<>();
            if (ObjectUtil.isNotEmpty(univerSheet)) {
                List<UniverDataConfig> cellList = custom.getCells().stream().filter(t -> Objects.equals(sheetOrder, t.getSheet())).collect(Collectors.toList());
                UniverSheet sheet = buildLuckySheetDate(univerSheet, cellList, dataList, sortDataMap, resources);
                List<UniverDataConfig> echartsList = echartMap.get(sheetOrder) != null ? echartMap.get(sheetOrder) : new ArrayList<>();
                ChartUtil.chart(chartList, dataList, echartsList);
                sheetList.add(sheet);
            }
        }
        Map<String, UniverSheet> sheet = sheetList.stream().collect(Collectors.toMap(UniverSheet::getId, Function.identity()));
        univerWorkBook.setSheets(sheet);
        UniverPreview vo = new UniverPreview();
        vo.setSnapshot(JSONUtil.toJsonStr(univerWorkBook));
        vo.setCells(cells);

        vo.setChartData(JSONUtil.toJsonStr(chartList));
        return vo;
    }

    private UniverSheet buildLuckySheetDate(UniverSheet sheet, List<UniverDataConfig> cell, Map<String, List<Map<String, Object>>> sheetDataMap, Map<String, List<DataSortModel>> sortDataMap, List<UniverResource> resources) {
        List<UniverDataConfig> datasourceData = cell.stream().filter(t -> CellDataEnum.dataSource.name().equals(t.getType())).collect(Collectors.toList());
        if (datasourceData.isEmpty()) {
            return sheet;
        }
        //处理数据
        Map<String, List<Map<String, Object>>> dataList = new HashMap<>();
        for (String key : sheetDataMap.keySet()) {
            List<Map<String, Object>> list = sheetDataMap.get(key) != null ? sheetDataMap.get(key) : new ArrayList<>();
            List<DataSortModel> dataSortList = sortDataMap.get(key) != null ? sortDataMap.get(key) : new ArrayList<>();
            StringJoiner joiner = new StringJoiner(",");
            for (DataSortModel dataSortModel : dataSortList) {
                String vModel = dataSortModel.getVModel();
                boolean isDesc = Objects.equals(SortType.DESC, dataSortModel.getType());
                joiner.add((isDesc ? "-" : "") + vModel);
            }
            List<Map<String, Object>> data = DataUtils.orderDataList(list, joiner.toString());
            dataList.put(key, data);
        }
        List<Integer> rowMax = new ArrayList<>();
        rowMax.add(0);
        List<Integer> columnMax = new ArrayList<>();
        columnMax.add(0);
        Map<Integer, Map<Integer, UniverSheetCellData>> cellData = sheet.getCellData();
        for (Integer rowKey : cellData.keySet()) {
            rowMax.add(rowKey);
            Map<Integer, UniverSheetCellData> cellDataMap = cellData.get(rowKey);
            columnMax.addAll(cellDataMap.keySet());
        }
        List<UniverSheetRange> mergeData = sheet.getMergeData();
        Map<Integer, UniverSheetRowData> sheetRowData = sheet.getRowData();
        Map<Integer, UniverSheetColumnData> sheetColumnData = sheet.getColumnData();
        ReportDefinition reportDefinition = new ReportDefinition();
        List<RowDefinition> rows = new ArrayList<>();
        List<ColumnDefinition> columns = new ArrayList<>();
        List<CellDefinition> cells = new ArrayList<>();
        reportDefinition.setRows(rows);
        reportDefinition.setColumns(columns);
        reportDefinition.setCells(cells);
        Map<String, Dataset> datasetMap = new HashMap<>();
        for (String key : dataList.keySet()) {
            Dataset dataset = new Dataset();
            dataset.setName(key);
            dataset.setData(dataList.get(key));
            datasetMap.put(key, dataset);
        }
        reportDefinition.setDatasetMap(datasetMap);
        Map<String, Functions> functionMap = new HashMap<>();
        //冻结
        UniverSheetFreeze freeze = sheet.getFreeze() != null ? sheet.getFreeze() : new UniverSheetFreeze();
        int freezeRow = freeze.getStartRow();
        int freezeColumn = freeze.getStartColumn();
        for (int i = 0; i <= Collections.max(rowMax); i++) {
            RowDefinition rowDefinition = new RowDefinition();
            rowDefinition.setRowNumber(i);
            rowDefinition.setSheetRowData(sheetRowData.get(i));
            rowDefinition.setFreeze(Objects.equals(freezeRow - 1, i));
            Map<Integer, UniverSheetCellData> columnData = cellData.get(i) != null ? cellData.get(i) : new HashMap<>();
            for (int j = 0; j <= Collections.max(columnMax); j++) {
                ColumnDefinition columnDefinition = new ColumnDefinition();
                columnDefinition.setColumnNumber(j);
                columnDefinition.setFreeze(Objects.equals(freezeColumn - 1, j));
                columnDefinition.setSheetColumnData(sheetColumnData.get(j));
                UniverSheetCellData sheetCellData = columnData.get(j) != null ? columnData.get(j) : new UniverSheetCellData();
                //合并
                int rowSpan = 0;
                int colSpan = 0;
                StyleModel styleModel = new StyleModel();
                Optional<UniverSheetRange> range = mergeData.stream().filter(t -> t.getStartRow().equals(rowDefinition.getRowNumber()) && t.getStartColumn().equals(columnDefinition.getColumnNumber())).findFirst();
                if (range.isPresent()) {
                    UniverSheetRange sheetRange = range.get();
                    rowSpan = sheetRange.getEndRow() - sheetRange.getStartRow();
                    colSpan = sheetRange.getEndColumn() - sheetRange.getStartColumn();
                    if (rowSpan > 0) {
                        for (int row = sheetRange.getStartRow() + 1; row <= sheetRange.getEndRow() - 1; row++) {
                            Map<Integer, UniverSheetCellData> dataMap = cellData.get(row);
                            if (dataMap != null) {
                                UniverSheetCellData startData = dataMap.get(sheetRange.getStartColumn());
                                if (startData != null) {
                                    styleModel.setL(startData.getS());
                                }
                                UniverSheetCellData endData = dataMap.get(sheetRange.getEndColumn());
                                if (endData != null) {
                                    styleModel.setR(endData.getS());
                                }
                            }
                        }
                    }
                    if (colSpan > 0) {
                        Map<Integer, UniverSheetCellData> startDataMap = cellData.get(sheetRange.getStartRow());
                        Map<Integer, UniverSheetCellData> endDataMap = cellData.get(sheetRange.getEndRow());
                        for (int col = sheetRange.getStartColumn() + 1; col <= sheetRange.getEndColumn() - 1; col++) {
                            if (startDataMap != null) {
                                UniverSheetCellData startData = startDataMap.get(col);
                                if (startData != null) {
                                    styleModel.setT(startData.getS());
                                }
                            }
                            if (endDataMap != null) {
                                UniverSheetCellData endData = endDataMap.get(col);
                                if (endData != null) {
                                    styleModel.setB(endData.getS());
                                }
                            }
                        }
                    }
                    Map<Integer, UniverSheetCellData> startDataMap = cellData.get(sheetRange.getStartRow());
                    if (startDataMap != null) {
                        UniverSheetCellData leftTopData = startDataMap.get(sheetRange.getStartColumn());
                        if (leftTopData != null) {
                            styleModel.setLt(leftTopData.getS());
                        }
                        UniverSheetCellData rightTopData = startDataMap.get(sheetRange.getEndColumn());
                        if (rightTopData != null) {
                            styleModel.setRt(rightTopData.getS());
                        }
                    }
                    Map<Integer, UniverSheetCellData> endDataMap = cellData.get(sheetRange.getEndRow());
                    if (endDataMap != null) {
                        UniverSheetCellData leftBodData = endDataMap.get(sheetRange.getStartColumn());
                        if (leftBodData != null) {
                            styleModel.setLb(leftBodData.getS());
                        }
                        UniverSheetCellData rightBodData = endDataMap.get(sheetRange.getEndColumn());
                        if (rightBodData != null) {
                            styleModel.setRb(rightBodData.getS());
                        }
                    }
                }
                CellDefinition cellDefinition = new CellDefinition();
                String definitionName = new CellReference(i, j).formatAsString();
                cellDefinition.setName(definitionName);
                cellDefinition.setRowNumber(i + 1);
                cellDefinition.setColumnNumber(j + 1);
                cellDefinition.setRowSpan(rowSpan > 0 ? rowSpan + 1 : rowSpan);
                cellDefinition.setColSpan(colSpan > 0 ? colSpan + 1 : colSpan);
                cellDefinition.setSheetColumnData(sheetColumnData.get(j));
                cellDefinition.setSheetRowData(sheetRowData.get(i));
                cellDefinition.setCellData(sheetCellData);
                cellDefinition.setStyleModel(styleModel);

                //判断函数
                String function = sheetCellData.getF() != null ? sheetCellData.getF().toString() : "";
                if (StringUtil.isNotEmpty(function)) {
                    if (function.startsWith("=")) {
                        List<CellRangeAddress> list = new ArrayList<>();
                        functionName(function, list);
                        Map<Integer, Map<Integer, String>> functionCell = new HashMap<>();
                        for (CellRangeAddress rangeAddress : list) {
                            int startRow = rangeAddress.getFirstRow();
                            int startCol = rangeAddress.getFirstColumn();
                            int endRow = rangeAddress.getLastRow();
                            int endCol = rangeAddress.getLastColumn();
                            List<CellReference> cellsRange = getCellsRange(startRow, endRow, startCol, endCol);
                            List<String> rangeName = new ArrayList<>();
                            for (CellReference reference : cellsRange) {
                                int row = reference.getRow();
                                int col = reference.getCol();
                                Map<Integer, String> rowMap = functionCell.get(row) != null ? functionCell.get(row) : new HashMap<>();
                                rowMap.put(col, reference.formatAsString());
                                functionCell.put(row, rowMap);
                                rangeName.add(reference.formatAsString());
                            }
                            if (cellsRange.size() > 1) {
                                function = function.replace(rangeAddress.formatAsString(), String.join(",", rangeName));
                            }
                        }
                        List<String> functionNameList = new ArrayList<>();
                        List<Integer> rowList = new ArrayList<>(functionCell.keySet()).stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
                        for (Integer row : rowList) {
                            Map<Integer, String> rowMap = functionCell.get(row) != null ? functionCell.get(row) : new HashMap<>();
                            List<Integer> colList = new ArrayList<>(rowMap.keySet()).stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
                            for (Integer col : colList) {
                                functionNameList.add(rowMap.get(col));
                            }
                        }
                        Functions functions = new Functions();
                        functions.setFunction(function);
                        functions.setName(definitionName);
                        functions.setFunctionName(functionNameList);
                        functionMap.put(definitionName, functions);
                        sheetCellData.setF(function);
                        sheetCellData.setV(null);
                    }
                }
                //数据类型
                Expand expand = Expand.None;
                String value = sheetCellData.getV() != null ? sheetCellData.getV().toString() : null;
                Value values = new SimpleValue(value);
                UniverDataConfig univerCellData = cell.stream().filter(t -> Objects.equals(t.getRow(), rowDefinition.getRowNumber()) && Objects.equals(t.getCol(), columnDefinition.getColumnNumber())).findFirst().orElse(new UniverDataConfig());
                UniverDataConfig univerDataConfig = univerCellData.getCustom() != null ? univerCellData.getCustom() : new UniverDataConfig();
                if (Objects.equals(CellDataEnum.dataSource.name(), univerCellData.getType())) {
                    String datasetName = "";
                    String property = "";
                    String fillDirection = univerDataConfig.getFillDirection();
                    String fileName = univerDataConfig.getField();
                    String summaryType = univerDataConfig.getSummaryType();
                    if (StringUtils.isNotEmpty(fileName)) {
                        String[] params = fileName.split("\\.");
                        if (params.length == 2) {
                            datasetName = params[0];
                            property = params[1];
                        }
                    }
                    AggregateType aggregate = AggregateType.none;
                    Integer type = univerDataConfig.getPolymerizationType();
                    boolean isSelect = Objects.equals(type, UniverDataEnum.select.getCode());
                    boolean isGroup = Objects.equals(type, UniverDataEnum.group.getCode());
                    boolean isSummary = Objects.equals(type, UniverDataEnum.summary.getCode());
                    if (isSelect || isGroup) {
                        expand = Objects.equals(UniverDataEnum.cellDirection.getName(), fillDirection) ? Expand.Down : Expand.Right;
                        aggregate = isGroup ? AggregateType.group : AggregateType.select;
                    } else if (isSummary) {
                        aggregate = AggregateType.value(summaryType);
                    }
                    DatasetValue datasetValue = new DatasetValue();
                    datasetValue.setDatasetName(datasetName);
                    datasetValue.setProperty(property);
                    datasetValue.setAggregate(aggregate);
                    values = datasetValue;
                }

                String leftName = "";
                String leftType = univerDataConfig.getLeftParentCellType();
                if (StringUtil.isNotEmpty(leftType)) {
                    UniverDataEnum dataType = UniverDataEnum.getData(leftType);
                    if (dataType != null) {
                        switch (dataType) {
                            case cellNone:
                                leftName = UniverDataEnum.cellRoot.getName();
                                break;
                            case cellCustom:
                                leftName = univerDataConfig.getLeftParentCellCustomRowName() + univerDataConfig.getLeftParentCellCustomColName();
                                break;
                        }
                    }
                }
                cellDefinition.setLeftType(leftType);
                cellDefinition.setLeftParentCellName(leftName);
                String topName = "";
                String topType = univerDataConfig.getTopParentCellType();
                if (StringUtil.isNotEmpty(topType)) {
                    UniverDataEnum dataType = UniverDataEnum.getData(topType);
                    if (dataType != null) {
                        switch (dataType) {
                            case cellNone:
                                topName = UniverDataEnum.cellRoot.getName();
                                break;
                            case cellCustom:
                                topName = univerDataConfig.getTopParentCellCustomRowName() + univerDataConfig.getTopParentCellCustomColName();
                                break;
                        }
                    }
                }
                cellDefinition.setTopType(topType);
                cellDefinition.setTopParentCellName(topName);
                cellDefinition.setExpand(expand);
                cellDefinition.setValue(values);
                boolean notAdd = mergeData.stream().filter(t -> t.getStartRow() <= rowDefinition.getRowNumber() && t.getStartColumn() <= columnDefinition.getColumnNumber() && t.getEndRow() >= rowDefinition.getRowNumber() && t.getEndColumn() >= columnDefinition.getColumnNumber()).count() > 0;
                if (!notAdd || mergeData.isEmpty() || range.isPresent()) {
                    cells.add(cellDefinition);
                }
                columnDefinition.setColumnNumber(columnDefinition.getColumnNumber() + 1);
                if (columns.stream().filter(t -> Objects.equals(t.getColumnNumber(), columnDefinition.getColumnNumber())).count() == 0) {
                    columns.add(columnDefinition);
                }
            }
            rowDefinition.setRowNumber(rowDefinition.getRowNumber() + 1);
            rows.add(rowDefinition);
        }
        rebuild(reportDefinition);
        rebuildReportDefinition(reportDefinition);
        ReportBuilder reportBuilder = new ReportBuilder();
        Report report = reportBuilder.buildReport(reportDefinition);
        UniverSheet result = sheet(sheet, report, functionMap);
        resource(sheet.getId(), report, resources);
        return result;
    }

    private UniverSheet sheet(UniverSheet sheet, Report report, Map<String, Functions> functionMap) {
        sheet.setCellData(new HashMap<>());
        sheet.setMergeData(new ArrayList<>());
        sheet.setRowData(new HashMap<>());
        sheet.setColumnData(new HashMap<>());
        Map<Integer, UniverSheetRowData> rowData = new HashMap<>();
        Map<Integer, UniverSheetColumnData> columnData = new HashMap<>();
        UniverSheet result = JsonUtil.getJsonToBean(sheet, UniverSheet.class);
        List<Row> rows = report.getRows();
        List<Column> columns = report.getColumns();
        Map<Row, Map<Column, Cell>> cellMap = report.getRowColCellMap();
        Map<Integer, Map<Integer, UniverSheetCellData>> cellData = new HashMap<>();
        Map<Integer, Map<Integer, Cell>> cellFunctionMap = new HashMap<>();
        List<UniverSheetRange> mergeData = new ArrayList<>();
        //获取冻结位置
        UniverSheetFreeze sheetFreeze = sheet.getFreeze() != null ? sheet.getFreeze() : new UniverSheetFreeze();
        int freezeRow = sheetFreeze.getStartRow();
        List<Integer> freezeRowList = new ArrayList<>();
        freezeRowList.add(freezeRow);
        int freezeColumn = sheetFreeze.getStartColumn();
        List<Integer> freezeColumnList = new ArrayList<>();
        freezeColumnList.add(freezeColumn);
        //绘制格子
        for (int i = 0; i < rows.size(); i++) {
            Row row = rows.get(i);
            rowData.put(i, row.getSheetRowData());
            if (row.getFreeze()) {
                freezeRowList.add(i + 1);
            }
            for (int j = 0; j < columns.size(); j++) {
                Column col = columns.get(j);
                Cell cell = null;
                if (cellMap.containsKey(row)) {
                    Map<Column, Cell> colMap = cellMap.get(row);
                    if (colMap.containsKey(col)) {
                        cell = colMap.get(col);
                    }
                }
                if (cell == null) {
                    continue;
                }
                if (col.getFreeze()) {
                    freezeColumnList.add(j + 1);
                }
                cell.setReference(new CellReference(i, j));
                UniverSheetCellData sheetCellData = JsonUtil.getJsonToBean(cell.getCellData(), UniverSheetCellData.class);
                //获取函数格子
                String cellName = cell.getName();
                if (functionMap.get(cellName) != null) {
                    Map<Integer, Cell> data = cellFunctionMap.get(i) != null ? cellFunctionMap.get(i) : new HashMap<>();
                    data.put(j, cell);
                    cellFunctionMap.put(i, data);
                }

                //合并格子
                int startRow = i;
                int endRow = i + (cell.getRowSpan() > 0 ? cell.getRowSpan() - 1 : cell.getRowSpan());
                int startCol = j;
                int endCol = j + (cell.getColSpan() > 0 ? cell.getColSpan() - 1 : cell.getColSpan());
                int rowSpan = cell.getRowSpan();
                int colSpan = cell.getColSpan();
                StyleModel styleModel = cell.getStyleModel();
                if (colSpan > 0 || rowSpan > 0) {
                    //左、右边框
                    boolean isL = ObjectUtil.isNotEmpty(styleModel.getL());
                    boolean isR = ObjectUtil.isNotEmpty(styleModel.getR());
                    for (int rowCount = startRow; rowCount <= endRow; rowCount++) {
                        Map<Integer, UniverSheetCellData> dataMap = cellData.get(rowCount) != null ? cellData.get(rowCount) : new HashMap<>();
                        UniverSheetCellData startData = dataMap.get(startCol) != null ? dataMap.get(startCol) : new UniverSheetCellData();
                        startData.setS(isL ? styleModel.getL() : sheetCellData.getS());
                        dataMap.put(startCol, startData);

                        UniverSheetCellData endData = dataMap.get(endCol) != null ? dataMap.get(endCol) : new UniverSheetCellData();
                        endData.setS(isR ? styleModel.getR() : sheetCellData.getS());
                        dataMap.put(endCol, endData);

                        cellData.put(rowCount, dataMap);
                    }

                    //上、下边框
                    boolean isT = ObjectUtil.isNotEmpty(styleModel.getT());
                    boolean isB = ObjectUtil.isNotEmpty(styleModel.getB());
                    for (int columnCount = startCol; columnCount <= endCol; columnCount++) {
                        Map<Integer, UniverSheetCellData> startDataMap = cellData.get(startRow) != null ? cellData.get(startRow) : new HashMap<>();
                        UniverSheetCellData startData = startDataMap.get(columnCount) != null ? startDataMap.get(columnCount) : new UniverSheetCellData();
                        startData.setS(isT ? styleModel.getT() : sheetCellData.getS());
                        startDataMap.put(columnCount, startData);
                        cellData.put(startRow, startDataMap);

                        Map<Integer, UniverSheetCellData> endDataMap = cellData.get(endRow) != null ? cellData.get(endRow) : new HashMap<>();
                        UniverSheetCellData endData = endDataMap.get(columnCount) != null ? endDataMap.get(columnCount) : new UniverSheetCellData();
                        endData.setS(isB ? styleModel.getB() : sheetCellData.getS());
                        endDataMap.put(columnCount, endData);
                        cellData.put(endRow, endDataMap);
                    }

                    //角样式
                    boolean isLT = ObjectUtil.isNotEmpty(styleModel.getLt());
                    boolean isRT = ObjectUtil.isNotEmpty(styleModel.getRt());
                    Map<Integer, UniverSheetCellData> startDataMap = cellData.get(startRow) != null ? cellData.get(startRow) : new HashMap<>();
                    UniverSheetCellData leftTopData = startDataMap.get(startCol) != null ? startDataMap.get(startCol) : new UniverSheetCellData();
                    leftTopData.setS(isLT ? styleModel.getLt() : sheetCellData.getS());
                    startDataMap.put(startCol, leftTopData);
                    UniverSheetCellData rightTopData = startDataMap.get(endCol) != null ? startDataMap.get(endCol) : new UniverSheetCellData();
                    rightTopData.setS(isRT ? styleModel.getRt() : sheetCellData.getS());
                    startDataMap.put(endCol, rightTopData);
                    cellData.put(startRow, startDataMap);

                    boolean isLB = ObjectUtil.isNotEmpty(styleModel.getLb());
                    boolean isRB = ObjectUtil.isNotEmpty(styleModel.getRb());
                    Map<Integer, UniverSheetCellData> endDataMap = cellData.get(endRow) != null ? cellData.get(endRow) : new HashMap<>();
                    UniverSheetCellData leftBottomData = endDataMap.get(startCol) != null ? endDataMap.get(startCol) : new UniverSheetCellData();
                    leftBottomData.setS(isLB ? styleModel.getLb() : sheetCellData.getS());
                    endDataMap.put(startCol, leftBottomData);
                    UniverSheetCellData rightBottomData = endDataMap.get(endCol) != null ? endDataMap.get(endCol) : new UniverSheetCellData();
                    rightBottomData.setS(isRB ? styleModel.getRb() : sheetCellData.getS());
                    endDataMap.put(endCol, rightBottomData);
                    cellData.put(endRow, endDataMap);

                    boolean notRange = mergeData.stream().filter(t -> t.getStartRow() <= startRow && t.getStartColumn() <= startCol && t.getEndRow() >= startRow && t.getEndColumn() >= startCol).count() > 0;
                    if (!notRange) {
                        UniverSheetRange range = new UniverSheetRange();
                        range.setStartRow(startRow);
                        range.setEndRow(endRow);
                        range.setStartColumn(startCol);
                        range.setEndColumn(endCol);
                        mergeData.add(range);
                    }
                }
                //赋值
                Object sheetData = cell.getData();
                Integer dataType = 1;
                try {
                    new BigDecimal(String.valueOf(sheetData));
                    dataType = 2;
                } catch (Exception e) {
                }
                if (sheetData instanceof Boolean) {
                    dataType = 3;
                }
                if (ObjectUtil.isNotEmpty(sheetCellData.getF())) {
                    dataType = 4;
                }
                sheetCellData.setT(dataType);
                sheetCellData.setV(sheetData);
                columnData.put(j, col.getSheetColumnData());
                Map<Integer, UniverSheetCellData> cellDataMap = cellData.get(i) != null ? cellData.get(i) : new HashMap<>();
                cellDataMap.put(j, sheetCellData);
                cellData.put(i, cellDataMap);
            }
        }
        //修改函数
        List<Integer> rowList = new ArrayList<>(cellFunctionMap.keySet()).stream().sorted(Comparator.naturalOrder()).collect(Collectors.toList());
        for (Integer row : rowList) {
            Map<Integer, Cell> rowMap = cellFunctionMap.get(row) != null ? cellFunctionMap.get(row) : new HashMap<>();
            List<Integer> colList = new ArrayList<>(rowMap.keySet()).stream().sorted(Comparator.naturalOrder()).collect(Collectors.toList());
            for (Integer col : colList) {
                Cell cell = rowMap.get(col);
                Functions model = functionMap.get(cell.getName());
                if (model != null) {
                    model.setRowNumber(row);
                    model.setColNumber(col);
                    functionList(cell, model, report);
                    //赋值
                    UniverSheetCellData data = JsonUtil.getJsonToBean(cell.getCellData(), UniverSheetCellData.class);
                    data.setT(4);
                    Map<Integer, UniverSheetCellData> cellDataMap = cellData.get(row) != null ? cellData.get(row) : new HashMap<>();
                    cellDataMap.put(col, data);
                    cellData.put(row, cellDataMap);
                }
            }
        }
        //赋值数据
        result.setCellData(cellData);
        result.setMergeData(mergeData);
        result.setRowData(rowData);
        result.setColumnData(columnData);
        List<Integer> rowMax = new ArrayList<>();
        rowMax.add(sheet.getRowCount());
        rowMax.add(rows.size());
        result.setRowCount(Collections.max(rowMax));
        List<Integer> columnMax = new ArrayList<>();
        columnMax.add(sheet.getColumnCount());
        columnMax.add(columns.size());
        result.setColumnCount(Collections.max(columnMax));

        //赋值冻结数据
        UniverSheetFreeze freeze = new UniverSheetFreeze();
        freeze.setStartRow(Collections.max(freezeRowList));
        freeze.setStartColumn(Collections.max(freezeColumnList));
        freeze.setYSplit(freeze.getStartRow() > -1 ? freeze.getStartRow() : 0);
        freeze.setXSplit(freeze.getStartColumn() > -1 ? freeze.getStartColumn() : 0);
        result.setFreeze(freeze);
        return result;
    }

    private void functionList(Cell cell, Functions model, Report report) {
        String function = new String(model.getFunction());
        Map<String, List<Cell>> cellsMap = report.getCellsMap();
        int endRow = model.getRowNumber();
        int endCol = model.getColNumber();
        Map<String, List<String>> functionName = new LinkedHashMap<>();
        for (String name : model.getFunctionName()) {
            Map<String, List<String>> leftTop = model.getLeftTop();
            Map<String, List<String>> leftBottom = model.getLeftBottom();
            Map<String, List<String>> rightTop = model.getRightTop();
            Map<String, List<String>> rightBottom = model.getRightBottom();
            List<String> leftTopListAll = leftTop.get(name) != null ? leftTop.get(name) : new ArrayList<>();
            List<String> leftBottomListAll = leftBottom.get(name) != null ? leftBottom.get(name) : new ArrayList<>();
            List<String> rightTopListAll = rightTop.get(name) != null ? rightTop.get(name) : new ArrayList<>();
            List<String> rightBottomListAll = rightBottom.get(name) != null ? rightBottom.get(name) : new ArrayList<>();
            List<String> leftTopList = new ArrayList<>();
            List<String> leftBottomList = new ArrayList<>();
            List<String> rightTopList = new ArrayList<>();
            List<String> rightBottomList = new ArrayList<>();
            List<Cell> cellList = cellsMap.get(name) != null ? cellsMap.get(name) : new ArrayList<>();
            for (Cell functionCell : cellList) {
                int rowSpan = cell.getRowSpan();
                int colSpan = cell.getColSpan();
                CellReference reference = functionCell.getReference();
                if (functionCell.getReference() != null) {
                    int functionRow = reference.getRow();
                    int functionCol = reference.getCol();
                    String format = reference.formatAsString();
                    //左上角
                    if (endRow >= functionRow && endCol >= functionCol) {
                        if (!leftTopListAll.contains(format)) {
                            leftTopList.add(format);
                        }else if (rowSpan > 0 && functionRow <= endRow && endRow <= functionRow + rowSpan - 1){
                            leftTopList.add(format);
                        }else if (colSpan > 0 && functionCol <= endCol && endCol <= functionCol + colSpan - 1){
                            leftTopList.add(format);
                        }
                    }
                    //左下角
                    if (endRow < functionRow && endCol >= functionCol) {
                        if (!leftBottomListAll.contains(format)) {
                            leftBottomList.add(format);
                        }
                    }
                    //右上角
                    if (endRow > functionRow) {
                        if (!rightTopListAll.contains(format)) {
                            rightTopList.add(format);
                        }
                    }
                    //右下角
                    if (endRow < functionRow || (endRow == functionRow && endCol >= functionCol)) {
                        if (!rightBottomListAll.contains(format)) {
                            rightBottomList.add(format);
                        }
                    }
                }
            }
            List<String> nameList = functionName.get(name) != null ? functionName.get(name) : new ArrayList<>();
            if (leftTopList.size() > 0) {
                leftTopListAll.addAll(leftTopList);
                nameList.addAll(leftTopList);
                leftTop.put(name, leftTopListAll);
            } else if (rightTopList.size() > 0) {
                rightTopListAll.addAll(rightTopList);
                nameList.addAll(rightTopList);
                rightTop.put(name, rightTopListAll);
            } else if (leftBottomList.size() > 0) {
                leftBottomListAll.addAll(leftBottomList);
                nameList.addAll(leftBottomList);
                leftBottom.put(name, leftBottomListAll);
            } else if (rightBottomList.size() > 0) {
                rightBottomListAll.addAll(rightBottomList);
                nameList.addAll(rightBottomList);
                rightBottom.put(name, rightBottomListAll);
            } else {
                if (cellList.size() == 1) {
                    nameList.add(cellList.get(0).getReference().formatAsString());
                }
            }
            if (nameList.size() > 0) {
                functionName.put(name, nameList);
            }
        }
        if (!functionName.isEmpty()) {
            for (String name : functionName.keySet()) {
                List<String> functionNameList = functionName.get(name);
                if (functionNameList.size() > 255) {
                    function = function.replaceAll(name, functionNameList.get(0) + ":" + functionNameList.get(functionNameList.size() - 1));
                } else {
                    function = function.replaceAll(name, String.join(",", functionNameList));
                }
            }
            cell.getCellData().setF(function);
        }
    }

    private void rebuild(ReportDefinition report) {
        List<CellDefinition> cells = report.getCells();
        Map<String, CellDefinition> cellsMap = new HashMap<>();
        Map<String, CellDefinition> cellsRowColMap = new HashMap<>();
        for (CellDefinition cell : cells) {
            cellsMap.put(cell.getName(), cell);
            int rowNum = cell.getRowNumber();
            int colNum = cell.getColumnNumber();
            int rowSpan = cell.getRowSpan() > 0 ? cell.getRowSpan() : 1;
            int colSpan = cell.getColSpan() > 0 ? cell.getColSpan() : 1;
            int rowStart = rowNum;
            int rowEnd = rowNum + rowSpan;
            int colStart = colNum;
            int colEnd = colNum + colSpan;
            for (int i = rowStart; i < rowEnd; i++) {
                cellsRowColMap.put(i + "," + colNum, cell);
            }
            for (int i = colStart; i < colEnd; i++) {
                cellsRowColMap.put(rowNum + "," + i, cell);
            }
        }
        for (CellDefinition cell : cells) {
            int rowNumber = cell.getRowNumber();
            int colNumber = cell.getColumnNumber();
            Value value = cell.getValue();
            boolean isData = value instanceof DatasetValue;

            String leftType = cell.getLeftType();
            String leftParentCellName = cell.getLeftParentCellName();
            CellDefinition leftTargetCell = cellsMap.get(leftParentCellName);
            if (leftTargetCell == null) {
                if (colNumber > 1) {
                    leftTargetCell = cellsRowColMap.get(rowNumber + "," + (colNumber - 1));
                    if (isData) {
                        for (int i = colNumber; i > 0; i--) {
                            CellDefinition definition = cellsRowColMap.get(rowNumber + "," + (i - 1));
                            if (definition != null) {
                                Value definitionValue = definition.getValue();
                                if (definitionValue instanceof DatasetValue) {
                                    leftTargetCell = definition;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            cell.setLeftParentCell(leftTargetCell);

            String topType = cell.getTopType();
            String topParentCellName = cell.getTopParentCellName();
            CellDefinition topTargetCell = cellsMap.get(topParentCellName);
            if (topTargetCell == null) {
                if (rowNumber > 1) {
                    topTargetCell = cellsRowColMap.get((rowNumber - 1) + "," + colNumber);
                    if (isData) {
                        for (int i = rowNumber; i > 0; i--) {
                            CellDefinition definition = cellsRowColMap.get((i - 1) + "," + colNumber);
                            if (definition != null) {
                                Value definitionValue = definition.getValue();
                                if (definitionValue instanceof DatasetValue) {
                                    topTargetCell = definition;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            cell.setTopParentCell(topTargetCell);

            if (isData) {
                DatasetValue datasetValue = (DatasetValue) value;
                AggregateType aggregate = datasetValue.getAggregate();
                List<AggregateType> aggregateType = ImmutableList.of(AggregateType.select, AggregateType.group);
                if (Objects.equals(topType, UniverDataEnum.cellNone.getName()) && Objects.equals(leftType, UniverDataEnum.cellNone.getName())) {
                    if (!aggregateType.contains(aggregate)) {
                        cell.setTopParentCell(null);
                        cell.setLeftParentCell(null);
                    }
                }
            }
        }
    }

    //赋值左、上父格
    private void rebuildReportDefinition(ReportDefinition reportDefinition) {
        List<CellDefinition> cells = reportDefinition.getCells();
        for (CellDefinition cell : cells) {
            List<String> rowName = new ArrayList<>();
            addRowChildCell(cell, cell, rowName);
            Set<String> row = new HashSet<>(rowName);
            List<String> columnName = new ArrayList<>();
            addColumnChildCell(cell, cell, columnName);
            Set<String> column = new HashSet<>(columnName);
            if (row.size() < rowName.size() || column.size() < columnName.size()) {
                throw new DataException(MsgCode.FA106.get());
            }
        }
        for (CellDefinition cell : cells) {
            Expand expand = cell.getExpand();
            switch (expand) {
                case Down:
                    DownCellbuilder downCellbuilder = new DownCellbuilder();
                    downCellbuilder.buildParentCell(cell, cells);
                    break;
                case Right:
                    RightCellbuilder rightCellbuilder = new RightCellbuilder();
                    rightCellbuilder.buildParentCell(cell, cells);
                    break;
            }
        }
    }

    //添加上父格
    private static void addRowChildCell(CellDefinition cell, CellDefinition childCell, List<String> rowName) {
        CellDefinition leftCell = cell.getLeftParentCell();
        if (leftCell == null) {
            return;
        }
        if (rowName.contains(leftCell.getName())) {
            rowName.add(leftCell.getName());
            return;
        }
        rowName.add(leftCell.getName());
        List<CellDefinition> childrenCells = leftCell.getRowChildrenCells();
        childrenCells.add(childCell);
        addRowChildCell(leftCell, childCell, rowName);
    }

    //添加左父格
    private static void addColumnChildCell(CellDefinition cell, CellDefinition childCell, List<String> columnName) {
        CellDefinition topCell = cell.getTopParentCell();
        if (topCell == null) {
            return;
        }
        if (columnName.contains(topCell.getName())) {
            columnName.add(topCell.getName());
            return;
        }
        columnName.add(topCell.getName());
        List<CellDefinition> childrenCells = topCell.getColumnChildrenCells();
        childrenCells.add(childCell);
        addColumnChildCell(topCell, childCell, columnName);
    }

    //解析函数，获取所在的格子
    private static void functionName(String functionText, List<CellRangeAddress> list) {
        Stack<Integer> stack = new Stack<>();
        List<String> result = new ArrayList<>();
        for (int i = 0; i < functionText.length(); i++) {
            char c = functionText.charAt(i);
            if (c == '(') {
                stack.push(i);
            } else if (c == ')') {
                if (!stack.isEmpty()) {
                    int start = stack.pop();
                    result.add(functionText.substring(start + 1, i));
                }
            }
        }
        List<String> splitList = ImmutableList.of(",","=");
        for (String range : result){
            for (String split : splitList){
                String[] name = range.split(split);
                for (String cell : name){
                    try {
                        CellRangeAddress cellRange = CellRangeAddress.valueOf(cell);
                        if (!list.contains(cellRange)) {
                            list.add(cellRange);
                        }
                    }catch (Exception e){
                    }
                }
            }
        }
    }

    //函数区间的格子
    private static List<CellReference> getCellsRange(int startRow, int endRow, int startCol, int endCol) {
        int rangeStartRow = startRow;
        int rangeStartCol = startCol;
        int rangeEndRow = endRow;
        int rangeEndCol = endCol;
        if (startRow > endRow || startCol > endCol) {
            rangeStartRow = endRow;
            rangeStartCol = endCol;
            rangeEndRow = startRow;
            rangeEndCol = startCol;
        }
        List<CellReference> referenceList = new ArrayList<>();
        if (rangeStartRow >= 0) {
            for (int rowNum = rangeStartRow; rowNum <= rangeEndRow; rowNum++) {
                for (int colNum = rangeStartCol; colNum <= rangeEndCol; colNum++) {
                    CellReference reference = new CellReference(rowNum, colNum);
                    referenceList.add(reference);
                }
            }
        }
        return referenceList;
    }

    private static void resource(String sheet, Report report, List<UniverResource> resources) {
        Map<String, List<Cell>> cellsMap = report.getCellsMap();
        //条件
        format(sheet, cellsMap, resources);
        //数据验证
        dataValidation(sheet, cellsMap, resources);
    }

    //调整数据格式、数据管理的所在格子
    private static List<UniverSheetRange> resourceRange(Map<String, List<Cell>> cellsMap, List<UniverSheetRange> sheetRanges) {
        List<UniverSheetRange> rangeList = new ArrayList<>();
        for (UniverSheetRange sheetRange : sheetRanges) {
            int startRow = sheetRange.getStartRow();
            int endRow = sheetRange.getEndRow();
            int startCol = sheetRange.getStartColumn();
            int endCol = sheetRange.getEndColumn();
            List<CellReference> cellReferenceList = getCellsRange(startRow, endRow, startCol, endCol);
            for (CellReference cellReference : cellReferenceList) {
                List<Cell> cellList = cellsMap.get(cellReference.formatAsString()) != null ? cellsMap.get(cellReference.formatAsString()) : new ArrayList<>();
                for (Cell cell : cellList) {
                    CellReference reference = cell.getReference();
                    if (reference != null) {
                        UniverSheetRange range = JsonUtil.getJsonToBean(sheetRange, UniverSheetRange.class);
                        range.setStartRow(reference.getRow());
                        range.setStartColumn((int) reference.getCol());
                        range.setEndRow(range.getStartRow());
                        range.setEndColumn(range.getStartColumn());
                        rangeList.add(range);
                    }
                }
            }
        }
        return rangeList.isEmpty() ? sheetRanges : rangeList;
    }

    //处理图表数据
    private static Map<String, List<UniverDataConfig>> drawing(List<UniverResource> resources, Map<String, UniverDataConfig> floatEcharts) {
        UniverResource drawing = resources.stream().filter(t -> ResourceEnum.SHEET_DRAWING_PLUGIN.name().equals(t.getName())).findFirst().orElse(null);
        Map<String, List<UniverDataConfig>> echartMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(drawing) && ObjectUtil.isNotEmpty(drawing.getData())) {
            Map<String, Object> data = JsonUtil.stringToMap(drawing.getData());
            data.forEach((key, value) -> {
                UniverResourceData jsonToBean = JsonUtil.getJsonToBean(value, UniverResourceData.class);
                Map<String, UniverDrawing> drawingMap = jsonToBean.getData() != null ? jsonToBean.getData() : new HashMap<>();
                for (String id : drawingMap.keySet()) {
                    UniverDataConfig univerDataConfig = floatEcharts.get(id);
                    UniverDrawing univerDrawing = drawingMap.get(id);
                    if (univerDataConfig != null && univerDrawing != null) {
                        univerDataConfig.setDrawingId(univerDrawing.getDrawingId());
                        univerDataConfig.setUnitId(univerDrawing.getUnitId());
                        univerDataConfig.setSubUnitId(univerDrawing.getSubUnitId());
                        List<UniverDataConfig> echartList = echartMap.get(key) != null ? echartMap.get(key) : new ArrayList<>();
                        echartList.add(univerDataConfig);
                        echartMap.put(key, echartList);
                    }
                }
            });
        }
        return echartMap;
    }

    //解析数据格式
    private static void format(String sheet, Map<String, List<Cell>> cellsMap, List<UniverResource> resources) {
        UniverResource formatting = resources.stream().filter(t -> ResourceEnum.SHEET_CONDITIONAL_FORMATTING_PLUGIN.name().equals(t.getName())).findFirst().orElse(null);
        Map<String, List<UniverResourceData>> foramtMap = new HashMap<>();
        if (formatting != null && ObjectUtil.isNotEmpty(formatting.getData())) {
            Map<String, Object> data = JsonUtil.stringToMap(formatting.getData());
            data.forEach((key, value) -> {
                foramtMap.put(key, JsonUtil.getJsonToList(value, UniverResourceData.class));
            });
            if (foramtMap.get(sheet) != null) {
                List<UniverResourceData> dataList = foramtMap.get(sheet);
                for (UniverResourceData resourceData : dataList) {
                    List<UniverSheetRange> sheetRanges = resourceData.getRanges();
                    List<UniverSheetRange> rangesList = resourceRange(cellsMap, sheetRanges);
                    resourceData.setRanges(rangesList);
                }
            }
            formatting.setData(JSONUtil.toJsonStr(foramtMap));
        }
    }

    //解析数据验证
    private static void dataValidation(String sheet, Map<String, List<Cell>> cellsMap, List<UniverResource> resources) {
        UniverResource validation = resources.stream().filter(t -> ResourceEnum.SHEET_DATA_VALIDATION_PLUGIN.name().equals(t.getName())).findFirst().orElse(null);
        Map<String, List<UniverResourceData>> validationMap = new HashMap<>();
        if (validation != null && ObjectUtil.isNotEmpty(validation.getData())) {
            Map<String, Object> data = JsonUtil.stringToMap(validation.getData());
            data.forEach((key, value) -> {
                validationMap.put(key, JsonUtil.getJsonToList(value, UniverResourceData.class));
            });
            if (validationMap.get(sheet) != null) {
                List<UniverResourceData> dataList = validationMap.get(sheet);
                for (UniverResourceData resourceData : dataList) {
                    List<UniverSheetRange> sheetRanges = resourceData.getRanges();
                    List<UniverSheetRange> rangesList = resourceRange(cellsMap, sheetRanges);
                    resourceData.setRanges(rangesList);
                }
            }
            validation.setData(JSONUtil.toJsonStr(validationMap));
        }
    }

    private static void filter(String sheet, Map<String, List<Cell>> cellsMap, List<UniverResource> resources) {
        UniverResource filter = resources.stream().filter(t -> ResourceEnum.SHEET_FILTER_PLUGIN.name().equals(t.getName())).findFirst().orElse(null);
        Map<String, UniverResourceData> filterMap = new HashMap<>();
        if (filter != null && ObjectUtil.isNotEmpty(filter.getData())) {
            Map<String, Object> data = JsonUtil.stringToMap(filter.getData());
            data.forEach((key, value) -> {
                filterMap.put(key, JsonUtil.getJsonToBean(value, UniverResourceData.class));
            });
            if (filterMap.get(sheet) != null) {
                UniverResourceData resourceData = filterMap.get(sheet);
                if (resourceData != null) {
                    UniverSheetRange sheetRange = resourceData.getRef();
                    List<UniverSheetRange> rangesList = resourceRange(cellsMap, ImmutableList.of(sheetRange));
                    Map<Integer, List<UniverSheetRange>> rangesMap = rangesList.stream().collect(Collectors.groupingBy(UniverSheetRange::getStartRow));
                    int startRow = Collections.min(rangesMap.keySet());
                    int startCol = Collections.min(rangesMap.get(startRow).stream().map(UniverSheetRange::getStartColumn).collect(Collectors.toList()));
                    int endRow = Collections.max(rangesMap.keySet());
                    int endCol = Collections.max(rangesMap.get(endRow).stream().map(UniverSheetRange::getEndColumn).collect(Collectors.toList()));
                    UniverSheetRange range = JsonUtil.getJsonToBean(sheetRange, UniverSheetRange.class);
                    range.setStartRow(startRow);
                    range.setStartColumn(startCol);
                    range.setEndRow(endRow);
                    range.setEndColumn(endCol);
                    resourceData.setRef(range);
                }
                filter.setData(JSONUtil.toJsonStr(filterMap));
            }
        }
    }
}
