import Foundation
import NucleicProtocol

/// Decides whether a session may be transferred, and why not (mesh P5). The session/graph checks
/// are pure; repo-shape checks live in `TransferGitProbe` (async git) and are combined by the
/// caller, which knows the project root.
public enum TransferClassifier {
    /// The session-level reject reason, or nil if the session itself is transferable. Does NOT
    /// probe the repo shape (shallow/LFS/…) — combine with `TransferGitProbe.repoShape`.
    ///
    /// - Parameter isParentOfLiveChild: whether any live session has this one as its parent (a
    ///   stack of dependent sessions can't move a member alone).
    public static func sessionReject(
        session: Session, project: Project, isParentOfLiveChild: Bool
    ) -> TransferRejectReason? {
        // A live backend process must quiesce first.
        if session.status.hasTurnInFlight { return .notQuiescent }
        // Shared-trunk (nvrsion) sessions have no per-session worktree/branch to bundle.
        if project.nvrsionActive { return .nvrsion }
        // Nothing to move without a worktree + branch + base.
        guard session.worktreePath != nil, session.branch != nil, session.baseSHA != nil else {
            return .noWorktree
        }
        // A nested child, or a parent of still-live children — its lineage can't move on its own.
        if session.parentSessionID != nil || isParentOfLiveChild { return .nestedOrParent }
        return nil
    }
}
