package com.xdap.self_development.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.fastjson2.JSON;
import com.xdap.self_development.common.MyResponse;
import com.xdap.self_development.domain.pojo.ParameterPojo;
import com.xdap.self_development.service.TemplateService;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Slf4j
public class SheetDataListener implements ReadListener<ParameterPojo> {
	private static final int BATCH_SIZE = 1000;

	private final TemplateService templateService;
	private final String templateRowId;
	private final String createBy;
    private final List<ParameterPojo> cachedDataList;
    private final List<String> subDepartments;
	private String currentSheetName;
	MyResponse problems;


	public SheetDataListener(TemplateService templateService,
                             String templateRowId, String createBy,
                             MyResponse problems, List<String> subDepartments) {
		this.templateService = templateService;
		this.templateRowId = templateRowId;
		this.createBy = createBy;
		this.cachedDataList = new ArrayList<>(BATCH_SIZE);
		this.problems = problems;
        this.subDepartments = subDepartments;
	}

	@Override
	public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
		currentSheetName = context.readSheetHolder().getSheetName();
		// 每个模板一开始认定没有问题
		problems.setFlag(false);
		log.info("开始解析Sheet: {}", currentSheetName);
        log.info("开始解析表头行: {}", context.readRowHolder().getRowIndex());
        log.info("解析到一条头数据:{}", JSON.toJSONString(headMap));
	}

	@Override
	public void invoke(ParameterPojo data, AnalysisContext context) {
        log.info("开始解析数据行: {}", context.readRowHolder().getRowIndex());
        log.info("解析到一条数据: {}", data);
        if (context.readRowHolder().getRowIndex() == 1) {
            return;
        }
        // 参数校验
        if (data == null) {
            return;
        }

        if (currentSheetName == null) {
			currentSheetName = context.readSheetHolder().getSheetName();
		}

        if (!"数据平台手工录入".equals(data.getParameterSource())
                && !"TC分类表".equals(data.getParameterSource())
                && !"公式计算".equals(data.getParameterSource())
        ) {
            problems.setFlag(true);
            problems.getErrors().add(String.format("模板导入失败:" + "模板'%s'的参数'%s'来源错误， %s",
                    currentSheetName, data.getParameterName(),
                    data.getParameterSource()));
            return;
        }

        if ("公式计算".equals(data.getParameterSource()) && data.getNumberOrFormula() == null) {
            problems.setFlag(true);
            problems.getErrors().add(String.format("模板导入失败:" + "模板'%s'的参数'%s'公式不能为空",
                    currentSheetName, data.getParameterName()));
            return;
        }

        if ("数据平台手工录入".equals(data.getParameterSource()) && data.getDepartment() == null) {
                problems.setFlag(true);
                problems.getErrors().add(String.format("模板导入失败:" + "模板'%s'的参数'%s'部门不能为空",
                        currentSheetName, data.getParameterName()));
                return;
        }

		if (data.getDepartment() != null && !subDepartments.contains(data.getDepartment())) {
            problems.setFlag(true);
            problems.getErrors().add(String.format("模板导入失败:" + "模板'%s'的参数'%s'部门不存在",
                    currentSheetName, data.getParameterName()));
            return;
        }

        if (data.getIsNumber() == null
                || (!Objects.equals(data.getIsNumber(), "数值")
                && !Objects.equals(data.getIsNumber(), "非数值"))) {
            data.setIsNumber("非数值");
        }

		cachedDataList.add(data);

		// 达到批处理大小时提前处理
		if (cachedDataList.size() >= BATCH_SIZE) {
			processBatch();
		}
	}

	@Override
	public void doAfterAllAnalysed(AnalysisContext context) {
		if (!cachedDataList.isEmpty()) {
			processBatch();
		} else {
			problems.getErrors().add("模板导入失败:模板'" + currentSheetName + "'没有数据");
			problems.setFlag(true);
		}
	}

	private void processBatch() {
		templateService.processSheetData(
				new ArrayList<>(cachedDataList),
				currentSheetName,
				templateRowId,
				createBy,
				problems
		);
		cachedDataList.clear();
	}
}
