package com.zt.plat.module.contractorder.api;

import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.zt.plat.framework.common.pojo.CommonResult;
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.contractorder.api.dto.contract.ContractRespDTO;
import com.zt.plat.module.contractorder.api.dto.order.PrchOrdDtlDTO;
import com.zt.plat.module.contractorder.api.dto.order.PurchaseOrderWithDetailsDTO;
import com.zt.plat.module.contractorder.api.dto.order.SalesOrdDtlDTO;
import com.zt.plat.module.contractorder.api.vo.contract.international.*;
import com.zt.plat.module.contractorder.controller.admin.purchaseorder.vo.PurchaseOrderDetailsRespVO;
import com.zt.plat.module.contractorder.dal.dataobject.contract.ContractMainDO;
import com.zt.plat.module.contractorder.dal.dataobject.contract.ContractOtherFieldDO;
import com.zt.plat.module.contractorder.dal.dataobject.contract.ContractOtherFormDO;
import com.zt.plat.module.contractorder.dal.dataobject.contract.SystemRelativityDO;
import com.zt.plat.module.contractorder.dal.dataobject.purchaseorder.PrchOrdDtlDO;
import com.zt.plat.module.contractorder.dal.dataobject.purchaseorder.PurchaseOrderDO;
import com.zt.plat.module.contractorder.dal.dataobject.salesorder.SalesOrderDO;
import com.zt.plat.module.contractorder.dal.dataobject.salesorder.SalesOrderDetailDO;
import com.zt.plat.module.contractorder.dal.mysql.contract.ContractMainMapper;
import com.zt.plat.module.contractorder.dal.mysql.contract.ContractOtherFieldMapper;
import com.zt.plat.module.contractorder.dal.mysql.contract.ContractOtherFormMapper;
import com.zt.plat.module.contractorder.dal.mysql.contract.SystemRelativityMapper;
import com.zt.plat.module.contractorder.dal.mysql.purchaseorder.PrchOrdDtlMapper;
import com.zt.plat.module.contractorder.dal.mysql.salesorder.SalesOrderDetailMapper;
import com.zt.plat.module.contractorder.dal.mysql.salesorder.SalesOrderMapper;
import com.zt.plat.module.contractorder.enums.contract.DictEnum;
import com.zt.plat.module.contractorder.service.contract.ContractService;
import com.zt.plat.module.contractorder.service.purchaseorder.PurchaseOrderService;
import com.zt.plat.module.contractorder.util.ShareServiceUtil;
import com.zt.plat.module.erp.controller.admin.erp.vo.ErpContractSaveReqVO;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.zt.plat.framework.common.pojo.CommonResult.success;
import static com.zt.plat.module.contractorder.enums.ErrorCodeConstants.*;

@RestController
@Validated
@Slf4j
public class ContractApiImpl implements ContractApi {

    @Resource
    private ContractService contractService;
    @Resource
    private PurchaseOrderService purchaseOrderService;
    @Resource
    private ContractMainMapper contractMainMapper;
    @Resource
    private ContractOtherFormMapper contractOtherFormMapper;
    @Resource
    private ContractOtherFieldMapper contractOtherFieldMapper;
    @Resource
    private SystemRelativityMapper systemRelativityMapper;
    @Autowired
    private ShareServiceUtil shareServiceUtil;

    @Override
    public ContractRespDTO getContractByPaperNumber(String contractPaperNumber) {
        return contractService.getFormulasByPaperNumber(contractPaperNumber);
    }

    @Override
    public ContractRespDTO getFormulasBySysNumber(String contractSysNumber) {
        return contractService.getFormulasBySysNumber(contractSysNumber);
    }

    @Override
    public CommonResult<Boolean> updateOrderStatus(Long orderId, String status) {
        return success(purchaseOrderService.updateOrderStatus(orderId, status));
    }

