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.ErpExternalApi;
import com.zt.plat.module.erp.api.dto.ErpSubmitReqDTO;
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.ErpBomPageReqVO;
import com.zt.plat.module.erp.controller.admin.erp.vo.ErpBomRespVO;
import com.zt.plat.module.erp.controller.admin.erp.vo.ErpBomSaveReqVO;
import com.zt.plat.module.erp.dal.dataobject.erp.ErpBomDO;
import com.zt.plat.module.erp.dal.dataobject.erp.ErpBomDetailDO;
import com.zt.plat.module.erp.dal.mysql.erp.ErpBomMapper;
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 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物料清单(BOM) Service 实现类
 *
 * @author 后台管理
 */
@Service
@Validated
public class ErpBomServiceImpl implements ErpBomService {

    @Resource
    private ErpBomMapper erpBomMapper;

    @Resource
    private MyRedisConfig myRedisConfig;

    @Resource
    private ErpConfig erpConfig;

    @Resource
    public ErpExternalApi erpExternalApi;

    @Resource
    private ErpBomDetailServiceImpl bomDetailService;

    @Override
    public ErpBomRespVO createErpBom(ErpBomSaveReqVO createReqVO) {
        // 插入
        ErpBomDO erpBom = BeanUtils.toBean(createReqVO, ErpBomDO.class);
        erpBomMapper.insert(erpBom);
        // 返回
        return BeanUtils.toBean(erpBom, ErpBomRespVO.class);
    }

    @Override
    public void updateErpBom(ErpBomSaveReqVO updateReqVO) {
        // 校验存在
        validateErpBomExists(updateReqVO.getId());
        // 更新
        ErpBomDO updateObj = BeanUtils.toBean(updateReqVO, ErpBomDO.class);
        erpBomMapper.updateById(updateObj);
    }

    @Override
    public void deleteErpBom(Long id) {
        // 校验存在
        validateErpBomExists(id);
        // 删除
        erpBomMapper.deleteById(id);
    }

    @Override
    public void deleteErpBomListByIds(List<Long> ids) {
        // 校验存在
        validateErpBomExists(ids);
        // 删除
        erpBomMapper.deleteByIds(ids);
    }

