import Foundation
import NucleicProtocol

/// One parked mesh dispatch (mesh dispatch, durable queue): a chat the user asked to run on the
/// mesh that couldn't be placed on any eligible runner right now, held on the dispatching host
/// and retried when a runner comes online. Persists across relaunch.
public struct MeshDispatchRecord: Sendable, Equatable {
    /// The dispatch/row id (also the `requestID` of the eventual `startChat`).
    public let id: String
    /// This host's own project id for the chat's repo.
    public let projectID: ProjectID
    public let message: String
    public let model: String?
    public let effort: String?
    public let auto: Bool?
    public let createdAt: Date

    public init(
        id: String, projectID: ProjectID, message: String, model: String?,
        effort: String?, auto: Bool?, createdAt: Date
    ) {
        self.id = id
        self.projectID = projectID
        self.message = message
        self.model = model
        self.effort = effort
        self.auto = auto
        self.createdAt = createdAt
    }
}

/// Durable storage for the mesh-dispatch queue (the `mesh_dispatch` table, GRDB v28). A seam like
/// `CastPersisting` so tests run it on the in-memory queue; accessed via `database as?
/// MeshDispatchPersisting` so a store that doesn't implement it simply disables the offline queue.
public protocol MeshDispatchPersisting: Sendable {
    func enqueueMeshDispatch(_ record: MeshDispatchRecord) async throws
    func queuedMeshDispatches() async throws -> [MeshDispatchRecord]
    func removeMeshDispatch(id: String) async throws
    /// Drop queued dispatches for a project that's going away (deleted/archived).
    func removeMeshDispatches(projectID: ProjectID) async throws
}