    @Override
    public CommonResult<List<PurchaseOrderWithDetailsDTO>> getOrderByOrderNo(List<String> orderNoS) {
        List<PurchaseOrderDO> orderByNos = purchaseOrderService.getOrderByNos(orderNoS);
        if (orderByNos.isEmpty()) {
            return success(new ArrayList<>());
        }
        List<PurchaseOrderWithDetailsDTO> order = new ArrayList<>();
        List<String> purchaseOrderNoS = new ArrayList<>();
        List<String> salesOrdNoS = new ArrayList<>();
        orderByNos.forEach(f -> {
            if ("SALE".equals(f.getSplyBsnTp())) {
                // 销售订单
                salesOrdNoS.add(f.getSystemOrderNumber());
            } else {
                // 非销售订单（采购订单）
                purchaseOrderNoS.add(f.getSystemOrderNumber());
            }
        });

        // 处理采购订单详情
        List<PurchaseOrderWithDetailsDTO> purchaseOrderDetails = getPurchaseOrderDetails(purchaseOrderNoS);
        if (!purchaseOrderDetails.isEmpty()) {
            order.addAll(purchaseOrderDetails);
        }

        // 处理销售订单详情
        List<PurchaseOrderWithDetailsDTO> salesOrdDetails = getSalesOrdDetails(salesOrdNoS);
        if (!salesOrdDetails.isEmpty()) {
            order.addAll(salesOrdDetails);
        }
        return success(order);
    }

    private List<PurchaseOrderWithDetailsDTO> getSalesOrdDetails(List<String> orderNoS) {
        if (orderNoS.isEmpty()) {
            return new ArrayList<>();
        }
        SalesOrderMapper salesOrderMapper = SpringUtil.getBean(SalesOrderMapper.class);
        SalesOrderDetailMapper salesOrderDetailMapper = SpringUtil.getBean(SalesOrderDetailMapper.class);
        List<SalesOrderDO> salesOrderDOS = salesOrderMapper.selectList(SalesOrderDO::getSystemOrderNumber, orderNoS);
        if (salesOrderDOS.isEmpty()) {
            return new ArrayList<>();
        }
        List<PurchaseOrderWithDetailsDTO> purchaseOrderWithDetailsDTOS = BeanUtils.toBean(salesOrderDOS, PurchaseOrderWithDetailsDTO.class);
        purchaseOrderWithDetailsDTOS.forEach(purchaseOrderWithDetailsDTO -> {
            List<SalesOrderDetailDO> salesOrderDetailDOS = salesOrderDetailMapper.selectList(SalesOrderDetailDO::getOrderId, purchaseOrderWithDetailsDTO.getId());
            List<SalesOrdDtlDTO> salesOrdDtlDTOS = BeanUtils.toBean(salesOrderDetailDOS, SalesOrdDtlDTO.class);
            purchaseOrderWithDetailsDTO.setSalesOrdDtlDTOS(salesOrdDtlDTOS);
        });
        return purchaseOrderWithDetailsDTOS;
    }

    private List<PurchaseOrderWithDetailsDTO> getPurchaseOrderDetails(List<String> orderNoS) {
        if (orderNoS.isEmpty()) {
            return new ArrayList<>();
        }
        List<PurchaseOrderWithDetailsDTO> purchaseOrderWithDetailsDTOS = new ArrayList<>();
        List<PurchaseOrderDetailsRespVO> purchaseOrderWithDetailsVOS = purchaseOrderService.getOrderByOrderNo(orderNoS);
        purchaseOrderWithDetailsVOS.forEach(purchaseOrderWithDetailsVO -> {
            if (purchaseOrderWithDetailsVO != null) {
                PurchaseOrderWithDetailsDTO purchaseOrderWithDetailsDTO = BeanUtils.toBean(purchaseOrderWithDetailsVO, PurchaseOrderWithDetailsDTO.class);
                if (purchaseOrderWithDetailsVO.getOrderDetails().isEmpty()) {
                    purchaseOrderWithDetailsDTO.setPrchOrdDtlDTOS(new ArrayList<>());
                } else {
                    purchaseOrderWithDetailsDTO.setPrchOrdDtlDTOS(BeanUtils.toBean(purchaseOrderWithDetailsVO.getOrderDetails(), PrchOrdDtlDTO.class));
                }
                purchaseOrderWithDetailsDTOS.add(purchaseOrderWithDetailsDTO);
            }
        });
        return purchaseOrderWithDetailsDTOS;
    }

