package com.aucma.base.service.impl;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import com.aucma.base.domain.BaseMaterialInfo;
import com.aucma.base.mapper.BaseMaterialinfoMapper;
import com.aucma.base.service.IBaseMaterialInfoService;
import com.aucma.base.utils.MaterialConstants;
import com.aucma.base.utils.MaterialImportExcelHelper;
import com.aucma.common.exception.ServiceException;
import com.aucma.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 物料信息Service业务层处理
 *
 * @author Yinq
 * @date 2023-09-19
 */
@Service
public class BaseMaterialInfoServiceImpl implements IBaseMaterialInfoService
{
    @Autowired
    private BaseMaterialinfoMapper baseMaterialInfoMapper;

    /**
     * 查询物料信息
     *
     * @param objId 物料信息主键
     * @return 物料信息
     */
    @Override
    public BaseMaterialInfo selectBaseMaterialInfoByObjId(Long objId)
    {
        return baseMaterialInfoMapper.selectBaseMaterialInfoByObjId(objId);
    }

    /**
     * 查询物料信息列表
     *
     * @param baseMaterialInfo 物料信息
     * @return 物料信息
     */
    @Override
    public List<BaseMaterialInfo> selectBaseMaterialInfoList(BaseMaterialInfo baseMaterialInfo)
    {
        return baseMaterialInfoMapper.selectBaseMaterialInfoList(baseMaterialInfo);
    }

    /**
     * PDA按关键字模糊查询物料
     */
    @Override
    public List<BaseMaterialInfo> selectPdaMaterialListByKeyword(String keyword)
    {
        return baseMaterialInfoMapper.selectPdaMaterialListByKeyword(keyword);
    }

    /**
     * 导入物料BOM滚算模板
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importMaterialExcel(InputStream inputStream, Boolean updateSupport, String operName, String plantCode)
    {
        try
        {
            MaterialImportExcelHelper.ParseResult parseResult = MaterialImportExcelHelper.parse(inputStream);
            List<MaterialImportExcelHelper.MaterialImportRow> importRows = parseResult.getMaterialRows();
            Map<String, BaseMaterialInfo> existMap = loadExistMaterialMap(importRows);
            int insertNum = 0;
            int updateNum = 0;
            int skipNum = 0;
            Date now = DateUtils.getNowDate();
            for (MaterialImportExcelHelper.MaterialImportRow importRow : importRows)
            {
                BaseMaterialInfo existed = existMap.get(importRow.getMaterialCode());
                if (existed == null)
                {
                    BaseMaterialInfo materialInfo = buildImportMaterial(importRow, operName, plantCode, now);
                    insertBaseMaterialInfo(materialInfo);
                    insertNum++;
                    continue;
                }
                if (!Boolean.TRUE.equals(updateSupport))
                {
                    skipNum++;
                    continue;
                }
                // Why：模板只有编码和对象描述，更新时只覆盖模板能表达的字段，避免把人工维护的单位/分类等数据刷成空值。
                existed.setMaterialName(importRow.getMaterialName());
                if (!isBlank(plantCode))
                {
                    existed.setPlantCode(plantCode);
                }
                existed.setIncrementDate(now);
                existed.setUpdatedBy(operName);
                updateBaseMaterialInfo(existed);
                updateNum++;
            }
            return buildImportResult(insertNum, updateNum, skipNum, parseResult.getDuplicateRows());
        }
        catch (ServiceException e)
        {
            throw e;
        }
        catch (Exception e)
        {
            throw new ServiceException("导入物料模板失败：" + e.getMessage());
        }
    }

    /**
     * 新增物料信息
     *
     * @param baseMaterialInfo 物料信息
     * @return 结果
     */
    @Override
    public int insertBaseMaterialInfo(BaseMaterialInfo baseMaterialInfo)
    {
        fillMaterialSpecifications(baseMaterialInfo);
        baseMaterialInfo.setCreatedTime(DateUtils.getNowDate());
        return baseMaterialInfoMapper.insertBaseMaterialInfo(baseMaterialInfo);
    }

    /**
     * 修改物料信息
     *
     * @param baseMaterialInfo 物料信息
     * @return 结果
     */
    @Override
    public int updateBaseMaterialInfo(BaseMaterialInfo baseMaterialInfo)
    {
        fillMaterialSpecifications(baseMaterialInfo);
        baseMaterialInfo.setUpdatedTime(DateUtils.getNowDate());
        return baseMaterialInfoMapper.updateBaseMaterialInfo(baseMaterialInfo);
    }

    /**
     * 批量删除物料信息
     *
     * @param objIds 需要删除的物料信息主键
     * @return 结果
     */
    @Override
    public int deleteBaseMaterialInfoByObjIds(Long[] objIds)
    {
        return baseMaterialInfoMapper.deleteBaseMaterialInfoByObjIds(objIds);
    }

