package com.ruoyi.asset.mapper;

import java.util.List;
import com.ruoyi.asset.domain.AmsAsset;
import com.ruoyi.asset.domain.AmsReceiveOrder;
import com.ruoyi.asset.domain.AmsReceiveOrderItem;
import org.apache.ibatis.annotations.Param;

/**
 * 资产领用管理数据访问接口 (Mapper)
 * 
 * 提供资产领用单（ams_receive_order）及领用明细表（ams_receive_order_item）的数据库 CRUD 操作。
 * 重点包含用于排他性控制的 `select...ForUpdate` 加锁查询，以及跨单据占用校验的计数与可用资产过滤逻辑。
 *
 * @author Yangk
 */
public interface AmsReceiveOrderMapper
{
    /**
     * 根据单据主键ID查询领用单详情，联查其包含的全部明细信息（用于详情页展示）
     */
    public AmsReceiveOrder selectAmsReceiveOrderByOrderId(Long orderId);

    /**
     * 根据单据主键ID查询领用单，并通过 `FOR UPDATE` 在数据库层层面对该行数据进行悲观锁排他锁定。
     * 业务意图：在提交、审核确认、驳回以及逻辑删除领用单前，必须先获取此排他锁，防止并发操作导致状态流转冲突或数据不一致。
     */
    public AmsReceiveOrder selectAmsReceiveOrderByOrderIdForUpdate(Long orderId);

    /**
     * 根据查询条件检索领用单列表，支持按单号、申请人姓名、申请部门、状态等进行联合筛选
     */
    public List<AmsReceiveOrder> selectAmsReceiveOrderList(AmsReceiveOrder amsReceiveOrder);

    /**
     * 查询当前可选用于领用的资产列表。
     * 业务意图：筛选处于在库状态（IN_STOCK）的资产，同时必须排除已被其他有效领用单（即处于“草稿”或“待确认”状态的领用单）占用的资产。
     * 支持在已有领用单编辑时排除当前领用单ID本身（允许当前单据内关联的资产继续被加载）。
     */
    public List<AmsAsset> selectAvailableReceiveAssetList(@Param("asset") AmsAsset amsAsset,
            @Param("currentOrderId") Long currentOrderId, @Param("stockStatus") String stockStatus,
            @Param("draftStatus") String draftStatus, @Param("pendingStatus") String pendingStatus);

    /**
     * 统计指定资产在其他活跃领用单（草稿、待确认状态）中被占用的次数。
     * 业务意图：用于在后端进行防并发重复占用的严密验证，返回值大于0表示此资产已被其他用户抢先锁定。
     */
    public int countOtherActiveReceiveOrderByAssetId(@Param("assetId") Long assetId,
            @Param("currentOrderId") Long currentOrderId, @Param("draftStatus") String draftStatus,
            @Param("pendingStatus") String pendingStatus);

    /**
     * 写入新增的领用单主表记录，自动返回并填充自增主键 `orderId`
     */
    public int insertAmsReceiveOrder(AmsReceiveOrder amsReceiveOrder);

    /**
     * 更新领用主表的非核心状态受控字段（例如更新备注等）。
     * 限制：为了防止越权或状态越级，此SQL在XML中必须限制 `order_status = 'DRAFT'` 条件。
     */
    public int updateAmsReceiveOrder(AmsReceiveOrder amsReceiveOrder);

    /**
     * 提交领用单，将状态更新为 PENDING_CONFIRM (待确认)。
     * 限制：最终更新在XML中必须限制前置状态为 `DRAFT`。
     */
    public int submitAmsReceiveOrder(AmsReceiveOrder amsReceiveOrder);

    /**
     * 确认领用，记录确认人快照和确认时间，并将状态置为 COMPLETED (已完成)。
     * 限制：最终更新在XML中必须限制前置状态为 `PENDING_CONFIRM`。
     */
    public int confirmAmsReceiveOrder(AmsReceiveOrder amsReceiveOrder);

    /**
     * 驳回领用申请，记录驳回原因，并将状态重置为 REJECTED (已驳回)。
     * 限制：最终更新在XML中必须限制前置状态为 `PENDING_CONFIRM`。
     */
    public int rejectAmsReceiveOrder(AmsReceiveOrder amsReceiveOrder);

    /**
     * 逻辑删除单个领用单，将 del_flag 置为 '1'。
     * 限制：只允许逻辑删除 `DRAFT` 状态的草稿单。
     */
    public int deleteAmsReceiveOrderByOrderId(Long orderId);

    /**
     * 批量逻辑删除领用单，将指定ID数组的主表记录 del_flag 置为 '1'。
     * 限制：同样仅限 `DRAFT` 状态单据。
     */
    public int deleteAmsReceiveOrderByOrderIds(String[] orderIds);

    /**
     * 批量逻辑删除领用单对应的明细项记录。
     */
    public int deleteAmsReceiveOrderItemByOrderIds(String[] orderIds);

    /**
     * 批量向 ams_receive_order_item 中插入多条资产领用明细记录（级联保存明细）
     */
    public int batchAmsReceiveOrderItem(List<AmsReceiveOrderItem> amsReceiveOrderItemList);

    /**
     * 根据领用单ID物理删除其关联的所有领用明细项记录。
     * 业务意图：在编辑草稿单据并重新保存时，采用“先删后增”策略来同步明细列表，这是常规的Ruoyi主子表结构维护方案。
     */
    public int deleteAmsReceiveOrderItemByOrderId(Long orderId);
}
