package com.zt.plat.module.erp.service.erp;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.framework.common.util.object.BeanUtils;
import com.zt.plat.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.zt.plat.module.erp.api.dto.ErpProductiveVersionReqDTO;
import com.zt.plat.module.erp.utils.ErpConfig;
import com.zt.plat.module.erp.utils.MyRedisConfig;
import com.zt.plat.module.erp.enums.OftenEnum;
import com.zt.plat.module.erp.controller.admin.erp.vo.ErpProductiveVersionPageReqVO;
import com.zt.plat.module.erp.controller.admin.erp.vo.ErpProductiveVersionRespVO;
import com.zt.plat.module.erp.controller.admin.erp.vo.ErpProductiveVersionSaveReqVO;
import com.zt.plat.module.erp.dal.dataobject.erp.ErpProductiveVersionDO;
import com.zt.plat.module.erp.dal.mysql.erp.ErpProductiveVersionMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

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

import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.zt.plat.module.erp.enums.ErrorCodeConstants.*;
import static dm.jdbc.util.DriverUtil.log;

/**
 * ERP生产版本 Service 实现类
 *
 * @author 后台管理
 */
@Service
@Validated
public class ErpProductiveVersionServiceImpl implements ErpProductiveVersionService {

    @Resource
    private ErpProductiveVersionMapper erpProductiveVersionMapper;

    @Resource
    private MyRedisConfig myRedisConfig;
    @Resource
    private ErpConfig erpConfig;

    @Override
    public ErpProductiveVersionRespVO createErpProductiveVersion(ErpProductiveVersionSaveReqVO createReqVO) {
        // 插入
        ErpProductiveVersionDO erpProductiveVersion = BeanUtils.toBean(createReqVO, ErpProductiveVersionDO.class);
        erpProductiveVersionMapper.insert(erpProductiveVersion);
        // 返回
        return BeanUtils.toBean(erpProductiveVersion, ErpProductiveVersionRespVO.class);
    }

    @Override
    public void updateErpProductiveVersion(ErpProductiveVersionSaveReqVO updateReqVO) {
        // 校验存在
        validateErpProductiveVersionExists(updateReqVO.getId());
        // 更新
        ErpProductiveVersionDO updateObj = BeanUtils.toBean(updateReqVO, ErpProductiveVersionDO.class);
        erpProductiveVersionMapper.updateById(updateObj);
    }

    @Override
    public void deleteErpProductiveVersion(Long id) {
        // 校验存在
        validateErpProductiveVersionExists(id);
        // 删除
        erpProductiveVersionMapper.deleteById(id);
    }

    @Override
    public void deleteErpProductiveVersionListByIds(List<Long> ids) {
        // 校验存在
        validateErpProductiveVersionExists(ids);
        // 删除
        erpProductiveVersionMapper.deleteByIds(ids);
    }

