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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import cn.iocoder.yudao.module.pms.sap.service.IotSapService;
import cn.iocoder.yudao.module.pms.sap.vo.IotSapMaterialVO;
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 io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Tag(name = "管理后台 - SAP同步接口 物料主数据 领料单 SAP库存")
@RequestMapping("/pms/sapSync")
@RestController
@Validated
public class SapController {
    @Autowired
    private SapConnector sapConnector;
    @Autowired
    private SapOrgApi sapOrgApi;
    @Autowired
    private IotSapService iotSapService;

    @GetMapping("/callSapStock")
    @Operation(summary = "同步sap 库存接口")
    public String callSapStock() {
        try {
            JCoDestination destination = sapConnector.getDestination();
            JCoFunction function = destination.getRepository().getFunction("ZPMS_002");

            // 设置输入参数
            JCoParameterList input = function.getImportParameterList();
            input.setValue("IV_WERKS", "5022");

            // 执行 RFC 调用
            function.execute(destination);

            // 获取输出参数
            JCoParameterList output = function.getTableParameterList();
            JCoTable etStockTable = function.getTableParameterList().getTable("ET_STOCK");
            // JCoParameterList output = function.getExportParameterList();
            if (CollUtil.isNotEmpty(output)) {
                output.forEach(material -> {
                    System.out.println(material.getName());
                });
            }

            if (etStockTable != null && etStockTable.getNumRows() > 0) {
                BigDecimal jiage = BigDecimal.ZERO;
                // 库存地点集合
                Set<String> storageLocations = new HashSet<>();
                for (int i = 0; i < etStockTable.getNumRows(); i++) {
                    etStockTable.setRow(i);
                    System.out.println(String.format("行号 %d: 工厂=%s, 物料编码=%s, 物料描述=%s, 库存数量 非限制=%s, 库存地点编码=%s, 批次=%s \n" +
                                    "特殊库存=%s, 基本单位=%s, 质量检验=%s, 已冻结=%s, 库存价格=%s",
                            i,
                            etStockTable.getString("WERKS"),    // 工厂
                            etStockTable.getString("MATNR"),    // 物料编码
                            etStockTable.getString("MAKTX"),    // 物料描述
                            etStockTable.getBigDecimal("LABST"),    // 库存数量 非限制
                            etStockTable.getString("LGORT"),    // 库存地点编码
                            etStockTable.getString("CHARG"),    // 批次
                            etStockTable.getString("SOBKZ"),    // 特殊库存
                            // etStockTable.getString("PSPNR"),    // WBS 要素
                            // etStockTable.getString("POSID"),    // WBS 元素
                            etStockTable.getString("MEINS"),    // 基本单位
                            etStockTable.getString("INSME"),    // 质量检验
                            etStockTable.getString("SPEME"),    // 已冻结
                            etStockTable.getBigDecimal("JIAGE")     // 库存价格
                    ));
                    BigDecimal tempJiage = etStockTable.getBigDecimal("JIAGE");
                    String location = etStockTable.getString("LGORT");
                    storageLocations.add(location);
                    jiage = jiage.add(tempJiage);
                }
                System.out.println("总价格：" + jiage.toString());
                // 1. 逗号拼接所有库存地点输出一行
                String locationAll = storageLocations.stream()
                        .collect(Collectors.joining("、"));
                System.out.println("【所有库存地点汇总】：" + locationAll);
            }
            return "Material Info: " + output.getString("ET_STOCK");
        } catch (JCoException e) {
            return "Error calling SAP Stock: " + e.getMessage();
        }
    }

