package wang.yaojia.webterm.hostregistry

/**
 * Frozen contract (plan §3 :host-registry). Implementations: [DataStoreHostStore]
 * (real, Preferences-DataStore-backed) and [InMemoryHostStore] (in-Sources double
 * for this module's contract tests AND the AW4 ViewModel tests).
 *
 * Immutable style throughout: mutations return the NEW collection instead of
 * mutating shared state in place (mirrors the iOS `HostStore` protocol).
 */
public interface HostStore {
    /** The full paired-host list, in stored (insertion) order. */
    public suspend fun loadAll(): List<Host>

    /**
     * Insert, or replace the host with the same [Host.id] (position preserved).
     * Returns the new collection.
     */
    public suspend fun upsert(host: Host): List<Host>

    /**
     * Remove the host with [id]. Removing an unknown [id] is an explicit no-op:
     * returns the unchanged collection, never throws for "not found".
     */
    public suspend fun remove(id: String): List<Host>
}

// ── Pure collection transforms shared by all HostStore implementations (DRY) ─────
// Never mutate the receiver — always return a fresh list. Mirrors the iOS
// `extension [Host] { upserting / removing }`. `internal` so both stores and the
// same-module unit tests can use them without widening the public surface.

/**
 * Insert [host], or replace the existing entry with the same [Host.id] IN PLACE
 * (position preserved). Returns a new list; the receiver is untouched.
 */
internal fun List<Host>.upserting(host: Host): List<Host> =
    if (any { it.id == host.id }) {
        map { if (it.id == host.id) host else it }
    } else {
        this + host
    }

/**
 * Return a new list without the host whose id equals [id]. Unknown id → a copy
 * with the same contents (no-op). The receiver is untouched.
 */
internal fun List<Host>.removing(id: String): List<Host> =
    filter { it.id != id }
