package cn.iocoder.yudao.module.pms.job.sap;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
import cn.iocoder.yudao.module.pms.dal.mysql.iotsappickinglist.IotSapPickingListMapper;
import cn.iocoder.yudao.module.pms.sap.SapConnector;
import cn.iocoder.yudao.module.pms.sap.service.IotSapService;
import cn.iocoder.yudao.module.pms.sap.vo.IotSapPickingListHeadVO;
import cn.iocoder.yudao.module.pms.sap.vo.IotSapPickingListItemVO;
import cn.iocoder.yudao.module.system.api.saporg.SapOrgApi;
import cn.iocoder.yudao.module.system.api.saporg.dto.SapOrgRespDTO;
import com.sap.conn.jco.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.module.pms.framework.config.MultiThreadConfiguration.PMS_THREAD_POOL_TASK_EXECUTOR;

/**
 * 同步 SAP 领料单 定时任务
 */
@Component
@Slf4j
public class SyncSapPickingListJob implements JobHandler {
    @Autowired
    private SapConnector sapConnector;
    @Autowired
    private SapOrgApi sapOrgApi;
    @Autowired
    private IotSapPickingListMapper sapPickingListMapper;
    @Resource(name = PMS_THREAD_POOL_TASK_EXECUTOR)
    private ThreadPoolTaskExecutor pmsThreadPoolTaskExecutor;
    @Autowired
    private IotSapService iotSapService;