    /**
     * 同步SAP领料单 数据只有新增的情况
     * @return
     */
    @GetMapping("/callSapPickingList")
    @Operation(summary = "同步sap 领料单接口")
    public String callSapPickingList() {
        List<String> factoryCodes = factoryCodes();
        if (CollUtil.isEmpty(factoryCodes)) {
            return "No SAP Factory";
        }
        try {
            JCoDestination destination = sapConnector.getDestination();
            JCoFunction function = destination.getRepository().getFunction("ZPMS_006");
            if (ObjUtil.isEmpty(function)) {
                return "No SAP Function";
            }
            // 设置输入参数   暂时只同步2025年的数据
            JCoParameterList input = function.getImportParameterList();
            input.setValue("I_WERKS", "6006");
            // 暂时只设置同步 2025年后的 领料单 2025年之前的领料单 手动入库
            input.setValue("I_DATUM_F", "2025-06-15"); // 开始日期
            input.setValue("I_DATUM_T", "2025-12-31"); // 结束日期

            // 执行 RFC 调用
            function.execute(destination);

            // 获取输出参数
            JCoParameterList output = function.getTableParameterList();
            JCoTable headTable = function.getTableParameterList().getTable("T_HEAD");
            // JCoParameterList output = function.getExportParameterList();
            if (CollUtil.isNotEmpty(output)) {
                output.forEach(material -> {
                    // System.out.println(material.getName());
                });
            }
            if (headTable != null && headTable.getNumRows() > 0) {
                for (int i = 0; i < headTable.getNumRows(); i++) {
                    headTable.setRow(i);
                    String TXTMD = headTable.getString("TXTMD");
                    System.out.println(String.format("行号 %d: 工厂=%s, 名称 1=%s, 领料/退料编号=%s, 领料/退料单名称=%s, " +
                                    "日期=%tT, 项目定义=%s, WBS 元素=%s, 描述=%s, 所属项目部=%s, 所属项目部描述=%s, 成本中心=%s, 成本中心描述=%s\n",
                            i,
                            headTable.getString("WERKS"),   // 工厂code
                            headTable.getString("TXTMD"),   // 工厂名称
                            headTable.getString("ZLTNO"),   // 领料/退料编号
                            headTable.getString("ZLLLX"),   // 领料/退料单名称
                            headTable.getDate("DATUM"),   // 日期
                            headTable.getString("PSPID"),   // 项目定义
                            headTable.getString("POSID"),   // WBS元素
                            headTable.getString("POST1"),   // 描述 50032队/YB058-H02井
                            headTable.getString("ZSSXMB"),  // 所属项目部
                            headTable.getString("LGOBE"),   // 所属项目部描述
                            headTable.getString("KOSTL"),   // 成本中心
                            headTable.getString("LTEXT")    // 成本中心描述
                    ));
                }
            }

            JCoTable itemTable = function.getTableParameterList().getTable("T_ITEM");
            if (itemTable != null && itemTable.getNumRows() > 0) {
                for (int i = 0; i < itemTable.getNumRows(); i++) {
                    itemTable.setRow(i);
                    String MATNR = itemTable.getString("MATNR");
                    if ("2000000040".equals(MATNR)) {
                        System.out.println(String.format("行号 %d: 工厂编号=%s, 领料/退料编号=%s, 物料编码=%s, 物料描述=%s, " +
                                        "物料数量=%s, 基本单位=%s, 特殊库存=%s, 移动原因=%s, 原因=%s, 库存地点编码=%s, 库存地点描述=%s, 库存仓位=%s, 批次=%s, 转入工厂=%s\n" +
                                        "备注=%s, 物料凭证编号=%s, 物料凭证年度=%s, 行项目号=%s, 本位币金额(单价)=%s, 货币码=%s, 交易后库存数量 - 以输入单位计=%s, 本位币库存总价值=%s, 价格控制标识=%s, 移动平均价或标准价=%s\n",
                                i,
                                itemTable.getString("WERKS"),       // 工厂编号
                                itemTable.getString("ZLTNO"),       // 领料/退料编号
                                itemTable.getString("MATNR"),       // 物料编码
                                itemTable.getString("MAKTX"),       // 物料描述
                                itemTable.getBigDecimal("MENGE"),   // 物料数量
                                itemTable.getString("MEINS"),       // 基本单位
                                itemTable.getString("SOBKZ"),       // 特殊库存
                                itemTable.getString("GRUND"),       // 移动原因
                                itemTable.getString("GRTXT"),       // 原因
                                itemTable.getString("LGORT"),       // 库存地点编码
                                itemTable.getString("LGOBE"),       // 库存地点描述
                                itemTable.getString("LGPBE"),       // 库存仓位
                                itemTable.getString("CHARG"),       // 批次
                                itemTable.getString("WERKS_ZR"),    // 转入工厂
                                itemTable.getString("BEIZHU"),      // 备注
                                // 无文档描述
                                itemTable.getString("MBLNR"),       // 物料凭证编号
                                itemTable.getString("MJAHR"),       // 物料凭证年度
                                itemTable.getString("ZEILE"),       // 行项目号
                                itemTable.getBigDecimal("DMBTR"),   // 本位币金额(单价)
                                itemTable.getString("WAERS"),       // 货币码
                                itemTable.getBigDecimal("LBKUM"),   // 交易后库存数量 - 以输入单位计
                                itemTable.getBigDecimal("SALK3"),   // 本位币库存总价值
                                itemTable.getString("VPRSV"),       // 价格控制标识
                                itemTable.getBigDecimal("VERPR")    // 移动平均价或标准价
                        ));
                    }
                }
            }

            return "Material Info: " + output.getString("T_HEAD");
        } catch (JCoException e) {
            return "Error calling SAP Picking List: " + e.getMessage();
        }
    }