    private void validateErpProductiveVersionExists(List<Long> ids) {
        List<ErpProductiveVersionDO> list = erpProductiveVersionMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
            throw exception(ERP_PRODUCTIVE_VERSION_NOT_EXISTS);
        }
    }

    private void validateErpProductiveVersionExists(Long id) {
        if (erpProductiveVersionMapper.selectById(id) == null) {
            throw exception(ERP_PRODUCTIVE_VERSION_NOT_EXISTS);
        }
    }

    @Override
    public ErpProductiveVersionDO getErpProductiveVersion(Long id) {
        return erpProductiveVersionMapper.selectById(id);
    }

    @Override
    public PageResult<ErpProductiveVersionDO> getErpProductiveVersionPage(ErpProductiveVersionPageReqVO pageReqVO) {
        return erpProductiveVersionMapper.selectPage(pageReqVO);
    }

    @Override
    public void enableErpProductiveVersion(ErpProductiveVersionSaveReqVO updateReqVO) {

        validateErpProductiveVersionExists(updateReqVO.getId());
        erpProductiveVersionMapper.enableErpProductiveVersion(updateReqVO.getFactoryNumber(), updateReqVO.getMaterialNumber());
        // 更新
        ErpProductiveVersionDO updateObj = BeanUtils.toBean(updateReqVO, ErpProductiveVersionDO.class);
        erpProductiveVersionMapper.updateById(updateObj);
    }

    @Override
    public String getErpProductiveVersionByFM(ErpProductiveVersionReqDTO reqDTO) {
        return erpProductiveVersionMapper.getErpProductiveVersionByFM(reqDTO);
    }


    @Override
    @Transactional
    @XxlJob("getErpProductiveVersionTask")
    public void callErpRfcInterface() {
        OftenEnum.FuncnrEnum funcnrEnum = OftenEnum.FuncnrEnum.生产版本;
        String funcnr = funcnrEnum.getFuncnr();
        //防止缓存数据丢失
        String key = "erpMap" + funcnrEnum.getFuncnr();
        if (myRedisConfig.getRedisCacheMap(key).isEmpty()) {
            initializeMap(key);
        }

        Map<String, Object> req = new HashMap<>();
        JSONArray dataArrayALL = new JSONArray();
        String factKey = "erpMap" + OftenEnum.FuncnrEnum.工厂信息.getFuncnr();
        Map<String, Long> redisCache = myRedisConfig.getRedisCacheMap(factKey);
        if (CollUtil.isEmpty(redisCache)) {
            throw exception(ERP_FACTORY_NOT_EXISTS);
        }
        // 1. 调用ERP接口获取数据
        for (String number : redisCache.keySet()) {
            req.put("WERKS", number);
            // 1. 调用ERP接口获取数据
            Map<String, Object> dataFromERP = erpConfig.fetchDataFromERP(funcnr, req);
            JSONArray dataArray = (JSONArray) dataFromERP.get("E_RESP");
            if (dataArray == null || dataArray.isEmpty()) {
                continue;
            }
            dataArrayALL.addAll(dataArray);
        }
        if (dataArrayALL.isEmpty()) {
            throw exception(ERP_PRODUCTIVE_VERSION_NOT_EXISTS);
        }

        // 2. 处理公司数据，区分新增和更新
        ProcessingResult result = processData(dataArrayALL, funcnrEnum);

        // 3. 批量保存数据
        saveData(result);
    }

    /**
     * 处理数据，区分新增和更新
     */
    private ProcessingResult processData(JSONArray dataArray, OftenEnum.FuncnrEnum funcnr) {
        String key = "erpMap" + funcnr.getFuncnr();
        Map<String, Long> numbers = myRedisConfig.getRedisCacheMap(key);
        List<ErpProductiveVersionDO> toUpdate = new ArrayList<>();
        List<ErpProductiveVersionDO> toInsert = new ArrayList<>();

        List<String> dataArrayNumbers = new ArrayList<>();
        for (int i = 0; i < dataArray.size(); i++) {
            JSONObject dataJson = dataArray.getJSONObject(i);
            if (dataJson != null) {
                ErpProductiveVersionDO DO = new ErpProductiveVersionDO();
                DO.setFactoryNumber(dataJson.getString("WERKS") != null ? dataJson.getString("WERKS").trim() : null);
                DO.setMaterialNumber(dataJson.getString("MATNR") != null ? dataJson.getString("MATNR").trim() : null);
                DO.setProductiveVersionNumber(dataJson.getString("VERID") != null ? dataJson.getString("VERID").trim() : null);
                DO.setProductiveVersionName(dataJson.getString("TEXT1"));
                DO.setBomNumber(dataJson.getString("STLAL"));
                DO.setBlineGroup(dataJson.getString("ALNAL"));
                String alnalValue = dataJson.getString("PLNNR");
                // 修复：增加对空字符串的判断
                DO.setGroupCount(alnalValue != null && !alnalValue.trim().isEmpty() ? Long.valueOf(alnalValue.trim()) : null);
                String number = dataJson.getString("MATNR").trim() + "-" + dataJson.getString("WERKS").trim() + "-" + dataJson.getString("VERID").trim();
                if (numbers.get(number) != null) {
                    // 更新
                    DO.setId(numbers.get(number));
                    toUpdate.add(DO);
                } else {
                    // 新增
                    toInsert.add(DO);
                }
                dataArrayNumbers.add(number);
            }
        }
        // 过滤出numbers中有，但dataArray中KOSTL没有的记录，即为需要删除的数据
        Map<String, Long> deleteNumbers = new HashMap<>();
        for (String number : numbers.keySet()) {
            if (!dataArrayNumbers.contains(number)) {
                deleteNumbers.put(number, numbers.get(number));
            }
        }

        return new ProcessingResult(toUpdate, toInsert, key, deleteNumbers);
    }

    /**
     * 批量保存数据
     */
    private void saveData(ProcessingResult result) {
        // 批量新增和更新
        if (!result.toInsert.isEmpty()) {
            erpProductiveVersionMapper.insertBatch(result.toInsert);
            // 批量查询刚插入数据的id，提升效率
            List<ErpProductiveVersionDO> insertedRecords = erpProductiveVersionMapper.selectList(
                    new LambdaQueryWrapperX<ErpProductiveVersionDO>()
                            .in(ErpProductiveVersionDO::getFactoryNumber, result.toInsert.stream().map(ErpProductiveVersionDO::getFactoryNumber).collect(Collectors.toList()))
                            .in(ErpProductiveVersionDO::getMaterialNumber, result.toInsert.stream().map(ErpProductiveVersionDO::getMaterialNumber).collect(Collectors.toList()))
                            .in(ErpProductiveVersionDO::getProductiveVersionNumber, result.toInsert.stream().map(ErpProductiveVersionDO::getProductiveVersionNumber).collect(Collectors.toList()))
            );
            Map<String, Long> numberIdMap = insertedRecords.stream()
                    .collect(Collectors.toMap(asset -> asset.getFactoryNumber() + "-" + asset.getMaterialNumber() + "-" + asset.getProductiveVersionNumber(), ErpProductiveVersionDO::getId));
            myRedisConfig.addRedisCacheMap(result.key, numberIdMap);
        }
        if (!result.toUpdate.isEmpty()) {
            erpProductiveVersionMapper.updateBatch(result.toUpdate);
        }
        if (!result.deleteNumbers.isEmpty()) {
            // 使用流式处理和批处理优化删除逻辑
            List<Long> idsToDelete = new ArrayList<>(result.deleteNumbers.values());
            erpProductiveVersionMapper.deleteByIds(idsToDelete);
            myRedisConfig.deleteRedisCacheMap(result.key, new ArrayList<>(result.deleteNumbers.keySet()));
        }
    }

    /**
     * 数据处理结果封装类
     */
    private static class ProcessingResult {
        private final List<ErpProductiveVersionDO> toUpdate;
        private final List<ErpProductiveVersionDO> toInsert;
        private final String key;
        private final Map<String, Long> deleteNumbers;

        public ProcessingResult(List<ErpProductiveVersionDO> toUpdate, List<ErpProductiveVersionDO> toInsert, String key, Map<String, Long> deleteNumbers) {
            this.toUpdate = toUpdate;
            this.toInsert = toInsert;
            this.key = key;
            this.deleteNumbers = deleteNumbers;
        }
    }

    private void initializeMap(String key) {
        List<ErpProductiveVersionDO> assets = erpProductiveVersionMapper.selectList(new LambdaQueryWrapperX<ErpProductiveVersionDO>());
        Map<String, Long> existingNumbers = new HashMap<>();
        for (ErpProductiveVersionDO asset : assets) {
            String mapKey = asset.getFactoryNumber() + "-" + asset.getMaterialNumber() + "-" + asset.getProductiveVersionNumber();
            existingNumbers.put(mapKey, asset.getId());
        }
        myRedisConfig.addRedisCacheMap(key, existingNumbers);
    }
}