    @Override
    @TenantJob
    public String execute(String param) throws Exception {
        // 查询所有工厂 根据工厂 多线程处理 领料单
        List<String> factoryCodes = factoryCodes();
        if (CollUtil.isEmpty(factoryCodes)) {
            return "No SAP Factory";
        }
        // 查询 SAP同步领料单 开始时间 结束时间 数据字典
        String startTime = DictFrameworkUtils.parseDictDataValue("iot_sap_pickinglist_synctime_range", "开始时间");
        String endTime = DictFrameworkUtils.parseDictDataValue("iot_sap_pickinglist_synctime_range", "结束时间");
        if (StrUtil.isEmpty(startTime) || StrUtil.isEmpty(endTime)) {
            return "No startTime or endTime";
        }
        factoryCodes.forEach(factory -> {
            CountDownLatch latch = new CountDownLatch(factoryCodes.size());
            pmsThreadPoolTaskExecutor.execute(() -> {
                try {
                    JCoDestination destination = sapConnector.getDestination();
                    JCoFunction function = destination.getRepository().getFunction("ZPMS_006");
                    if (ObjUtil.isNotEmpty(function)) {
                        // 设置输入参数
                        JCoParameterList input = function.getImportParameterList();
                        input.setValue("I_WERKS", factory);
                        // 暂时只设置同步 2025年后的 领料单 2025年之前的领料单 手动入库
                        input.setValue("I_DATUM_F", startTime); // 开始日期 必填
                        input.setValue("I_DATUM_T", endTime);   // 结束日期 必填
                        // 执行 RFC 调用
                        function.execute(destination);
                        // 获取输出参数
                        JCoParameterList output = function.getTableParameterList();
                        JCoTable headTable = function.getTableParameterList().getTable("T_HEAD");
                        System.out.println(factory + "当前工厂对应的领料单HEAD数量：" + headTable.getNumRows());
                        List<IotSapPickingListHeadVO> pickingListHeads = new ArrayList<>();
                        if (headTable != null && headTable.getNumRows() > 0) {
                            for (int i = 0; i < headTable.getNumRows(); i++) {
                                headTable.setRow(i);
                                IotSapPickingListHeadVO pickingListHead = new IotSapPickingListHeadVO();
                                pickingListHead.setWERKS(headTable.getString("WERKS"));
                                pickingListHead.setTXTMD(headTable.getString("TXTMD"));
                                pickingListHead.setZLTNO(headTable.getString("ZLTNO"));
                                pickingListHead.setZLLLX(headTable.getString("ZLLLX"));
                                pickingListHead.setDATUM(LocalDateTimeUtil.of(headTable.getDate("DATUM")));
                                pickingListHead.setPSPID(headTable.getString("PSPID"));
                                pickingListHead.setPOSID(headTable.getString("POSID"));
                                pickingListHead.setPOST1(headTable.getString("POST1"));
                                pickingListHead.setZSSXMB(headTable.getString("ZSSXMB"));
                                pickingListHead.setLGOBE(headTable.getString("LGOBE"));
                                pickingListHead.setKOSTL(headTable.getString("KOSTL"));
                                pickingListHead.setLTEXT(headTable.getString("LTEXT"));
                                pickingListHeads.add(pickingListHead);
                            }
                        }
                        // 清空函数继续下次请求
                        JCoTable itemTable = function.getTableParameterList().getTable("T_ITEM");
                        System.out.println(factory + "当前工厂对应的领料单ITEM数量：" + itemTable.getNumRows());
                        List<IotSapPickingListItemVO> pickingListItems = new ArrayList<>();
                        if (itemTable != null && itemTable.getNumRows() > 0) {
                            for (int i = 0; i < itemTable.getNumRows(); i++) {
                                itemTable.setRow(i);
                                IotSapPickingListItemVO pickingListItem = new IotSapPickingListItemVO();
                                pickingListItem.setWERKS(itemTable.getString("WERKS"));
                                pickingListItem.setZLTNO(itemTable.getString("ZLTNO"));
                                pickingListItem.setMATNR(itemTable.getString("MATNR"));
                                pickingListItem.setMAKTX(itemTable.getString("MAKTX"));
                                pickingListItem.setMENGE(itemTable.getBigDecimal("MENGE"));
                                pickingListItem.setMEINS(itemTable.getString("MEINS"));
                                pickingListItem.setSOBKZ(itemTable.getString("SOBKZ"));
                                pickingListItem.setGRUND(itemTable.getString("GRUND"));
                                pickingListItem.setGRTXT(itemTable.getString("GRTXT"));
                                pickingListItem.setLGORT(itemTable.getString("LGORT"));
                                pickingListItem.setLGOBE(itemTable.getString("LGOBE"));
                                pickingListItem.setCHARG(itemTable.getString("CHARG"));

                                pickingListItem.setWERKS_ZR(itemTable.getString("WERKS_ZR"));
                                pickingListItem.setBEIZHU(itemTable.getString("BEIZHU"));
                                pickingListItem.setMBLNR(itemTable.getString("MBLNR"));
                                pickingListItem.setMJAHR(itemTable.getString("MJAHR"));
                                pickingListItem.setZEILE(itemTable.getString("ZEILE"));
                                pickingListItem.setDMBTR(itemTable.getBigDecimal("DMBTR"));
                                pickingListItem.setWAERS(itemTable.getString("WAERS"));
                                pickingListItem.setLBKUM(itemTable.getBigDecimal("LBKUM"));
                                pickingListItem.setSALK3(itemTable.getBigDecimal("SALK3"));
                                pickingListItem.setVPRSV(itemTable.getString("VPRSV"));
                                pickingListItem.setVERPR(itemTable.getBigDecimal("VERPR"));
                                pickingListItems.add(pickingListItem);
                            }
                        }
                        // 处理头部表信息 和 明细表数据
                        if (CollUtil.isNotEmpty(pickingListHeads) && CollUtil.isNotEmpty(pickingListItems)) {
                            iotSapService.processPickingLists(factory, pickingListHeads, pickingListItems);
                        }
                    }
                } catch (JCoException e) {
                    // 记录调用接口异常日志
                    throw new RuntimeException(e);
                } finally {
                    latch.countDown();
                }
            });
        });
        return "Picking List Info: T_HEAD T_ITEM";
    }

    /**
     * 查询所有SAP工厂
     */
    private List<String> factoryCodes(){
        List<SapOrgRespDTO> sapOrgs = sapOrgApi.getSapOrgByType(1);
        if (CollUtil.isEmpty(sapOrgs)) {
            return CollectionUtil.newArrayList();
        }
        List<String> factoryCodes = sapOrgs.stream()
                .filter(org -> ObjUtil.isNotEmpty(org.getStatus()) && org.getStatus() == 0)
                .map(SapOrgRespDTO::getFactoryCode)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        return CollUtil.isEmpty(factoryCodes) ? CollUtil.empty(String.class) : factoryCodes;
    }
}