    @GetMapping("/callSapMaterialMasterData")
    @Operation(summary = "同步sap 物料主数据接口")
    public String callSapMaterialMasterData() {
        //
        try {
            JCoDestination destination = sapConnector.getDestination();
            JCoFunction function = destination.getRepository().getFunction("ZPMS_005");

            // 设置输入参数
            JCoParameterList input = function.getImportParameterList();
            input.setValue("IV_LAEDA", ""); // 上次更改的日期
            input.setValue("IV_MATNR", ""); // 物料编号
            input.setValue("IV_MAKTX", ""); // 物料描述

            // 执行 RFC 调用
            function.execute(destination);

            // 获取输出参数
            JCoParameterList output = function.getTableParameterList();
            JCoTable otItabTable = function.getTableParameterList().getTable("OT_ITAB");
            if (CollUtil.isNotEmpty(output)) {
                output.forEach(material -> {
                    System.out.println(material.getName());
                });
            }
            if (otItabTable != null && otItabTable.getNumRows() > 0) {
                List<IotSapMaterialVO> sapMaterials = new ArrayList<>();
                for (int i = 0; i < otItabTable.getNumRows(); i++) {
                    otItabTable.setRow(i);
                    IotSapMaterialVO tempMaterial = new IotSapMaterialVO();
                    tempMaterial.setMATNR(otItabTable.getString("MATNR"));
                    tempMaterial.setMAKTX(otItabTable.getString("MAKTX"));
                    tempMaterial.setMTART(otItabTable.getString("MTART"));
                    tempMaterial.setMTBEZ(otItabTable.getString("MTBEZ"));
                    tempMaterial.setMATKL(otItabTable.getString("MATKL"));
                    tempMaterial.setWGBEZ(otItabTable.getString("WGBEZ"));
                    tempMaterial.setLVORM(otItabTable.getString("LVORM"));
                    tempMaterial.setLVORM(otItabTable.getString("MEINS"));
                    sapMaterials.add(tempMaterial);
                    System.out.println(String.format("行号 %d: 物料编码=%s, 物料描述=%s, 物料类型=%s, 物料类型描述=%s, 物料组=%s, 物料组描述=%s, 集团级的DF=%s, 单位=%s\n",
                            i,
                            otItabTable.getString("MATNR"), // 物料编码
                            otItabTable.getString("MAKTX"), // 物料描述
                            otItabTable.getString("MTART"), // 物料类型
                            otItabTable.getString("MTBEZ"), // 物料类型描述
                            otItabTable.getString("MATKL"), // 物料组
                            otItabTable.getString("WGBEZ"), // 物料组描述
                            otItabTable.getString("LVORM"),  // 集团级的DF
                            otItabTable.getString("MEINS")  // 单位
                    ));
                }
                // iotSapService.processMaterials(sapMaterials);
            }
            return "Material Info: " + output.getString("OT_ITAB");
        } catch (JCoException e) {
            return "Error calling SAP Material Master Data: " + e.getMessage();
        }
    }

