package com.zg.project.wisdom.service.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import com.zg.common.exception.ServiceException;
import com.zg.common.utils.DateUtils;
import com.zg.common.utils.StringUtils;
import com.zg.project.wisdom.domain.GysJh;
import com.zg.project.wisdom.domain.RkInfo;
import com.zg.project.wisdom.domain.vo.RecordStatisticVO;
import com.zg.project.wisdom.mapper.GysJhMapper;
import com.zg.project.wisdom.mapper.RkBillMapper;
import com.zg.project.wisdom.mapper.RkInfoMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zg.project.wisdom.mapper.RkRecordMapper;
import com.zg.project.wisdom.domain.RkRecord;
import com.zg.project.wisdom.service.IRkRecordService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 出入库记录Service业务层处理
 * 
 * @author zg
 * @date 2026-01-20
 */
@Service
public class RkRecordServiceImpl implements IRkRecordService 
{
    @Autowired
    private RkRecordMapper rkRecordMapper;

    @Autowired
    private RkInfoMapper rkInfoMapper;

    @Autowired
    private RkBillMapper rkBillMapper;

    @Autowired
    private GysJhMapper gysJhMapper;

    /**
     * 查询出入库记录
     * 
     * @param id 出入库记录主键
     * @return 出入库记录
     */
    @Override
    public RkRecord selectRkRecordById(Long id)
    {
        return rkRecordMapper.selectRkRecordById(id);
    }

    @Override
    public List<RkRecord> selectRkRecordListByBillNo(String billNo)
    {
        return rkRecordMapper.selectRkRecordListByBillNo(billNo);
    }

    /**
     * 查询出入库记录列表
     * 
     * @param rkRecord 出入库记录
     * @return 出入库记录
     */
    @Override
    public List<RkRecord> selectRkRecordList(RkRecord rkRecord)
    {
        return rkRecordMapper.selectRkRecordList(rkRecord);
    }

    /**
     * 新增出入库记录
     * 
     * @param rkRecord 出入库记录
     * @return 结果
     */
    @Override
    public int insertRkRecord(RkRecord rkRecord)
    {
        rkRecord.setCreateTime(DateUtils.getNowDate());
        return rkRecordMapper.insertRkRecord(rkRecord);
    }

    /**
     * 修改出入库记录
     *
     * 业务约定：
     * 1. rk_record.real_qty  —— 单条出入库记录的最终数量（绝对值）
     * 2. rk_info.real_qty    —— 当前库存数量
     * 3. gys_jh.real_qty     —— 供应计划累计已入库数量
     *
     * 入库（bizType = 0）：
     * - 使用【新值 - 旧值】差量修正供应计划 real_qty
     * - 严禁累计入库数量超过计划数量 jh_qty
     * - 自动维护供应计划状态：
     *      real_qty == 0        → 未到货
     *      0 < real_qty < jh_qty→ 部分到货
     *      real_qty == jh_qty   → 已入库
     *
     * 出库（bizType = 1）：
     * - 出库数量不得超过库存
     * - 出库数量变化联动库存 real_qty
     * - 库存为 0 时 is_chuku = 1，否则 = 0
     *
     * @param rkRecord 出入库记录
     * @return 影响行数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateRkRecord(RkRecord rkRecord) {

        /* ====================== 1. 基础校验 ====================== */
        if (rkRecord == null || rkRecord.getId() == null) {
            throw new RuntimeException("出入库记录ID不能为空");
        }

        rkRecord.setUpdateTime(DateUtils.getNowDate());

        /* ====================== 2. 查询原记录（唯一可信来源） ====================== */
        RkRecord oldRecord = rkRecordMapper.selectRkRecordById(rkRecord.getId());
        if (oldRecord == null) {
            throw new RuntimeException("原出入库记录不存在");
        }

        /* ====================== 3. 获取并校验库存ID（必须来自 oldRecord） ====================== */
        Long rkInfoId = oldRecord.getRkInfoId();
        if (rkInfoId == null) {
            throw new RuntimeException("出入库记录未关联库存，禁止修改");
        }

        RkInfo info = rkInfoMapper.selectRkInfoById(rkInfoId);
        if (info == null) {
            throw new RuntimeException("关联的库存记录不存在");
        }

        String bizType = rkRecord.getBizType();

