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.ErpMaterialDO;
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.ErpCustomerPageReqVO;
import com.zt.plat.module.erp.controller.admin.erp.vo.ErpCustomerRespVO;
import com.zt.plat.module.erp.controller.admin.erp.vo.ErpCustomerSaveReqVO;
import com.zt.plat.module.erp.dal.dataobject.erp.ErpCustomerDO;
import com.zt.plat.module.erp.dal.mysql.erp.ErpCustomerMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.time.LocalDate;
import java.time.LocalDateTime;
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.ERP_CUSTOMER_NOT_EXISTS;
import static dm.jdbc.util.DriverUtil.log;

/**
 * ERP客商主数据 Service 实现类
 *
 * @author 后台管理
 */
@Service
@Validated
public class ErpCustomerServiceImpl implements ErpCustomerService {

    @Resource
    private MyRedisConfig myRedisConfig;

    @Resource
    private ErpCustomerMapper erpCustomerMapper;
    @Resource
    private ErpConfig erpConfig;

    @Override
    public ErpCustomerRespVO createErpCustomer(ErpCustomerSaveReqVO createReqVO) {
        // 插入
        ErpCustomerDO erpCustomer = BeanUtils.toBean(createReqVO, ErpCustomerDO.class);
        erpCustomerMapper.insert(erpCustomer);
        // 返回
        return BeanUtils.toBean(erpCustomer, ErpCustomerRespVO.class);
    }

    @Override
    public void updateErpCustomer(ErpCustomerSaveReqVO updateReqVO) {
        // 校验存在
        validateErpCustomerExists(updateReqVO.getId());
        // 更新
        ErpCustomerDO updateObj = BeanUtils.toBean(updateReqVO, ErpCustomerDO.class);
        erpCustomerMapper.updateById(updateObj);
    }

    @Override
    public void deleteErpCustomer(Long id) {
        // 校验存在
        validateErpCustomerExists(id);
        // 删除
        erpCustomerMapper.deleteById(id);
    }

    @Override
    public void deleteErpCustomerListByIds(List<Long> ids) {
        // 校验存在
        validateErpCustomerExists(ids);
        // 删除
        erpCustomerMapper.deleteByIds(ids);
    }

    private void validateErpCustomerExists(List<Long> ids) {
        List<ErpCustomerDO> list = erpCustomerMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
            throw exception(ERP_CUSTOMER_NOT_EXISTS);
        }
    }

    private void validateErpCustomerExists(Long id) {
        if (erpCustomerMapper.selectById(id) == null) {
            throw exception(ERP_CUSTOMER_NOT_EXISTS);
        }
    }

    @Override
    public ErpCustomerDO getErpCustomer(Long id) {
        return erpCustomerMapper.selectById(id);
    }

    @Override
    public PageResult<ErpCustomerDO> getErpCustomerPage(ErpCustomerPageReqVO pageReqVO) {
        return erpCustomerMapper.selectPage(pageReqVO);
    }

    @Override
    @Transactional
    @XxlJob("getErpCustomerTask")
    public void callErpRfcInterface() {
        OftenEnum.FuncnrEnum funcnrEnum = OftenEnum.FuncnrEnum.客商信息;
        String funcnr = funcnrEnum.getFuncnr();

        String key = "erp" + funcnrEnum.getFuncnr();
        if (myRedisConfig.getRedisCache(key) == null) {
            initialize(key);
        }
        //循环近五年日期，
//        JSONArray dataArrayALL = new JSONArray();
//        LocalDate endDate = LocalDate.now();
//        LocalDate startDate = endDate.minusYears(5);
//        for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
        // 构建req参数
        Map<String, Object> req = new HashMap<>();
        List<Map<String, String>> datumList = new ArrayList<>();
        Map<String, String> datumEntry = new HashMap<>();
        // 构建datum参数数组
        datumEntry.put("sign", "I");
        datumEntry.put("option", "EQ");
        // 把每次循环的日期，放在这里
        datumEntry.put("low", LocalDate.now().toString());
        datumList.add(datumEntry);
        req.put(funcnrEnum.getDatekey(), datumList);

        // 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 (dataArray.isEmpty()) {
            return;
        }

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

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