    @Transactional
    @Override
    public void push(@RequestBody IntPushContractReqVO pushReqVO) {

        log.info("接受到国贸系统推送的合同数据：{}", new JSONObject(pushReqVO));
        try {
            // 合同主信息表映射
            ContractMainDO contractMainDO = internationalToMainDO(pushReqVO.getData());

            // 逻辑处理
            // 操作标志 I 新增/更新；D 删除
            String operateFlag = pushReqVO.getData().getOperateFlag();
            // 合同唯一键
            String externalId = pushReqVO.getData().getContractId();
            // 系统合同ID
            Long contractId = null;
            // 查询系统关联合同
            SystemRelativityDO systemRelativityDO = systemRelativityMapper.selectOne("UP_ID", externalId);
            if ("I".equals(operateFlag)) {
                if (systemRelativityDO != null && systemRelativityDO.getDownId() != null) { // 修改合同
                    contractId = Long.parseLong(systemRelativityDO.getDownId());
                    contractMainDO.setId(contractId);
                    contractMainMapper.updateById(contractMainDO);
                } else { // 新增合同
                    contractMainMapper.insert(contractMainDO);
                    contractId = contractMainDO.getId();

                    // 生成关联数据
                    SystemRelativityDO saveRelation = new SystemRelativityDO();
                    saveRelation.setUpId(externalId);
                    saveRelation.setDownId(contractId.toString());
                    saveRelation.setWay(DictEnum.BSE_SYS_REL_WY_EXTERNAL.getCode());
                    saveRelation.setStatus(DictEnum.BSE_SYS_REL_TP_CONTRACT.getCode());
                    systemRelativityMapper.insert(saveRelation);
                }
            } else if ("D".equals(operateFlag)) {
                if (systemRelativityDO == null || systemRelativityDO.getDownId() == null) throw exception(CONTRACT_NOT_EXISTS);
                contractId = Long.parseLong(systemRelativityDO.getDownId());
                contractMainMapper.deleteById(contractId);
                // 删除动态条款信息
                contractOtherFormMapper.delete("CTRT_MAIN_ID", contractId.toString());
                contractOtherFieldMapper.delete("CTRT_MAIN_ID", contractId.toString());
                pushResult(pushReqVO, 1, null);
            } else {
                throw exception(CONTRACT_UNKNOWN_OPERATE);
            }

            // 根据客商信息列表提交多个合同映射到erp
            if (pushReqVO.getData().getPartnerList() == null || pushReqVO.getData().getPartnerList().isEmpty()) {
                throw exception(CONTRACT_PARTNER_NOT_EXISTS);
            }

            // 合同主信息-合同编号
            String contractPaperNumber = contractMainDO.getContractPaperNumber();
            // 合同主信息-合同名称
            String contractName = contractMainDO.getContractName();
            for (int i = 0; i < pushReqVO.getData().getPartnerList().size(); i++) {
                Partner partner = pushReqVO.getData().getPartnerList().get(i);

                // 根据客商信息设置合同信息
                // 合同编号
                contractMainDO.setContractPaperNumber(contractPaperNumber + "_" + String.format("%03d", (i+1)));
                pushReqVO.getData().getPartnerList().get(i)
                        .setErpContractPaperNumber(contractPaperNumber + "_" + String.format("%03d", (i+1)));
                // 合同名称
                contractMainDO.setContractName(contractName + "_" + String.format("%03d", (i+1)));
                // 境内/境外 -> 客商信息:境内/外
                contractMainDO.setIsDomestic(partner.getDomesticOrOverseas());
                // 乙方公司编号(销售方) -> 客商信息:供应商代码
                contractMainDO.setSalesCompanyNumber(partner.getPartnerCode());
                // ERP乙方公司编码
                contractMainDO.setErpSalesCompanyNumber(partner.getPartnerCode());
                // 乙方公司名称 -> 客商信息:供应商名称
                contractMainDO.setSalesCompanyName(partner.getPartnerName());
                // ERP乙方公司名称
                contractMainDO.setErpSalesCompanyName(partner.getPartnerName());

                // 生成ERP合同映射表
                ErpContractSaveReqVO erpContractVO = contractService.getErpContract(contractMainDO);

                // 调用ERP模块
//                JSONObject erpResult = contractService.sendToErp(erpContractVO);
//                log.info("合同提交ERP结果：{}", erpResult);
//
//                // 调用ERP失败
//                if (!erpResult.getBool("success")) {
//                    throw exception(CONTRACT_SUBMIT_ERP_FAIL, erpResult.getStr("errMsg"));
//                }
            }

            // 删除动态条款信息
            contractOtherFormMapper.delete("CTRT_MAIN_ID", contractId.toString());
            contractOtherFieldMapper.delete("CTRT_MAIN_ID", contractId.toString());

            // 请求参数保存到动态条款
            saveIntContractFields(pushReqVO.getData(), contractId);

            pushResult(pushReqVO, 1, null);
        } catch (Exception e) {
            log.info("国贸系统推送合同异常：{}", e.getMessage(), e);
            pushResult(pushReqVO, -1, e.getMessage());
        }
    }

