import Foundation

/// Frozen contract (plan §3.3). Implementations: `KeychainHostStore` (real)
/// and `InMemoryHostStore` (in-Sources double for this package's tests and
/// the App-layer VM tests). Immutable style: mutations return the NEW
/// collection instead of mutating shared state in place.
public protocol HostStore: Sendable {
    func loadAll() async throws -> [Host]
    /// Insert, or replace the host with the same `id` (position preserved).
    /// Returns the new collection.
    func upsert(_ host: Host) async throws -> [Host]
    /// Removing an unknown `id` is an explicit no-op: returns the unchanged
    /// collection, never throws for "not found".
    func remove(id: UUID) async throws -> [Host]
}

// Pure collection transforms shared by all HostStore implementations (DRY);
// never mutate `self`, always return a fresh array.
extension [Host] {
    func upserting(_ host: Host) -> [Host] {
        contains(where: { $0.id == host.id })
            ? map { $0.id == host.id ? host : $0 }
            : self + [host]
    }

    func removing(id: UUID) -> [Host] {
        filter { $0.id != id }
    }
}