    /**
     * 删除物料信息信息
     *
     * @param objId 物料信息主键
     * @return 结果
     */
    @Override
    public int deleteBaseMaterialInfoByObjId(Long objId)
    {
        return baseMaterialInfoMapper.deleteBaseMaterialInfoByObjId(objId);
    }

    private Map<String, BaseMaterialInfo> loadExistMaterialMap(List<MaterialImportExcelHelper.MaterialImportRow> importRows)
    {
        Map<String, BaseMaterialInfo> materialMap = new LinkedHashMap<>();
        List<String> materialCodes = new ArrayList<>();
        for (MaterialImportExcelHelper.MaterialImportRow importRow : importRows)
        {
            materialCodes.add(importRow.getMaterialCode());
        }
        int batchSize = 900;
        for (int index = 0; index < materialCodes.size(); index += batchSize)
        {
            int endIndex = Math.min(index + batchSize, materialCodes.size());
            List<String> subCodes = materialCodes.subList(index, endIndex);
            List<BaseMaterialInfo> existedList = baseMaterialInfoMapper.selectBaseMaterialInfoByMaterialCodes(subCodes);
            for (BaseMaterialInfo materialInfo : existedList)
            {
                materialMap.put(materialInfo.getMaterialCode(), materialInfo);
            }
        }
        return materialMap;
    }

    private BaseMaterialInfo buildImportMaterial(MaterialImportExcelHelper.MaterialImportRow importRow, String operName, String plantCode, Date incrementDate)
    {
        BaseMaterialInfo materialInfo = new BaseMaterialInfo();
        materialInfo.setMaterialCode(importRow.getMaterialCode());
        materialInfo.setMaterialName(importRow.getMaterialName());
        materialInfo.setPlantCode(plantCode);
        materialInfo.setIsFlag(0L);
        materialInfo.setIncrementDate(incrementDate);
        materialInfo.setCreatedBy(operName);
        return materialInfo;
    }

    private String buildImportResult(int insertNum, int updateNum, int skipNum, List<MaterialImportExcelHelper.DuplicateMaterialRow> duplicateRows)
    {
        StringBuilder builder = new StringBuilder("导入完成！");
        builder.append("<br/>新增：").append(insertNum).append(" 条");
        builder.append("<br/>更新：").append(updateNum).append(" 条");
        if (skipNum > 0)
        {
            builder.append("<br/>跳过：").append(skipNum).append(" 条");
        }
        if (duplicateRows != null && !duplicateRows.isEmpty())
        {
            builder.append("<br/>模板内重复编码已跳过：").append(duplicateRows.size()).append(" 条");
            int previewSize = Math.min(10, duplicateRows.size());
            for (int index = 0; index < previewSize; index++)
            {
                MaterialImportExcelHelper.DuplicateMaterialRow duplicateRow = duplicateRows.get(index);
                builder.append("<br/>重复编码[")
                        .append(duplicateRow.getDuplicateRow().getMaterialCode())
                        .append("]，保留 ")
                        .append(duplicateRow.getFirstRow().getSheetName())
                        .append(" 第")
                        .append(duplicateRow.getFirstRow().getRowNum())
                        .append("行，跳过 ")
                        .append(duplicateRow.getDuplicateRow().getSheetName())
                        .append(" 第")
                        .append(duplicateRow.getDuplicateRow().getRowNum())
                        .append("行");
            }
            if (duplicateRows.size() > previewSize)
            {
                builder.append("<br/>其余重复编码共 ").append(duplicateRows.size() - previewSize).append(" 条未展开。");
            }
        }
        return builder.toString();
    }

    private void fillMaterialSpecifications(BaseMaterialInfo baseMaterialInfo)
    {
        String materialName = trimToEmpty(baseMaterialInfo.getMaterialName());
        String materialSubclass = trimToEmpty(baseMaterialInfo.getMaterialSubclass());
        if (materialName.isEmpty() || materialSubclass.isEmpty())
        {
            return;
        }
        String[] split = materialName.split(",");
        if (split.length == 0)
        {
            return;
        }
        // Why：导入模板只有编码和描述，只有在分类口径明确时才推导规格，避免因为模板信息不全覆盖人工维护结果。
        if (MaterialConstants.FP_MATERIAL_TYPE.equals(materialSubclass))
        {
            String firstPart = trimToEmpty(split[0]);
            if (firstPart.isEmpty())
            {
                return;
            }
            if (firstPart.startsWith("BC") || firstPart.length() == 1)
            {
                baseMaterialInfo.setMaterialSpecifications(firstPart);
                return;
            }
            baseMaterialInfo.setMaterialSpecifications(firstPart.substring(1));
            return;
        }
        if (split.length > 1)
        {
            baseMaterialInfo.setMaterialSpecifications(trimToEmpty(split[1]));
        }
    }

    private boolean isBlank(String text)
    {
        return text == null || text.trim().isEmpty();
    }

    private String trimToEmpty(String text)
    {
        return text == null ? "" : text.trim();
    }
}