    /**
     * 国贸合同信息未映射合同主信息字段保存到动态条款
     *
     * @param reqVO 国贸合同信息
     * @param contractId 合同主信息ID
     */
    private void saveIntContractFields(IntContract reqVO, Long contractId) {

        try {
            // 获取请求参数类结构
            Class<? extends IntContract> reqClass = reqVO.getClass();
            // 请求参数字段
            Field[] reqClassFields = reqClass.getDeclaredFields();

            // 条款明细表保存集合
            List<ContractOtherFieldDO> saveFields = new ArrayList<>();

            // 遍历字段
            for (Field reqClassField : reqClassFields) {

                reqClassField.setAccessible(true);

                // 获取字段说明
                Schema reqFieldSchema = reqClassField.getAnnotation(Schema.class);
                String reqFieldDesc = reqFieldSchema.description();

                // 获取字段对象
                Object reqFieldObj = reqClassField.get(reqVO);
                if (reqFieldObj != null) {
                    if (!"java.util.List".equals(reqClassField.getType().getName())) {
                        // 基础类型字段保存到条款明细表
                        ContractOtherFieldDO otherFieldDO = new ContractOtherFieldDO();
                        otherFieldDO.setContractMainId(contractId.toString());
                        otherFieldDO.setFieldNumber(reqClassField.getName());
                        otherFieldDO.setFieldName(reqFieldDesc);
                        otherFieldDO.setFieldValue(reqFieldObj.toString());
                        otherFieldDO.setFieldDescription(reqFieldDesc);
                        otherFieldDO.setType(reqClassField.getType().getName());
                        saveFields.add(otherFieldDO);
                    } else {
                        // list类型字段保存到条款表，再将字段保存到条款明细表
                        // 获取list类结构
                        Class<?> listClass = reqClassField.get(reqVO).getClass();
                        // 获取list迭代方法
                        Method iteratorMethod = listClass.getMethod("iterator");
                        // 获取迭代器
                        Iterator<?> iterator = (Iterator<?>) iteratorMethod.invoke(reqClassField.get(reqVO));
                        // 遍历
                        while (iterator.hasNext()) {

                            // 条款表保存
                            ContractOtherFormDO otherFormDO = new ContractOtherFormDO();
                            otherFormDO.setContractMainId(contractId);
                            otherFormDO.setFormNumber(reqClassField.getName());
                            otherFormDO.setFormName(reqFieldDesc);
                            otherFormDO.setFormDescription(reqFieldDesc);
                            contractOtherFormMapper.insert(otherFormDO);

                            // 条款表ID
                            Long otherFormDOId = otherFormDO.getId();

                            // 获取明细对象
                            Object detailObj = iterator.next();
                            // 获取明细对象类结构
                            Class<?> detailClass = detailObj.getClass();

                            // 条款明细表
                            if ("java.lang.String".equals(detailClass.getTypeName())) {
                                // 基础类型对应生成一条明细
                                ContractOtherFieldDO otherFieldDO = new ContractOtherFieldDO();
                                otherFieldDO.setContractMainId(contractId.toString());
                                otherFieldDO.setRelativityId(otherFormDOId);
                                otherFieldDO.setFieldNumber(detailClass.getTypeName());
                                otherFieldDO.setFieldName(reqFieldDesc);
                                otherFieldDO.setFieldValue(detailObj.toString());
                                otherFieldDO.setFieldDescription(reqFieldDesc);
                                otherFieldDO.setType(detailClass.getTypeName());
                                saveFields.add(otherFieldDO);
                            } else {
                                // 对象类型遍历字段保存对应明细
                                Field[] detailClassFields = detailClass.getDeclaredFields();
                                for (Field detailClassField : detailClassFields) {
                                    detailClassField.setAccessible(true);
                                    if (detailClassField.get(detailObj) != null) {
                                        ContractOtherFieldDO otherFieldDO = new ContractOtherFieldDO();
                                        otherFieldDO.setContractMainId(contractId.toString());
                                        otherFieldDO.setRelativityId(otherFormDOId);
                                        otherFieldDO.setFieldNumber(detailClassField.getName());
                                        otherFieldDO.setFieldName(detailClassField.getAnnotation(Schema.class).description());
                                        otherFieldDO.setFieldValue(detailClassField.get(detailObj).toString());
                                        otherFieldDO.setFieldDescription(detailClassField.getAnnotation(Schema.class).description());
                                        otherFieldDO.setType(detailClassField.getType().getName());
                                        saveFields.add(otherFieldDO);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // 条款明细表集合批量保存
            if (!saveFields.isEmpty()) {
                contractOtherFieldMapper.insertBatch(saveFields);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw exception(CONTRACT_PUSH_FAIL, e.getMessage());
        }
    }

    private void pushResult(IntPushContractReqVO pushReqVO, Integer code, String msg) {

        // 返回数据
        IntPushContractRespVO body = new IntPushContractRespVO();
        body.set__requestId_(pushReqVO.get__requestId__());
        body.set__interfaceType__("R_MY_JG_10");
        body.setBusiBillCode(pushReqVO.getBusiBillCode());
        body.setCode(code);
        body.setMessage(String.format("推送合同[%s]%s", pushReqVO.getBusiBillCode(), code >= 0 ? "成功" : "失败：" + msg));
        body.setDatetime(DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now()));
        body.setSystem("JYGK");
        body.setOperateFlag(pushReqVO.getOperateFlag());

        // 回调参数
        JSONObject req = new JSONObject();
        req.set("messageKey", "R_JG_MY_00");
        req.set("messageBody", body);
        try {
            log.info("国贸系统推送合同回调参数：{}",req);
            String res = shareServiceUtil.callShareService("S_EPLAT_04", req.toString());
            log.info("国贸系统推送合同回调成功：{}",res);
        } catch (Exception e) {
            log.error("国贸系统推送合同回调失败：{}",e.getMessage(), e);
        }
    }

    @Override
    public CommonResult<PageResult<IntContract>> logisticsListPage(IntContractPageReq pageReq) {

        // 查询条件
        LambdaQueryWrapperX<ContractMainDO> queryWrapperX = new LambdaQueryWrapperX<>();
        // 合同类型
        queryWrapperX.in(
                ContractMainDO::getBusinessType,
                Arrays.asList(
                        DictEnum.SPLY_BSN_TP_13HD.getCode(),
                        DictEnum.SPLY_BSN_TP_10YS.getCode(),
                        DictEnum.SPLY_BSN_TP_11CC.getCode(),
                        DictEnum.SPLY_BSN_TP_03BX.getCode()
                )
        );
        // 合同名称：模糊搜索
        queryWrapperX.likeIfPresent(ContractMainDO::getContractName, pageReq.getContractName());
        // 合同有效期起：日期选择
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        queryWrapperX.geIfPresent(ContractMainDO::getStartDate,
                pageReq.getContractStartDate() != null
                        ? LocalDateTime.of(LocalDate.parse(pageReq.getContractStartDate(), formatter), LocalTime.MIN)
                            .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
                        : null);
        // 合同有效期止：日期选择
        queryWrapperX.leIfPresent(ContractMainDO::getEndDate,
                pageReq.getContractEndDate() != null
                        ? LocalDateTime.of(LocalDate.parse(pageReq.getContractEndDate(), formatter), LocalTime.MAX)
                            .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
                        : null);
        // 签约地：模糊搜索
        queryWrapperX.likeIfPresent(ContractMainDO::getSignPlace, pageReq.getSignSite());
        // 经办人姓名：模糊搜索
        // 签约日期： 模糊搜索
        if (pageReq.getSignDate() != null) {
            queryWrapperX.apply("to_char(SGN_DT, 'yyyymmdd') like concat('%',{0},'%')", pageReq.getSignDate());
        }

        // 查询
        PageResult<ContractMainDO> pageResult = contractMainMapper.selectPage(pageReq, queryWrapperX);

        // 返回数据
        PageResult<IntContract> result = new PageResult<>();
        List<IntContract> resultList = new ArrayList<>();
        // 设置返回数据
        result.setTotal(pageResult.getTotal());
        result.setList(resultList);

        // 遍历查询结果，设置返回数据列表
        if (pageResult.getTotal() > 0) {
            pageResult.getList().forEach(contractMainDO
                    -> resultList.add(getIntContractByMainId(contractMainDO.getId())));
        }

        return success(result);
    }

    /**
     * 获取国贸合同信息通过合同主信息ID
     *
     * @param mainId 同主信息ID
     * @return 国贸合同信息
     */
    private IntContract getIntContractByMainId(Long mainId) {
        // 合同动态条款查询
        List<ContractOtherFormDO> otherFormDOs = contractOtherFormMapper.selectList(
                new LambdaQueryWrapperX<ContractOtherFormDO>()
                        .eq(ContractOtherFormDO::getContractMainId, mainId)
        );
        // 合同动态条款明细查询
        List<ContractOtherFieldDO> otherFieldDOs = contractOtherFieldMapper.selectList(
                new LambdaQueryWrapperX<ContractOtherFieldDO>()
                        .eq(ContractOtherFieldDO::getContractMainId, mainId)
        );

        JSONObject resultJson = new JSONObject();

        // 设置主信息
        otherFieldDOs.stream()
                .filter(otherFieldDO -> otherFieldDO.getRelativityId() == null)
                .forEach(otherFieldDO
                        -> resultJson.putOnce(otherFieldDO.getFieldNumber(), otherFieldDO.getFieldValue()));

        // 设置明细信息
        otherFormDOs.stream()
                .collect(Collectors.groupingBy(ContractOtherFormDO::getFormNumber))
                .forEach((key, value) -> {
                    JSONArray detailsJson = new JSONArray();
                    value.forEach(detail -> {
                        // 根据条款id筛选条款明细
                        Stream<ContractOtherFieldDO> stream = otherFieldDOs.stream()
                                .filter(otherFieldDO
                                        -> Objects.equals(otherFieldDO.getRelativityId(), detail.getId()));
                        if ("attachList".equals(key)) {
                            // 基础数据类型
                            stream.forEach(otherFieldDO
                                    -> detailsJson.add(otherFieldDO.getFieldValue()));
                        } else {
                            // 对象数据类型
                            JSONObject detailJson = new JSONObject();
                            stream.forEach(otherFieldDO
                                    -> detailJson.putOnce(otherFieldDO.getFieldNumber(), otherFieldDO.getFieldValue()));
                            detailsJson.add(detailJson);
                        }
                    });
                    resultJson.putOnce(key, detailsJson);
                });
        return resultJson.toBean(IntContract.class);
    }

    @Override
    public CommonResult<List<PurchaseOrderWithDetailsDTO>> getOrderByOrderIds(List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            throw new RuntimeException("订单id为空");
        }
        List<PurchaseOrderDO> ordersByIds = purchaseOrderService.getOrdersByIds(ids.stream().map(String::valueOf).toList());
        List<Long> purchaseOrderIds = new ArrayList<>();
        List<Long> salesOrderIds = new ArrayList<>();
        if (ordersByIds.isEmpty()) {
            return CommonResult.success(new ArrayList<>());
        }
        ordersByIds.forEach(o->{
            if ("SALE".equals(o.getSplyBsnTp())) {
                // 销售订单
                salesOrderIds.add(o.getId());
            } else {
                // 非销售订单（采购订单）
                purchaseOrderIds.add(o.getId());
            }
        });
        List<PurchaseOrderWithDetailsDTO> purchaseOrderDetails = getSalesOrdDetailsByIds(purchaseOrderIds);
        List<PurchaseOrderWithDetailsDTO> salesOrdDetails = getPurchaseOrderDetailsByIds(salesOrderIds);
        if (!purchaseOrderDetails.isEmpty()) {
            purchaseOrderDetails.addAll(salesOrdDetails);
        }
        if (!salesOrdDetails.isEmpty()) {
            purchaseOrderDetails.addAll(salesOrdDetails);
        }
        return CommonResult.success(purchaseOrderDetails);
    }

    /**
     * 国贸合同信息映射到合同主信息
     *
     * @param reqVO 国贸合同信息
     * @return 合同主信息
     */
    private ContractMainDO internationalToMainDO(IntContract reqVO) {

        // 合同主信息表映射
        ContractMainDO contractMainDO = new ContractMainDO();
        // 系统合同编号
        contractMainDO.setSystemContractNumber(contractService.generateSystemContractNumber(DictEnum.ERP_CTRT_HTLXBH_SAP02NCOZC.getCode()));
        // 合同编号
        contractMainDO.setContractPaperNumber(reqVO.getContractCode());
        // 合同名称
        contractMainDO.setContractName(reqVO.getContractName());
        // 施工类型编号 默认值:SAP02NCOZC
        contractMainDO.setConstructionTypeNumber(DictEnum.ERP_CTRT_HTLXBH_SAP02NCOZC.getCode());
        // 施工类型名称 默认值:铜非施工合同支出类
        contractMainDO.setConstructionTypeName(DictEnum.ERP_CTRT_HTLXBH_SAP02NCOZC.getLabel());
        // 类别 默认值:购销合同(1)
        contractMainDO.setCategory(DictEnum.ERP_CTRT_HTLB_1.getCode());
        // 是否虚拟合同 默认值:否(0)
        contractMainDO.setContractVirtual(DictEnum.ERP_CTRT_YN_NO.getCode());
        // 代理方 默认值:NULL
        // 签署日期 -> 签约日期 (40-签约必填)
        if (StringUtils.isNotEmpty(reqVO.getSignDate())) {
            contractMainDO.setSignDate(Instant.ofEpochMilli(Long.parseLong(reqVO.getSignDate()))
                    .atZone(ZoneId.systemDefault()).toLocalDateTime());
        }
        // 开始日期 -> 合同有效期起
        if (StringUtils.isNotEmpty(reqVO.getContractStartDate())) {
            contractMainDO.setStartDate(Instant.ofEpochMilli(Long.parseLong(reqVO.getContractStartDate()))
                    .atZone(ZoneId.systemDefault()).toLocalDateTime());
        }
        // 结束日期 -> 合同有效期止
        if (StringUtils.isNotEmpty(reqVO.getContractEndDate())) {
            contractMainDO.setEndDate(Instant.ofEpochMilli(Long.parseLong(reqVO.getContractEndDate()))
                    .atZone(ZoneId.systemDefault()).toLocalDateTime());
        }
        // 币种 -> 合同币种
        contractMainDO.setCurrency(reqVO.getCurrencyCode());
        // 原币金额 -> 预估含税总金额
        contractMainDO.setCooAmount(reqVO.getEstimateAmountTotal());
        // 原币金额-变更后
        contractMainDO.setChangeCooAmount(reqVO.getEstimateAmountTotal());
        // 本币金额 -> 预估含税总金额
        contractMainDO.setBasicAmount(reqVO.getEstimateAmountTotal());
        // 本币金额-变更后
        contractMainDO.setChangeBasicAmount(reqVO.getEstimateAmountTotal());
        // 状态 默认值:正在执行(EF) 执行中
        contractMainDO.setStatus(DictEnum.BSE_CTRT_STS_IN_PROGRESS.getCode());
        //设置erp状态为待上传
        contractMainDO.setErpStatus(DictEnum.ERP_REQ_STS_WAIT.getCode());
        // 是否有预付款 默认值:否
        contractMainDO.setHasPrepayment(DictEnum.ERP_CTRT_YN_NO.getCode());
        // 预付款比例 默认值:NULL
        // 预付款金额 默认值:NULL
        // 是否有质保金 默认值:否
        contractMainDO.setHasQualityAmount(DictEnum.ERP_CTRT_YN_NO.getCode());
        // 质保金比例 默认值:NULL
        // 质保金金额 默认值:NULL
        // 是否内部企业
        contractMainDO.setIsInternal(reqVO.getIsInternal());
        // 收支性质 默认值:支出
        contractMainDO.setDirection(DictEnum.ERP_RCV_DLVY_EXPENSES.getCode());
        // 是否框架合同
        contractMainDO.setIsFramework(reqVO.getIsFramework());
        // 建筑服务发生地 默认值:NULL
        // 达到收款条件金额 默认值:NULL
        // 是否有履约保证金 默认值:否
        contractMainDO.setHasDeposit(DictEnum.ERP_CTRT_YN_NO.getCode());
        // 原币履约保证金 默认值:NULL
        // 本币履约保证金 默认值:NULL
        // 交易方式 默认值:先款后货
        contractMainDO.setHasPayable(DictEnum.HS_PYBL_TP_PRE_PAY.getCode());
        // 合同类型
        contractMainDO.setBusinessType(reqVO.getContractType());
        // 签署地 -> 签约地 (40-签约必填)
        contractMainDO.setSignPlace(reqVO.getSignSite());
        // 甲方公司编号(采购方) -> 账套代码
        contractMainDO.setPurchaseCompanyNumber(reqVO.getBookId());
        // ERP甲方公司编号
        contractMainDO.setErpPurchaseCompanyNumber(reqVO.getBookId());
        // 甲方公司名称 -> 账套名称 null
        // ERP甲方公司名称
        contractMainDO.setErpPurchaseCompanyName("");
        // 甲方地址 默认值:NULL
        // 甲方法定代表人 默认值:NULL
        // 乙方地址 默认值:NULL
        // 乙方企业负责人 默认值:NULL

        return contractMainDO;
    }

    private List<PurchaseOrderWithDetailsDTO> getSalesOrdDetailsByIds(List<Long> ids) {
        if (ids.isEmpty()) {
            return new ArrayList<>();
        }
        SalesOrderMapper salesOrderMapper = SpringUtil.getBean(SalesOrderMapper.class);
        SalesOrderDetailMapper salesOrderDetailMapper = SpringUtil.getBean(SalesOrderDetailMapper.class);
        List<SalesOrderDO> salesOrderDOS = salesOrderMapper.selectList(SalesOrderDO::getId, ids);
        if (salesOrderDOS.isEmpty()) {
            return new ArrayList<>();
        }
        List<PurchaseOrderWithDetailsDTO> purchaseOrderWithDetailsDTOS = BeanUtils.toBean(salesOrderDOS, PurchaseOrderWithDetailsDTO.class);
        purchaseOrderWithDetailsDTOS.forEach(purchaseOrderWithDetailsDTO -> {
            List<SalesOrderDetailDO> salesOrderDetailDOS = salesOrderDetailMapper.selectList(SalesOrderDetailDO::getOrderId, purchaseOrderWithDetailsDTO.getId());
            List<SalesOrdDtlDTO> salesOrdDtlDTOS = BeanUtils.toBean(salesOrderDetailDOS, SalesOrdDtlDTO.class);
            purchaseOrderWithDetailsDTO.setSalesOrdDtlDTOS(salesOrdDtlDTOS);
        });
        return purchaseOrderWithDetailsDTOS;
    }

    private List<PurchaseOrderWithDetailsDTO> getPurchaseOrderDetailsByIds(List<Long> ids) {
        if (ids.isEmpty()) {
            return new ArrayList<>();
        }
        List<PurchaseOrderWithDetailsDTO> purchaseOrderWithDetailsDTOS = new ArrayList<>();
        List<PurchaseOrderDetailsRespVO> purchaseOrderWithDetailsVOS = purchaseOrderService.getOrderByIds(ids);
        purchaseOrderWithDetailsVOS.forEach(purchaseOrderWithDetailsVO -> {
            if (purchaseOrderWithDetailsVO != null) {
                PurchaseOrderWithDetailsDTO purchaseOrderWithDetailsDTO = BeanUtils.toBean(purchaseOrderWithDetailsVO, PurchaseOrderWithDetailsDTO.class);
                if (purchaseOrderWithDetailsVO.getOrderDetails().isEmpty()) {
                    purchaseOrderWithDetailsDTO.setPrchOrdDtlDTOS(new ArrayList<>());
                } else {
                    purchaseOrderWithDetailsDTO.setPrchOrdDtlDTOS(BeanUtils.toBean(purchaseOrderWithDetailsVO.getOrderDetails(), PrchOrdDtlDTO.class));
                }
                purchaseOrderWithDetailsDTOS.add(purchaseOrderWithDetailsDTO);
            }
        });
        return purchaseOrderWithDetailsDTOS;
    }

    @Override
    public CommonResult<SalesOrdDtlDTO> getSalesOrderDetailById(Long id) {
        SalesOrderDetailDO salesOrderDetailDO = SpringUtil.getBean(SalesOrderDetailMapper.class).selectOne(SalesOrderDetailDO::getId, id,SalesOrderDetailDO::getIsEnable,1);
        SalesOrdDtlDTO salesOrdDtlDTO = BeanUtils.toBean(salesOrderDetailDO, SalesOrdDtlDTO.class);
        salesOrdDtlDTO.setUnit(salesOrderDetailDO.getUnt());
        return success(salesOrdDtlDTO);
    }

    @Override
    public CommonResult<List<SalesOrdDtlDTO>> getSalesOrderDetailByIds(List<Long> ids) {
        List<SalesOrderDetailDO> salesOrderDetailDOS = SpringUtil.getBean(SalesOrderDetailMapper.class).selectList(SalesOrderDetailDO::getId, ids,SalesOrderDetailDO::getIsEnable,1);
        return success(BeanUtils.toBean(salesOrderDetailDOS, SalesOrdDtlDTO.class));
    }

    @Override
    public CommonResult<PrchOrdDtlDTO> getPoOrderDetailById(Long id) {
        PrchOrdDtlDO prchOrdDtlDO = SpringUtil.getBean(PrchOrdDtlMapper.class).selectOne(PrchOrdDtlDO::getId,id,PrchOrdDtlDO::getIsEnb,1);

        return  success(BeanUtils.toBean(prchOrdDtlDO, PrchOrdDtlDTO.class));
    }

    @Override
    public CommonResult<List<PrchOrdDtlDTO>> getPoOrderDetailByIds(List<Long> ids) {
        List<PrchOrdDtlDO> prchOrdDtlDOS = SpringUtil.getBean(PrchOrdDtlMapper.class).selectList(PrchOrdDtlDO::getId, ids,PrchOrdDtlDO::getIsEnb,1);
        return  success(BeanUtils.toBean(prchOrdDtlDOS, PrchOrdDtlDTO.class));
    }
}