        /* =========================================================
         * 【A】入库记录修改（bizType = 0）
         * ========================================================= */
        if ("0".equals(bizType)) {

            BigDecimal oldInQty = oldRecord.getRealQty() == null
                    ? BigDecimal.ZERO
                    : oldRecord.getRealQty();

            BigDecimal newInQty = rkRecord.getRealQty() == null
                    ? BigDecimal.ZERO
                    : rkRecord.getRealQty();

            BigDecimal diff = newInQty.subtract(oldInQty);

            /* ---------- 供应计划处理 ---------- */
            Long gysJhId = oldRecord.getGysJhId();
            if (gysJhId != null) {

                GysJh gysJh = gysJhMapper.selectGysJhById(gysJhId);
                if (gysJh == null) {
                    throw new RuntimeException("关联的供应计划不存在，ID：" + gysJhId);
                }

                BigDecimal planQty = gysJh.getJhQty();
                BigDecimal planRealQty = gysJh.getRealQty() == null
                        ? BigDecimal.ZERO
                        : gysJh.getRealQty();

                BigDecimal newPlanRealQty = planRealQty.add(diff);

                if (planQty != null && newPlanRealQty.compareTo(planQty) > 0) {
                    throw new RuntimeException("调整后已入库数量不能大于供应计划数量");
                }

                gysJh.setRealQty(newPlanRealQty);

                if (newPlanRealQty.compareTo(BigDecimal.ZERO) == 0) {
                    gysJh.setStatus("0"); // 未到货
                } else if (planQty != null && newPlanRealQty.compareTo(planQty) >= 0) {
                    gysJh.setStatus("1"); // 已入库
                } else {
                    gysJh.setStatus("2"); // 部分入库
                }

                gysJh.setWlNo(rkRecord.getWlNo());
                gysJh.setWlMs(rkRecord.getWlMs());
                gysJh.setXmNo(rkRecord.getXmNo());
                gysJh.setXmMs(rkRecord.getXmMs());
                gysJh.setGysNo(rkRecord.getGysNo());
                gysJh.setGysMc(rkRecord.getGysMc());
                gysJh.setDw(rkRecord.getDw());
                gysJh.setHtDj(rkRecord.getHtDj());
                gysJh.setUpdateTime(DateUtils.getNowDate());

                gysJhMapper.updateGysJh(gysJh);
            }

            /* ---------- 同步库存（明确字段，禁止 BeanUtils） ---------- */
            info.setRealQty(newInQty);
            info.setWlNo(rkRecord.getWlNo());
            info.setWlMs(rkRecord.getWlMs());
            info.setXmNo(rkRecord.getXmNo());
            info.setXmMs(rkRecord.getXmMs());
            info.setGysNo(rkRecord.getGysNo());
            info.setGysMc(rkRecord.getGysMc());
            info.setDw(rkRecord.getDw());
            info.setHtDj(rkRecord.getHtDj());
            info.setCangku(rkRecord.getCangku());
            info.setPcode(rkRecord.getPcode());
            info.setIsChuku("0");
        }

        /* =========================================================
         * 【B】出库记录修改（bizType = 1）
         * ========================================================= */
        if ("1".equals(bizType)) {

            BigDecimal oldOutQty = oldRecord.getRealQty();
            BigDecimal newOutQty = rkRecord.getRealQty();
            BigDecimal stockQty = info.getRealQty();

            if (oldOutQty == null || newOutQty == null || stockQty == null) {
                throw new RuntimeException("数量数据异常，无法修改出库记录");
            }

            BigDecimal diff = newOutQty.subtract(oldOutQty);
            BigDecimal newStockQty = stockQty.subtract(diff);

            if (newStockQty.compareTo(BigDecimal.ZERO) < 0) {
                throw new RuntimeException("库存不足，无法修改出库数量");
            }

            info.setRealQty(newStockQty);
            info.setIsChuku(newStockQty.compareTo(BigDecimal.ZERO) == 0 ? "1" : "0");

            info.setWlNo(rkRecord.getWlNo());
            info.setWlMs(rkRecord.getWlMs());
            info.setXmNo(rkRecord.getXmNo());
            info.setXmMs(rkRecord.getXmMs());
            info.setGysNo(rkRecord.getGysNo());
            info.setGysMc(rkRecord.getGysMc());
            info.setDw(rkRecord.getDw());
            info.setHtDj(rkRecord.getHtDj());
            info.setCangku(rkRecord.getCangku());
            info.setPcode(rkRecord.getPcode());
        }