    @GetMapping("/callSapMaterialMasterDatas")
    @Operation(summary = "同步sap 物料主数据接口")
    public String callSapMaterialMasterDatas() {
        //
        try {
            JCoDestination destination = sapConnector.getDestination();
            JCoFunction function = destination.getRepository().getFunction("ZPMS_001");

            // 设置输入参数
            /* JCoParameterList input = function.getImportParameterList();
            input.setValue("IV_LAEDA", ""); // 上次更改的日期
            input.setValue("IV_MATNR", ""); // 物料编号
            input.setValue("IV_MAKTX", ""); // 物料描述 */

            // JCoTable materialRange = function.getTableParameterList().getTable("MATNR_RANGE");
            function.getImportParameterList().setValue("CODE", "LFA1");
            // 执行 RFC 调用
            function.execute(destination);

            // JCoParameterList returnParams = function.getExportParameterList();
            // String returnType = returnParams.getString("RETURN_TYPE");
            // String returnMessage = returnParams.getString("RETURN_MESSAGE");

            /* if ("E".equals(returnType) || "A".equals(returnType)) {
                throw new RuntimeException("SAP调用错误: " + returnMessage);
            } */
            List<SapMaterial> materialList = new ArrayList<>();
            // 处理返回的物料列表
            JCoTable timportTable = function.getTableParameterList().getTable("TIMPORT");
            JCoTable texportTable = function.getTableParameterList().getTable("TEXPORT");
            for (int i = 0; i < texportTable.getNumRows(); i++) {
                texportTable.setRow(i);

                // SapMaterial material = new SapMaterial();
                /* material.setMaterialNumber(materialTable.getString("MATERIAL"));
                material.setMaterialDescription(materialTable.getString("MATL_DESC"));
                material.setMaterialType(materialTable.getString("MATL_TYPE"));
                material.setPlant(materialTable.getString("PLANT"));
                material.setBaseUnit(materialTable.getString("BASE_UOM"));
                material.setIndustrySector(materialTable.getString("INDUSTRY"));

                materialList.add(material); */
                System.out.println("当前供应商KV_CODE：" + texportTable.getString("KV_CODE"));
                System.out.println("当前供应商KV_NAME：" + texportTable.getString("KV_NAME"));
                System.out.println("当前供应商KV_KEY：" + texportTable.getString("KV_KEY"));
                System.out.println("当前供应商KV_VALUE：" + texportTable.getString("KV_VALUE"));
            }

            // 释放资源
            function.getTableParameterList().getTable("MATLIST").clear();

            // 获取输出参数
            JCoParameterList output = function.getTableParameterList();

            return "Material Info: " + output.getString("OT_ITAB");
        } catch (JCoException e) {
            return "Error calling SAP Material Master Data: " + e.getMessage();
        }
    }

    /**
     * 查询所有 SAP 工厂
     */
    private List<String> factoryCodes(){
        List<SapOrgRespDTO> sapOrgs = TenantUtils.execute(1L, () -> sapOrgApi.getSapOrgByType(1));

        if (CollUtil.isEmpty(sapOrgs)) {
            return CollUtil.empty(String.class);
        }
        List<String> factoryCodes = sapOrgs.stream()
                .map(SapOrgRespDTO::getFactoryCode)
                .collect(Collectors.toList());
        return CollUtil.isEmpty(factoryCodes) ? CollUtil.empty(String.class) : factoryCodes;
    }

    // 物料数据模型类
    public static class SapMaterial {
        private String materialNumber;
        private String materialDescription;
        private String materialType;
        private String plant;
        private String baseUnit;
        private String industrySector;

        // Getters and Setters
        public String getMaterialNumber() {
            return materialNumber;
        }

        public void setMaterialNumber(String materialNumber) {
            this.materialNumber = materialNumber;
        }

        public String getMaterialDescription() {
            return materialDescription;
        }

        public void setMaterialDescription(String materialDescription) {
            this.materialDescription = materialDescription;
        }

        public String getMaterialType() {
            return materialType;
        }

        public void setMaterialType(String materialType) {
            this.materialType = materialType;
        }

        public String getPlant() {
            return plant;
        }

        public void setPlant(String plant) {
            this.plant = plant;
        }

        public String getBaseUnit() {
            return baseUnit;
        }

        public void setBaseUnit(String baseUnit) {
            this.baseUnit = baseUnit;
        }

        public String getIndustrySector() {
            return industrySector;
        }

        public void setIndustrySector(String industrySector) {
            this.industrySector = industrySector;
        }

        @Override
        public String toString() {
            return "SapMaterial{" +
                    "materialNumber='" + materialNumber + '\'' +
                    ", materialDescription='" + materialDescription + '\'' +
                    ", materialType='" + materialType + '\'' +
                    ", plant='" + plant + '\'' +
                    ", baseUnit='" + baseUnit + '\'' +
                    ", industrySector='" + industrySector + '\'' +
                    '}';
        }
    }
}