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.dal.dataobject.erp.ErpFactoryDO;
import com.zt.plat.module.erp.dal.mysql.erp.ErpFactoryMapper;
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.ErpWarehousePageReqVO;
import com.zt.plat.module.erp.controller.admin.erp.vo.ErpWarehouseRespVO;
import com.zt.plat.module.erp.controller.admin.erp.vo.ErpWarehouseSaveReqVO;
import com.zt.plat.module.erp.dal.dataobject.erp.ErpWarehouseDO;
import com.zt.plat.module.erp.dal.mysql.erp.ErpWarehouseMapper;
import jakarta.annotation.Resource;
import org.apache.ibatis.executor.BatchResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.util.*;
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 ErpWarehouseServiceImpl implements ErpWarehouseService {

    @Resource
    private ErpWarehouseMapper erpWarehouseMapper;
    @Resource
    private ErpFactoryService erpFactoryService;

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

    @Resource
    private WarehouseFactoryService warehouseFactoryService;

    @Override
    public ErpWarehouseRespVO createErpWarehouse(ErpWarehouseSaveReqVO createReqVO) {
        // 校验存在
        validateErpFactoryExistsNumber(createReqVO.getNumber(), createReqVO.getFactoryNumber());
        // 插入
        ErpWarehouseDO warehouse = BeanUtils.toBean(createReqVO, ErpWarehouseDO.class);
        // 库位编码自动生成，格式 KW-0001,依次新增
//        if (warehouse.getNumber() == null) {
//            String maxCode = erpWarehouseMapper.selectMaxCode();
//            if (maxCode == null) {
//                warehouse.setNumber("KW-0001");
//            } else {
//                String prefix = "KW-";
//                String numberPart = maxCode.substring(prefix.length());
//                int nextNumber = Integer.parseInt(numberPart) + 1;
//                String nextCode = prefix + String.format("%04d", nextNumber);
//                warehouse.setNumber(nextCode);
//            }
//        }
        warehouse.setType("SPLY");
        warehouse.setIsEnable("1");
        erpWarehouseMapper.insert(warehouse);
        // 返回
        return BeanUtils.toBean(warehouse, ErpWarehouseRespVO.class);
    }

    @Override
    public void updateErpWarehouse(ErpWarehouseSaveReqVO updateReqVO) {
        // 校验存在
        validateErpWarehouseExists(updateReqVO.getId());
        // 更新
        ErpWarehouseDO updateObj = BeanUtils.toBean(updateReqVO, ErpWarehouseDO.class);
        if (updateObj.getType().equals("SPLY") && updateObj.getIsEnable().equals("0")) {
            erpWarehouseMapper.updateById(updateObj);
        } else {
            throw exception(ERP_WAREHOUSE_NOT_ALLOW_UPDATE);
        }
    }

    @Override
    public void deleteErpWarehouse(Long id) {
        // 校验存在
        validateErpWarehouseExists(id);
        // 删除
        erpWarehouseMapper.deleteById(id);
    }

    @Override
    public void deleteErpWarehouseListByIds(List<Long> ids) {
        // 校验存在
        validateErpWarehouseExists(ids);
        // 删除
        erpWarehouseMapper.deleteByIds(ids);
    }

    private void validateErpWarehouseExists(List<Long> ids) {
        List<ErpWarehouseDO> list = erpWarehouseMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
            throw exception(ERP_WAREHOUSE_NOT_EXISTS);
        }
    }

    private void validateErpWarehouseExists(Long id) {
        if (erpWarehouseMapper.selectById(id) == null) {
            throw exception(ERP_WAREHOUSE_NOT_EXISTS);
        }
    }

    private void validateErpFactoryExistsNumber(String number, String factoryNumber) {
        List<ErpWarehouseDO> list = erpWarehouseMapper.selectList(new LambdaQueryWrapperX<ErpWarehouseDO>()).stream()
                .filter(erpWarehouseDO -> erpWarehouseDO.getNumber().equals(number))
                .filter(erpWarehouseDO -> Objects.equals(erpWarehouseDO.getFactoryNumber(), factoryNumber))
                .toList();
        if (!list.isEmpty()) {
            throw exception(ERP_WAREHOUSE_EXISTS);
        }
    }

    @Override
    public ErpWarehouseRespVO getErpWarehouse(Long id) {
        ErpWarehouseRespVO erpWarehouseRespVO = BeanUtils.toBean(erpWarehouseMapper.selectById(id), ErpWarehouseRespVO.class);
        setWarehouseFactoryInfo(erpWarehouseRespVO);
        return erpWarehouseRespVO;
    }

    @Override
    public ErpWarehouseDO getErpWarehouse(String id) {
        return erpWarehouseMapper.selectById(id);
    }

    @Override
    public void enableWarehouseList(List<ErpWarehouseSaveReqVO> saveReqVOS) {
        List<ErpWarehouseDO> updateObj = BeanUtils.toBean(saveReqVOS, ErpWarehouseDO.class);
        List<BatchResult> count = erpWarehouseMapper.updateById(updateObj);
        if (CollUtil.isEmpty(count)) {
            throw exception(ERP_WAREHOUSE_NOT_EXISTS);
        }
    }