    private void validateErpBomExists(List<Long> ids) {
        List<ErpBomDO> list = erpBomMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
            throw exception(ERP_BOM_NOT_EXISTS);
        }
    }

    private void validateErpBomExists(Long id) {
        if (erpBomMapper.selectById(id) == null) {
            throw exception(ERP_BOM_NOT_EXISTS);
        }
    }

    @Override
    public ErpBomDO getErpBom(Long id) {
        return erpBomMapper.selectById(id);
    }

    @Override
    public PageResult<ErpBomDO> getErpBomPage(ErpBomPageReqVO pageReqVO) {
        return erpBomMapper.selectPage(pageReqVO);
    }

    @Override
    @Transactional
    @XxlJob("getErpBomTask")
    public void callErpRfcInterface() {
        OftenEnum.FuncnrEnum funcnrEnum = OftenEnum.FuncnrEnum.BOM清单;
        String funcnr = funcnrEnum.getFuncnr();
        String key = "erpMap" + funcnr;
        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_REDIS_NOT_EXISTS);
        }
        for (String factoryNumber : redisCache.keySet()) {
            req.put("WERKS", factoryNumber);
            // 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 (CollUtil.isEmpty(dataArrayALL)) {
            throw exception(ERP_BOM_NOT_EXISTS);
        }

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

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

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

        List<ErpBomDetailDO> erpBomDetailDOList = new ArrayList<>();
        Map<String, Long> addnumbers = new HashMap<>();
        List<String> dataArrayNumbers = new ArrayList<>();

        for (int i = 0; i < dataArray.size(); i++) {
            JSONObject dataJson = dataArray.getJSONObject(i);
            if (dataJson != null) {
                ErpBomDO bomDO = new ErpBomDO();
                bomDO.setFactoryNumber(dataJson.getString("WERKS"));
                bomDO.setUpMaterial(dataJson.getString("MATNR"));
                bomDO.setUseItem(dataJson.getString("STLAL"));
                bomDO.setMaterialDescription(dataJson.getString("MAKTX"));
                bomDO.setQuantity(dataJson.getBigDecimal("BMENG"));
                bomDO.setUnit(dataJson.getString("BMEIN"));

                String number = bomDO.getFactoryNumber() + "-" + bomDO.getUpMaterial() + "-" + bomDO.getUseItem();
                dataArrayNumbers.add(number);

                if (numbers.containsKey(number)) {
                    // 更新
                    bomDO.setId(numbers.get(number));
                    toUpdate.add(bomDO);
                } else {
                    // 新增
                    erpBomMapper.insert(bomDO);
                    addnumbers.put(number, bomDO.getId());
                }

                JSONArray dataJsonItem = dataJson.getJSONArray("ITEM");
                if (dataJsonItem != null && !dataJsonItem.isEmpty()) {
                    for (int j = 0; j < dataJsonItem.size(); j++) {
                        JSONObject itemJson = dataJsonItem.getJSONObject(j);
                        ErpBomDetailDO detailDO = new ErpBomDetailDO();
                        detailDO.setBomId(String.valueOf(bomDO.getId()));
                        detailDO.setErpBomId(itemJson.getString("STVKN"));
                        detailDO.setChildMaterialNumber(itemJson.getString("IDNRK"));
                        detailDO.setChildMaterialDescription(itemJson.getString("OJTXP"));
                        detailDO.setCategory(itemJson.getString("POSTP"));
                        detailDO.setQuantity(itemJson.getBigDecimal("MENGE"));
                        detailDO.setUnit(itemJson.getString("MEINS"));
                        detailDO.setIdentificationType(itemJson.getString("WLCAT"));
                        erpBomDetailDOList.add(detailDO);
                    }
                }
            }
        }

        // 识别需要删除的数据
        List<String> deleteNumbers = new ArrayList<>();
        for (String number : numbers.keySet()) {
            if (!dataArrayNumbers.contains(number)) {
                deleteNumbers.add(number);
            }
        }

        return new ProcessingResult(toUpdate, key, addnumbers, deleteNumbers, erpBomDetailDOList);
    }

    /**
     * 批量保存数据
     */
    private void saveData(ProcessingResult result) {
        // 批量更新
        if (!result.toUpdate.isEmpty()) {
            erpBomMapper.updateBatch(result.toUpdate);
        }

        // 保存或更新BOM详情
        if (!result.erpBomDetailDOList.isEmpty()) {
            bomDetailService.saveOrUpdateErpBomDetail(result.erpBomDetailDOList);
        }

        // 更新Redis缓存
        if (!result.addnumbers.isEmpty()) {
            myRedisConfig.addRedisCacheMap(result.key, result.addnumbers);
        }

        if (!result.deleteNumbers.isEmpty()) {
            myRedisConfig.deleteRedisCacheMap(result.key, result.deleteNumbers);
        }
    }

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

        public ProcessingResult(List<ErpBomDO> toUpdate, String key, Map<String, Long> addnumbers,
                                List<String> deleteNumbers, List<ErpBomDetailDO> erpBomDetailDOList) {
            this.toUpdate = toUpdate;
            this.key = key;
            this.addnumbers = addnumbers;
            this.deleteNumbers = deleteNumbers;
            this.erpBomDetailDOList = erpBomDetailDOList;
        }
    }

    private void initializeMap(String key) {
        List<ErpBomDO> bomList = erpBomMapper.selectList(new LambdaQueryWrapperX<ErpBomDO>());
        Map<String, Long> existingNumbers = new HashMap<>();
        for (ErpBomDO bom : bomList) {
            String mapKey = bom.getFactoryNumber() + "-" + bom.getUpMaterial() + "-" + bom.getUseItem();
            existingNumbers.put(mapKey, bom.getId());
        }
        myRedisConfig.addRedisCacheMap(key, existingNumbers);
    }


    @Override
    public void submitDataToErp() {
        ErpSubmitReqDTO reqDTO = new ErpSubmitReqDTO();
        reqDTO.setFuncnr("061");
        reqDTO.setBskey("POTEST011");
        reqDTO.setUsrid("cuibin");
        reqDTO.setUsrnm("崔斌");

        Map<String, Object> req = new HashMap<>();

        Map<String, String> exte = new HashMap<>();
        exte.put("zzhth", "成品采购合同0406-1-xt");
        req.put("exte", exte);

        Map<String, Object> head = new HashMap<>();
        head.put("pur_group", "120");
        head.put("purch_org", "3017");
        head.put("comp_code", "3017");
        head.put("vendor", "0000003162");
        head.put("doc_date", "20230406");
        head.put("currency", "CNY");
        head.put("exch_rate", 1.00000000);
        head.put("doc_type", "PO01");
        head.put("zzhth", "成品采购合同0406-1-xt");
        req.put("head", head);

        List<Map<String, Object>> items = new ArrayList<>();
        Map<String, Object> item = new HashMap<>();
        item.put("material", "000000000000226986");
        item.put("net_price", 40000.00);
        item.put("plant", "3026");
        item.put("po_item", 1);
        item.put("po_unit", "TON");
        item.put("price_unit", 1);
        item.put("quantity", 2000.000);
        item.put("stge_loc", "4011");
        item.put("tax_code", "J0");
        item.put("unlimited_dlv", "X");
        items.add(item);
        req.put("item", items);
        reqDTO.setReq(req);
        Map<String, String> response = erpExternalApi.submitDataToErp(reqDTO);
        if (response.get("result").isEmpty()) {
            log.info("ERP数据提交成功");
        }
    }
}