package com.ruoyi.asset.service;

import com.ruoyi.asset.domain.AssetTransitionContext;
import com.ruoyi.asset.domain.AssetTransitionResult;

/**
 * 资产状态流转公共服务
 *
 * @author Yangk
 */
public interface IAssetStatusTransitionService
{
    /**
     * 确认资产首次入库：PENDING_INBOUND → IN_STOCK（写入仓位，清除使用归属）
     * <p>在库资产换仓必须使用调拨业务。</p>
     *
     * @param assetId     资产ID
     * @param warehouseId 目标仓库ID
     * @param locationId  目标存放位置ID
     * @param context     流转操作上下文（来源单据、操作人等）
     * @return 变更前后的资产快照
     */
    public AssetTransitionResult confirmInbound(Long assetId, Long warehouseId, Long locationId,
            AssetTransitionContext context);

    /**
     * 确认资产领用：IN_STOCK → IN_USE（清空仓位，写入使用部门和使用人）
     *
     * @param assetId    资产ID
     * @param useDeptId  领用部门ID
     * @param useUserId  领用人ID
     * @param context    流转操作上下文
     * @return 变更前后的资产快照
     */
    public AssetTransitionResult confirmReceive(Long assetId, Long useDeptId, Long useUserId,
            AssetTransitionContext context);

    /**
     * 确认资产退库：IN_USE → IN_STOCK（更新仓位，清除使用归属）
     *
     * @param assetId     资产ID
     * @param warehouseId 退回目标仓库ID
     * @param locationId  退回目标位置ID
     * @param context     流转操作上下文
     * @return 变更前后的资产快照
     */
    public AssetTransitionResult confirmReturn(Long assetId, Long warehouseId, Long locationId,
            AssetTransitionContext context);

    /**
     * 确认资产借出：IN_STOCK → BORROWED（清空仓位和使用归属）
     * <p>借出前校验在库资产不能残留使用归属，防止数据不一致。</p>
     *
     * @param assetId 资产ID
     * @param context 流转操作上下文
     * @return 变更前后的资产快照
     */
    public AssetTransitionResult confirmBorrow(Long assetId, AssetTransitionContext context);

    /**
     * 确认借用归还：BORROWED → IN_STOCK（更新仓位，清除使用归属）
     *
     * @param assetId     资产ID
     * @param warehouseId 归还目标仓库ID
     * @param locationId  归还目标位置ID
     * @param context     流转操作上下文
     * @return 变更前后的资产快照
     */
    public AssetTransitionResult confirmBorrowReturn(Long assetId, Long warehouseId, Long locationId,
            AssetTransitionContext context);

    /**
     * 确认资产调拨：IN_STOCK → IN_STOCK（仅更新仓库和位置）
     * <p>在用资产必须先退库，不能直接调拨。</p>
     *
     * @param assetId     资产ID
     * @param warehouseId 调拨目标仓库ID
     * @param locationId  调拨目标位置ID
     * @param context     流转操作上下文
     * @return 变更前后的资产快照
     */
    public AssetTransitionResult confirmTransfer(Long assetId, Long warehouseId, Long locationId,
            AssetTransitionContext context);

    /**
     * 开始资产维修：IN_STOCK/IN_USE → REPAIRING
     * <p>调用方应保存维修前状态以便维修完成后恢复。</p>
     *
     * @param assetId 资产ID
     * @param context 流转操作上下文
     * @return 变更前后的资产快照，beforeAsset.assetStatus 即为维修前状态
     */
    public AssetTransitionResult startRepair(Long assetId, AssetTransitionContext context);

    /**
     * 完成资产维修：REPAIRING → IN_STOCK 或 IN_USE（恢复维修前状态）
     * <p>若 beforeAssetStatus 为空或空白则默认恢复为在库。恢复为在用时需确保资产仍有使用归属。</p>
     *
     * @param assetId           资产ID
     * @param beforeAssetStatus 维修前的资产状态，仅接受 IN_STOCK / IN_USE
     * @param context           流转操作上下文
     * @return 变更前后的资产快照
     */
    public AssetTransitionResult finishRepair(Long assetId, String beforeAssetStatus,
            AssetTransitionContext context);

    /**
     * 确认资产报废：IN_STOCK/IN_USE → DISPOSED
     * <p>报废不清除 RFID 绑定关系，保留标签溯源能力。</p>
     *
     * @param assetId 资产ID
     * @param context 流转操作上下文
     * @return 变更前后的资产快照
     */
    public AssetTransitionResult confirmDisposal(Long assetId, AssetTransitionContext context);
}