@Override
public PageResult<ErpWarehouseDO> getErpWarehousePageDistinctByFactory(ErpWarehousePageReqVO pageReqVO) {
    // 获取所有数据
    List<ErpWarehouseDO> allList = erpWarehouseMapper.selectList(pageReqVO);
    if (allList == null) {
        allList = Collections.emptyList();
    }

    // 按工厂编码去重，保留第一个出现的元素
    List<ErpWarehouseDO> distinctList = allList.stream()
            .collect(Collectors.toMap(
                    ErpWarehouseDO::getFactoryNumber,
                    warehouse -> warehouse,
                    (existing, replacement) -> existing,
                    LinkedHashMap::new)) // 保持原始顺序
            .values()
            .stream()
            .collect(Collectors.toList());

    // 分页处理
    int pageNo = pageReqVO.getPageNo();
    int pageSize = pageReqVO.getPageSize();
    long total = distinctList.size();

    // 计算分页起始和结束位置
    int fromIndex = (pageNo - 1) * pageSize;
    int toIndex = (int) Math.min((long) fromIndex + pageSize, total);

    // 如果起始位置超出范围，则返回空列表
    if (fromIndex >= total) {
        return new PageResult<>(Collections.emptyList(), total);
    }

    // 截取当前页数据
    List<ErpWarehouseDO> pageList = distinctList.subList(fromIndex, toIndex);
    return new PageResult<>(pageList, total);
}


    @Override
    public PageResult<ErpWarehouseDO> getErpWarehousePage(ErpWarehousePageReqVO pageReqVO) {
        return new PageResult<>(erpWarehouseMapper.selectWarehouseByDynamicParams(pageReqVO, pageReqVO.getPageNo()-1, pageReqVO.getPageSize()), erpWarehouseMapper.selectWarehouseByDynamicParamsCount(pageReqVO));
        //        PageResult<ErpWarehouseRespVO> erpWarehouseRespVOPageResult = BeanUtils.toBean(erpWarehouseMapper.selectPage(pageReqVO), ErpWarehouseRespVO.class);
//        if (erpWarehouseRespVOPageResult.getList() == null) {
//            return erpWarehouseRespVOPageResult;
//        }
//        erpWarehouseRespVOPageResult.getList().forEach(this::setWarehouseFactoryInfo);
//        return erpWarehouseRespVOPageResult;
        // 获取分页数据
//        List<ErpWarehouseDO> list = erpWarehouseMapper.getPageByReq(pageReqVO);
//        if (list == null) {
//            list = CollUtil.newArrayList();
//        }
//        // 分页处理
//        int pageNo = pageReqVO.getPageNo();
//        int pageSize = pageReqVO.getPageSize();
//        int total = list.size();
//        // 计算分页起始和结束位置
//        int fromIndex = (pageNo - 1) * pageSize;
//        int toIndex = Math.min(fromIndex + pageSize, total);
//        // 如果起始位置超出范围，则返回空列表
//        if (fromIndex >= total) {
//            return new PageResult<>(new ArrayList<>(), (long) total);
//        }
//        // 截取当前页数据
//        List<ErpWarehouseDO> pageList = list.subList(fromIndex, toIndex);
//        return new PageResult<>(pageList, (long) total);
    }

    // 设置主物料信息
    public void setWarehouseFactoryInfo(ErpWarehouseRespVO warehouse) {
        if (warehouse == null) {
            return;
        }
        warehouse.setWarehouseFactories(warehouseFactoryService.getWarehouseFactoryByMainId(warehouse.getId().toString()));

    }

    @Override
    @Transactional
    @XxlJob("getErpWarehouseTask")
    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);

        List<ErpFactoryDO> erpFactoryList = erpFactoryService.getErpFactoryList();
        Map<String, String> factoryMap = new HashMap<>();
        if (CollUtil.isNotEmpty(erpFactoryList)){
            for (ErpFactoryDO erpFactoryDO : erpFactoryList){
                factoryMap.put(erpFactoryDO.getNumber(),erpFactoryDO.getErpCompanyNumber());
            }
        }

        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;
            }
            // 往每个子项中添加BUKRS字段
            for (int j = 0; j < dataArray.size(); j++) {
                JSONObject item = dataArray.getJSONObject(j);
                if (item != null) {
                    item.put("WERKS", number);
                }
            }
            dataArrayALL.addAll(dataArray);
        }
        if (dataArrayALL.isEmpty()) {
            throw exception(ERP_WAREHOUSE_NOT_EXISTS);
        }

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

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

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

        List<String> dataArrayNumbers = new ArrayList<>();
        for (int i = 0; i < dataArray.size(); i++) {
            JSONObject dataJson = dataArray.getJSONObject(i);
            if (dataJson != null) {
                ErpWarehouseDO DO = new ErpWarehouseDO();
                DO.setName(dataJson.getString("LGOBE"));
                DO.setNumber(dataJson.getString("LGORT").trim());
                DO.setFactoryNumber(dataJson.getString("WERKS"));
                if (DO.getFactoryNumber() != null && factoryMap != null){
                    DO.setCompanyNumber(factoryMap.get(DO.getFactoryNumber()));
                }
                DO.setType("ERP");
                String number = dataJson.getString("WERKS").trim() + "-" + dataJson.getString("LGORT").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()) {
            erpWarehouseMapper.insertBatch(result.toInsert);
            // 批量查询刚插入数据的id，提升效率
            List<ErpWarehouseDO> insertedRecords = erpWarehouseMapper.selectList(
                    new LambdaQueryWrapperX<ErpWarehouseDO>()
                            .in(ErpWarehouseDO::getFactoryNumber, result.toInsert.stream().map(ErpWarehouseDO::getFactoryNumber).collect(Collectors.toList()))
                            .in(ErpWarehouseDO::getNumber, result.toInsert.stream().map(ErpWarehouseDO::getNumber).collect(Collectors.toList()))
            );
            Map<String, Long> numberIdMap = insertedRecords.stream()
                    .collect(Collectors.toMap(asset -> asset.getFactoryNumber() + "-" + asset.getNumber(), ErpWarehouseDO::getId));
            myRedisConfig.addRedisCacheMap(result.key, numberIdMap);
        }
        if (!result.toUpdate.isEmpty()) {
            erpWarehouseMapper.updateBatch(result.toUpdate);
        }
        if (!result.deleteNumbers.isEmpty()) {
            // 使用流式处理和批处理优化删除逻辑
            List<Long> idsToDelete = new ArrayList<>(result.deleteNumbers.values());
            erpWarehouseMapper.deleteByIds(idsToDelete);
            myRedisConfig.deleteRedisCacheMap(result.key, new ArrayList<>(result.deleteNumbers.keySet()));
        }
    }

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

        public ProcessingResult(List<ErpWarehouseDO> toUpdate, List<ErpWarehouseDO> 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<ErpWarehouseDO> assets = erpWarehouseMapper.selectList(new LambdaQueryWrapperX<ErpWarehouseDO>()
                .eq(ErpWarehouseDO::getType, "ERP"));
        Map<String, Long> existingNumbers = new HashMap<>();
        for (ErpWarehouseDO asset : assets) {
            String mapKey = asset.getFactoryNumber() + "-" + asset.getNumber();
            existingNumbers.put(mapKey, asset.getId());
        }
        myRedisConfig.addRedisCacheMap(key, existingNumbers);
    }
}