package com.cf.imes.module.executor.service.manage.plate;

import com.alibaba.excel.context.AnalysisContext;
import com.cf.imes.framework.dict.core.util.DictFrameworkUtils;
import com.cf.imes.module.executor.controller.admin.manage.plate.vo.plate.PlateImportExcelVO;
import com.cf.imes.module.executor.enums.DictTypeConstants;
import com.cf.imes.module.executor.util.file.ExcelListener;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

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

import static com.cf.imes.module.executor.enums.ErrorCodeConstants.PLATE_ATTR_GROUP_EXISTS;

@Slf4j
public final class PlateExcelListener<T> extends ExcelListener<PlateImportExcelVO> {

    /**
     * 自定义用于暂时存储data
     * 可以通过实例获取该值
     */
    private List<PlateImportExcelVO> datas = new ArrayList<>();

    private boolean flag = true;

    private Map<Integer, String> valueMap = new HashMap<>();

    private boolean updateSupport; // 是否更新

    private PlateManageService plateManageService;

    private Set<String> plateGoodsId;

    private List<String> orgAttrGroupList;

    public PlateExcelListener(boolean updateSupport, PlateManageService plateManageService, Long organId) {
        this.updateSupport = updateSupport;
        this.plateManageService = plateManageService;
        // 查询机构下的所有板材商品编号
        plateGoodsId = plateManageService.getOrgPlateGoodsId(organId);

        // 查询机构下名称、材质、颜色、厚度、品牌的分组
        List<LinkedHashMap<String, Object>> orgAttrGroup = plateManageService.getOrgAttrGroup(organId);

        orgAttrGroupList = orgAttrGroup.stream()
                .map(map -> map.values().stream()
                        .map(String::valueOf) // 确保都转为字符串
                        .collect(Collectors.joining("-")))
                .collect(Collectors.toList());
    }

    /**
     * 每解析一行都会回调invoke()方法
     *
     * @param data    读取后的数据对象
     * @param context 内容
     */
    @Override
    public void invoke(PlateImportExcelVO data, AnalysisContext context) {
        if (!data.isValidGoods()) {//返回false，表示商品信息无效；否则返回true，表示商品信息有效
            data.setResult("板材【*】信息请填写完整");
            this.flag = false;
        }
        setIfInvalid(data.getThickness(),"厚度",data);
        checkData(data.getThickness(),"厚度",data);
        if (data.getPrice() == null || data.getPrice().equals("")) {
            data.setPrice("0");
        }
        checkData(data.getPrice(),"价格",data);
        checkTexture(data.getTexture(),"纹理",data);
//        判断goodsID是否重复
        if (!updateSupport) {
            checkGoodsId(data.getGoodsId(),"物料编号",data);
        }
        // 检查属性组合组织内唯一性
        checkAttrGroup(data);
//        字段长度判断
        checkLength(data.getGoodsId(),"物料编号",data,32);
        checkLength(data.getGoodsName(),"物料名称",data,64);
        checkLength(data.getMaterial(),"材质",data,64);
        checkLength(data.getColor(),"颜色",data,32);
        checkLength(data.getBrand(),"品牌",data,64);
        checkLength(data.getRemark(),"备注",data,255);

        if (data.getResult() != null)
            data.setResult(data.getResult().replace("null,", ""));
        valueMap.put(context.getCurrentRowNum(), data.getResult());
        datas.add(data);
    }

    /**
     * 检查属性组合（名称、材质、颜色、厚度、品牌）是否存在
     *
     * @param data
     */
    private void checkAttrGroup(PlateImportExcelVO data) {
        String checkKey = data.getGoodsName() + "-" + data.getMaterial() + "-" + data.getColor() + "-" + Double.valueOf(data.getThickness()) + "-" + (StringUtils.isNotEmpty(data.getBrand()) ? data.getBrand() : "");
        if (orgAttrGroupList.contains(checkKey)) {
            this.flag = false;
            data.setResult(data.getResult() + "," + PLATE_ATTR_GROUP_EXISTS.getMsg());
        }
    }

    /**
     * 检查商品编号是否存在
     * @param valueCheck
     * @param head
     * @param data
     */
    private void checkGoodsId(String valueCheck, String head, PlateImportExcelVO data) {
        if (valueCheck != null && !valueCheck.equals("")) {
            String value = valueCheck.trim();
            if (plateGoodsId.contains(value)) {
                this.flag = false;
                data.setResult(data.getResult() + "," + head + "已存在");
            }
        }
    }
//    非空判断
    private void setIfInvalid(String valueCheck, String head, PlateImportExcelVO data) {
        if (valueCheck == null || valueCheck.equals("")) {
            this.flag = false;
            data.setResult(data.getResult() + "," + head + "信息缺少");
        }
    }
    private void checkData(String valueCheck, String head, PlateImportExcelVO data) {
//        长宽厚、价格判断非空
        if (valueCheck != null && !valueCheck.equals("")) {
            try {
                if (!data.checkPrecision(Double.valueOf(valueCheck))) {
                    data.setResult(data.getResult() + "," + head + "数据有误");
                    this.flag = false;
                }
            } catch (NumberFormatException e) {
                this.flag = false;
                data.setResult(data.getResult() + "," + head + "需要填写数字");
            }
        }
    }

    private void checkTexture(String valueCheck, String head, PlateImportExcelVO data) {

        if (valueCheck != null && !valueCheck.equals("")) {
            String value = valueCheck.trim();

            String dictData = DictFrameworkUtils.parseDictDataValue(DictTypeConstants.PLATE_TEXTURE_TYPE, value);
            if (StringUtils.isEmpty(dictData)) {
                this.flag = false;
                data.setResult(data.getResult() + "," + head + "信息有误");
            } else {
                data.setTexture(dictData);
            }
        }
    }


    /**
     * 字段长度判断
     */
    private void checkLength(String valueCheck, String head, PlateImportExcelVO data, int maxLength) {
        if (valueCheck != null && !valueCheck.equals("")) {
            if (valueCheck.length() > maxLength) {
                this.flag = false;
                data.setResult(data.getResult() + "," + head + "信息有误");
            }
        }
    }

    /**
     * 读取完后操作
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        if (this.flag)
            log.info("PlateExcelListener 所有数据读取完成");
    }

    /**
     * 返回数据
     *
     * @return 返回读取的数据集合
     **/
    public List<PlateImportExcelVO> getDates() {
        return datas;
    }

    /**
     * 返回读取结果
     *
     * @return 是否读取成功
     **/
    public boolean getFlag() {
        return flag;
    }

    /**
     * 返回错误信息
     *
     * @return String
     **/
    public Map<Integer, String> getValueMap() {
        return valueMap;
    }

}