        /* ====================== 4. 更新库存表 ====================== */
        info.setUpdateTime(DateUtils.getNowDate());
        int infoRows = rkInfoMapper.updateRkInfo(info);
        if (infoRows <= 0) {
            throw new RuntimeException("同步更新库存表失败");
        }

        /* ====================== 5. 最后更新 rk_record ====================== */
        rkRecord.setRkInfoId(rkInfoId); // 强制回填，防止被置空
        int rows = rkRecordMapper.updateRkRecord(rkRecord);
        if (rows <= 0) {
            throw new RuntimeException("更新出入库记录失败");
        }

        return rows;
    }

    /**
     * 批量删除出入库记录
     * 
     * @param ids 需要删除的出入库记录主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteRkRecordByIds(Long[] ids) {

        if (ids == null || ids.length == 0) {
            return 0;
        }

        // ================== 1. 查询 record ==================
        List<RkRecord> records = rkRecordMapper.selectRkRecordByIds(Arrays.asList(ids));
        if (records == null || records.isEmpty()) {
            return 0;
        }

        // ================== 2. 校验 record 必须全部是预入库 ==================
        boolean hasFinishedRecord = records.stream()
                .anyMatch(r -> r.getExecStatus() == null || !"0".equals(r.getExecStatus()));
        if (hasFinishedRecord) {
            throw new ServiceException("仅允许删除预入库/预出库的出入库记录");
        }

        // ================== 3. 回滚供应计划已入库数量 + 状态 ==================
        Map<Long, BigDecimal> rollbackMap = records.stream()
                .filter(r -> r.getGysJhId() != null && r.getRealQty() != null)
                .collect(Collectors.groupingBy(
                        RkRecord::getGysJhId,
                        Collectors.mapping(
                                RkRecord::getRealQty,
                                Collectors.reducing(BigDecimal.ZERO, BigDecimal::add)
                        )
                ));

        for (Map.Entry<Long, BigDecimal> entry : rollbackMap.entrySet()) {

            Long jhId = entry.getKey();
            BigDecimal rollbackQty = entry.getValue();

            // 1️⃣ 回滚数量
            gysJhMapper.rollbackInQty(jhId, rollbackQty);

            // 2️⃣ 判断回滚后数量是否为 0
            BigDecimal remainQty = gysJhMapper.selectRealQtyById(jhId);

            if (remainQty == null || remainQty.compareTo(BigDecimal.ZERO) == 0) {
                // 3️⃣ 已入库数量为 0，回退状态
                gysJhMapper.updateStatus(jhId, "0"); // 0=未入库
            }
        }

        // ================== 4. 收集 rkInfoId ==================
        List<Long> rkInfoIds = records.stream()
                .map(RkRecord::getRkInfoId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());

        // ================== 5. 校验 info 也必须是预入库 ==================
        if (!rkInfoIds.isEmpty()) {
            int invalidCount = rkInfoMapper.countNotPreByIds(rkInfoIds);
            if (invalidCount > 0) {
                throw new ServiceException("存在非预入库的库存明细，不允许删除");
            }

            // 先删 info
            rkInfoMapper.deleteRkInfoByIds(rkInfoIds.toArray(new Long[0]));
        }

        // ================== 6. 删除 record ==================
        int deleteCount = rkRecordMapper.deleteRkRecordByIds(ids);

        // ================== 7. 判断是否需要更新 bill 状态 ==================
        Set<String> billNos = records.stream()
                .map(RkRecord::getBillNo)
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.toSet());

        for (String billNo : billNos) {
            int remainPreCount = rkRecordMapper.countPreByBillNo(billNo);
            if (remainPreCount == 0) {
                rkBillMapper.updateExecStatus(billNo, "1");
            }
        }

        return deleteCount;
    }


    /**
     * 删除出入库记录信息
     * 
     * @param id 出入库记录主键
     * @return 结果
     */
    @Override
    public int deleteRkRecordById(Long id)
    {
        return rkRecordMapper.deleteRkRecordById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int rollbackToPreIn(List<Long> recordIds) {

        if (recordIds == null || recordIds.isEmpty()) {
            throw new ServiceException("撤销记录ID不能为空");
        }

        /* ====================== 1️⃣ 查询入库记录 ====================== */
        List<RkRecord> recordList = rkRecordMapper.selectRkRecordByIds(recordIds);
        if (recordList == null || recordList.isEmpty()) {
            throw new ServiceException("入库记录不存在");
        }

        /* ====================== 2️⃣ 校验是否发生过移库 ====================== */
        List<Long> rkInfoIds = recordList.stream()
                .map(RkRecord::getRkInfoId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());

        if (!rkInfoIds.isEmpty()) {

            // 查询对应库存
            List<RkInfo> infoList = rkInfoMapper.selectRkInfoByIds(rkInfoIds);

            // 只要有一条 has_moved = 1，直接禁止撤销
            boolean hasMoved = infoList.stream()
                    .anyMatch(info -> "1".equals(info.getHasMoved()));

            if (hasMoved) {
                throw new ServiceException("存在已移库的库存数据，禁止撤销入库");
            }
        }

        /* ====================== 3️⃣ rk_record 回退为预入库 ====================== */
        rkRecordMapper.updateExecStatusByIds(recordIds, "0");

        /* ====================== 4️⃣ rk_info 回退为预入库 ====================== */
        if (!rkInfoIds.isEmpty()) {
            rkInfoMapper.updateExecStatusByIds(rkInfoIds, "0");
        }

        /* ====================== 5️⃣ rk_bill 回退为预入库 ====================== */
        List<String> billNos = recordList.stream()
                .map(RkRecord::getBillNo)
                .filter(StringUtils::isNotBlank)
                .distinct()
                .collect(Collectors.toList());

        for (String billNo : billNos) {
            rkBillMapper.updateExecStatusByBillNo(billNo, "0");
        }

        return recordIds.size();
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public int finishIn(List<Long> recordIds) {

        if (recordIds == null || recordIds.isEmpty()) {
            throw new ServiceException("入库记录ID不能为空");
        }

        /* ================== 1. 查询 rk_record ================== */
        List<RkRecord> recordList = rkRecordMapper.selectRkRecordByIds(recordIds);
        if (recordList == null || recordList.isEmpty()) {
            throw new ServiceException("入库记录不存在");
        }

        /* ================== 2. 仅处理「预入库」记录 ================== */
        List<RkRecord> preRecordList = recordList.stream()
                .filter(r -> "0".equals(r.getExecStatus())) // 预入库
                .collect(Collectors.toList());

        if (preRecordList.isEmpty()) {
            throw new ServiceException("所选入库记录均已完成，无需重复入库");
        }

        /* ================== 3. 校验：完成入库数量 ≤ 计划交货数量 ================== */
        Map<Long, BigDecimal> finishQtyMap = new HashMap<>();

        for (RkRecord record : preRecordList) {
            if (record.getGysJhId() == null || record.getRealQty() == null) {
                continue;
            }
            finishQtyMap.merge(
                    record.getGysJhId(),
                    record.getRealQty(),
                    BigDecimal::add
            );
        }

        for (Map.Entry<Long, BigDecimal> entry : finishQtyMap.entrySet()) {

            Long gysJhId = entry.getKey();
            BigDecimal finishQty = entry.getValue();

            GysJh gysJh = gysJhMapper.selectGysJhById(gysJhId);
            if (gysJh == null) {
                throw new ServiceException("供应计划不存在，ID：" + gysJhId);
            }

            BigDecimal planQty = gysJh.getJhQty();
            if (planQty != null && finishQty.compareTo(planQty) > 0) {
                throw new ServiceException(
                        "一键入库数量超出供应计划数量，物料号：" + gysJh.getWlNo()
                                + "，计划数量：" + planQty
                                + "，本次完成入库：" + finishQty
                );
            }
        }

        /* ================== 4. 状态推进 ================== */

        // ① rk_record.exec_status = 1
        List<Long> preRecordIds = preRecordList.stream()
                .map(RkRecord::getId)
                .collect(Collectors.toList());

        rkRecordMapper.updateExecStatusByIds(preRecordIds, "1");

        // ② rk_info.exec_status = 1（只推进本次涉及的库存）
        List<Long> rkInfoIds = preRecordList.stream()
                .map(RkRecord::getRkInfoId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());

        if (!rkInfoIds.isEmpty()) {
            rkInfoMapper.updateExecStatusByIds(rkInfoIds, "1");
        }

        // ③ rk_bill.exec_status = 1（✅ 只有当 bill 下所有 record 均完成）
        Set<String> billNoSet = preRecordList.stream()
                .map(RkRecord::getBillNo)
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.toSet());

        for (String billNo : billNoSet) {

            // 查询该 bill 下是否仍存在 预入库 record
            int unFinishedCount = rkRecordMapper.countPreInRecordByBillNo(billNo);

            // 只有当不存在任何预入库 record 时，才推进 bill 状态
            if (unFinishedCount == 0) {
                rkBillMapper.updateExecStatusByBillNo(billNo, "1");
            }
        }

        /* ================== 5. 同步修正供应计划 ================== */
        for (Map.Entry<Long, BigDecimal> entry : finishQtyMap.entrySet()) {

            Long gysJhId = entry.getKey();
            BigDecimal finishQty = entry.getValue();

            // ① 修正实收数量
            gysJhMapper.updateRealQtyById(gysJhId, finishQty);

            // ② 修正状态
            GysJh gysJh = gysJhMapper.selectGysJhById(gysJhId);
            if (gysJh == null) {
                continue;
            }

            BigDecimal planQty = gysJh.getJhQty();
            BigDecimal realQty = gysJh.getRealQty();

            if (realQty == null || realQty.compareTo(BigDecimal.ZERO) == 0) {
                gysJhMapper.updateStatusById(gysJhId, "0"); // 未到货
            } else if (planQty != null && realQty.compareTo(planQty) >= 0) {
                gysJhMapper.updateStatusById(gysJhId, "1"); // 已入库
            } else {
                gysJhMapper.updateStatusById(gysJhId, "2"); // 部分入库
            }
        }

        return preRecordIds.size();
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public int rollbackOut(List<Long> recordIds) {

        if (recordIds == null || recordIds.isEmpty()) {
            throw new ServiceException("撤销出库记录ID不能为空");
        }

        // ================== 1. 查询出库记录 ==================
        List<RkRecord> recordList = rkRecordMapper.selectRkRecordByIds(recordIds);
        if (recordList == null || recordList.isEmpty()) {
            throw new ServiceException("出库记录不存在");
        }

        // 只允许撤销：已出库的出库记录
        for (RkRecord record : recordList) {
            if (!"1".equals(record.getBizType())) {
                throw new ServiceException("存在非出库记录，禁止撤销");
            }
            if (!"1".equals(record.getExecStatus())) {
                throw new ServiceException("只能撤销已出库记录");
            }
        }

        // ================== 2. 回滚库存 rk_info ==================
        for (RkRecord record : recordList) {

            Long rkInfoId = record.getRkInfoId();
            BigDecimal outQty = record.getRealQty();

            if (rkInfoId == null || outQty == null) {
                throw new ServiceException("出库记录数据不完整，无法撤销");
            }

            RkInfo info = rkInfoMapper.selectRkInfoById(rkInfoId);
            if (info == null) {
                throw new ServiceException("库存不存在，ID：" + rkInfoId);
            }

            BigDecimal oldQty = info.getRealQty();
            BigDecimal newQty = oldQty.add(outQty);

            // ① 补回库存数量
            rkInfoMapper.updateRealQtyById(rkInfoId, newQty);

            // ② 如果原库存为 0，说明 is_chuku=1，必须回退
            if (oldQty.compareTo(BigDecimal.ZERO) == 0) {
                rkInfoMapper.updateIsChukuById(rkInfoId, "0");
            }
        }

        // ================== 3. 回退出库记录状态 ==================
        rkRecordMapper.updateExecStatusByIds(recordIds, "0");

        // ================== 4. 回退主单 rk_bill ==================
        List<String> billNos = recordList.stream()
                .map(RkRecord::getBillNo)
                .filter(StringUtils::isNotBlank)
                .distinct()
                .collect(Collectors.toList());

        for (String billNo : billNos) {
            rkBillMapper.updateExecStatusByBillNo(billNo, "0");
        }

        return recordIds.size();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int finishOut(List<Long> recordIds) {

        if (recordIds == null || recordIds.isEmpty()) {
            throw new ServiceException("出库记录ID不能为空");
        }

        // ================== 1. 查询 rk_record ==================
        List<RkRecord> recordList = rkRecordMapper.selectRkRecordByIds(recordIds);
        if (recordList == null || recordList.isEmpty()) {
            throw new ServiceException("出库记录不存在");
        }

        // ================== 2. 只保留「预出库」记录 ==================
        List<RkRecord> preOutList = recordList.stream()
                .filter(r -> "1".equals(r.getBizType()))   // 出库
                .filter(r -> "0".equals(r.getExecStatus())) // 预出库
                .collect(Collectors.toList());

        if (preOutList.isEmpty()) {
            throw new ServiceException("所选出库记录均已完成出库");
        }

        // ================== 3. 库存校验 + 扣减 ==================
        for (RkRecord record : preOutList) {

            Long rkInfoId = record.getRkInfoId();
            BigDecimal outQty = record.getRealQty();

            if (rkInfoId == null || outQty == null) {
                throw new ServiceException("出库记录数据不完整");
            }

            RkInfo info = rkInfoMapper.selectRkInfoById(rkInfoId);
            if (info == null) {
                throw new ServiceException("库存不存在，ID：" + rkInfoId);
            }

            BigDecimal remainQty = info.getRealQty();
            if (remainQty.compareTo(outQty) < 0) {
                throw new ServiceException(
                        "库存不足，库存ID：" + rkInfoId +
                                "，当前库存：" + remainQty +
                                "，出库数量：" + outQty
                );
            }

            BigDecimal newQty = remainQty.subtract(outQty);

            // 扣库存
            rkInfoMapper.updateRealQtyById(rkInfoId, newQty);

            // 同步出库状态
            if (newQty.compareTo(BigDecimal.ZERO) == 0) {
                rkInfoMapper.updateIsChukuById(rkInfoId, "1");
            }
        }

        // ================== 4. 推进状态 ==================

        // ① rk_record.exec_status = 1
        List<Long> preOutIds = preOutList.stream()
                .map(RkRecord::getId)
                .collect(Collectors.toList());
        rkRecordMapper.updateExecStatusByIds(preOutIds, "1");

        // ② rk_info.exec_status = 1
        List<Long> rkInfoIds = preOutList.stream()
                .map(RkRecord::getRkInfoId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        if (!rkInfoIds.isEmpty()) {
            rkInfoMapper.updateExecStatusByIds(rkInfoIds, "1");
        }

        // ③ rk_bill.exec_status = 1
        List<String> billNos = preOutList.stream()
                .map(RkRecord::getBillNo)
                .filter(StringUtils::isNotBlank)
                .distinct()
                .collect(Collectors.toList());
        for (String billNo : billNos) {
            rkBillMapper.updateExecStatusByBillNo(billNo, "1");
        }

        return preOutIds.size();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deletePreOutRecords(Long[] ids) {

        if (ids == null || ids.length == 0) {
            return 0;
        }

        // ================== 1. 查询 record ==================
        List<RkRecord> records =
                rkRecordMapper.selectRkRecordByIds(Arrays.asList(ids));

        if (records == null || records.isEmpty()) {
            return 0;
        }

        // ================== 2. 严格校验：只能删「预出库」 ==================
        boolean hasInvalid = records.stream().anyMatch(r ->
                !"1".equals(r.getBizType())          // 1 = 出库
                        || !"0".equals(r.getExecStatus())    // 0 = 预出库
        );

        if (hasInvalid) {
            throw new ServiceException("仅允许删除预出库记录");
        }

        // ================== 3. 删除 rk_record ==================
        int deleteCount = rkRecordMapper.deleteRkRecordByIds(ids);

        // ================== 4. 维护 bill 状态 ==================
        Set<String> billNos = records.stream()
                .map(RkRecord::getBillNo)
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.toSet());

        for (String billNo : billNos) {
            // 该单据下是否还存在预出库记录
            int remainPreOut =
                    rkRecordMapper.countPreOutByBillNo(billNo);

            if (remainPreOut == 0) {
                // 没有任何预出库记录了，单据可视情况回退或推进
                rkBillMapper.updateExecStatusByBillNo(billNo, "1");
            }
        }

        return deleteCount;
    }
    @Override
    public RecordStatisticVO getRecordStatistic(RkRecord query) {

        RecordStatisticVO vo = new RecordStatisticVO();
        vo.setInStatistic(rkRecordMapper.selectInRecordStatistic(query));
        vo.setOutStatistic(rkRecordMapper.selectOutRecordStatistic(query));
        return vo;
    }
}