//    @Override
//    @Transactional
//    @XxlJob("getErpCustomerTask")
//    public void callErpRfcInterface() {
//        OftenEnum.FuncnrEnum funcnrEnum = OftenEnum.FuncnrEnum.客商信息;
//        String funcnr = funcnrEnum.getFuncnr();
//
//        String key = "erp" + funcnrEnum.getFuncnr();
//        List<String> allnumbers = myRedisConfig.getRedisCache(key);
//        List<String> numbers = null;
//        if (allnumbers != null) {
//            //取前100的数据
//            numbers = allnumbers.stream().limit(100).collect(Collectors.toList());
//            JSONArray dataArrayALL = new JSONArray();
//            //循环近五年日期，
//            for (String number : numbers) {
//                // 构建req参数
//                Map<String, Object> req = new HashMap<>();
//                List<Map<String, String>> datumList = new ArrayList<>();
//                Map<String, String> datumEntry = new HashMap<>();
//                // 构建datum参数数组
//                datumEntry.put("sign", "I");
//                datumEntry.put("option", "EQ");
//                // 把每次循环的日期，放在这里
//                datumEntry.put("low", number);
//                datumList.add(datumEntry);
//                req.put("PARTNER", datumList);
//
//                // 1. 调用ERP接口获取数据
//                for (OftenEnum.ModeTypeEnum type : OftenEnum.ModeTypeEnum.values()) {
//                    req.put("MODE", type.modetype);
//                    HashMap<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()) {
//                return;
//            }
//
//            // 2. 处理数据，区分新增和更新
//            ProcessingResult result = processData(dataArrayALL, funcnrEnum);
//
//            // 3. 批量保存数据
//            saveData(result);
//        }
//    }

    /**
     * 处理数据，区分新增和更新
     */
    private ProcessingResult processData(JSONArray dataArray, OftenEnum.FuncnrEnum funcnr) {
        String key = "erp" + funcnr.getFuncnr();
        Map<String, List<String>> numbers = myRedisConfig.numbers(dataArray, key, funcnr.getDatakey());
        List<String> allnumbers = numbers.get("all");
        List<String> comnumbers = numbers.get("com");
        List<ErpCustomerDO> toUpdate = new ArrayList<>();
        List<ErpCustomerDO> toInsert = new ArrayList<>();

        for (int i = 0; i < dataArray.size(); i++) {
            JSONObject dataJson = dataArray.getJSONObject(i);
            if (dataJson != null) {
                String number = dataJson.getString("PARTNER");
                if (number != null) {
                    number = number.trim();
                }
                ErpCustomerDO DO = new ErpCustomerDO();
                DO.setName(dataJson.getString("NAME_ORG1"));
                DO.setNumber(number);
                DO.setAccountGroup(dataJson.getString("BU_GROUP"));
                DO.setDescription(dataJson.getString("BU_SORT1"));
                DO.setCenterNumber(dataJson.getString("BU_SORT2"));
                String crdat = dataJson.getString("CRDAT");
                if (crdat != null && !crdat.equals("0000-00-00")) {
                    DO.setCreateDate(LocalDateTime.parse(crdat + "T00:00:00"));
                }
                String chdat = dataJson.getString("CHDAT");
                if (chdat != null && !chdat.equals("0000-00-00")) {
                    DO.setRepairDate(LocalDateTime.parse(chdat + "T00:00:00"));
                }
                DO.setIsGiveback(dataJson.getString("XDELE"));
                DO.setIsProvisional(dataJson.getString("XBLCK"));
                DO.setTaxNumber(dataJson.getString("TAXNUM"));

                if (comnumbers.contains(number)) {
                    // 更新
                    toUpdate.add(DO);
                } else {
                    // 新增
                    toInsert.add(DO);
                }
            }
        }

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

    /**
     * 批量保存数据
     */
    private void saveData(ProcessingResult result) {
        // 批量新增和更新
        if (!result.toInsert.isEmpty()) {
            erpCustomerMapper.insertBatch(result.toInsert);
        }
        if (!result.toUpdate.isEmpty()) {
            erpCustomerMapper.updateBatchByNumber(result.toUpdate);
        }
//        myRedisConfig.updateRedisCache(result.key, result.allnumbers);
    }

    /**
     * 数据处理结果封装类
     */
    private static class ProcessingResult {
        private final List<ErpCustomerDO> toUpdate;
        private final List<ErpCustomerDO> toInsert;
        private final String key;
        private final List<String> allnumbers;

        public ProcessingResult(List<ErpCustomerDO> toUpdate, List<ErpCustomerDO> toInsert, String key, List<String> allnumbers) {
            this.toUpdate = toUpdate;
            this.toInsert = toInsert;
            this.key = key;
            this.allnumbers = allnumbers;
        }
    }

    private void initialize(String key) {
        List<String> existingNumbers = erpCustomerMapper.selectList(new LambdaQueryWrapperX<ErpCustomerDO>())
                .stream()
                .map(ErpCustomerDO::getNumber)
                .collect(Collectors.toList());
        myRedisConfig.updateRedisCache(key, existingNumbers);
    }
}