namespace WslcApiDump;

/// <summary>
/// The <c>Microsoft.WSL.Containers</c> surface `NucleicBroker/Wslc/WslcFacade.cs` depends on.
///
/// **This list changed meaning on 2026-07-29.** It began as a list of *guesses* — the facade was
/// transcribed from documentation on machines with no WSL — and this tool existed to find out how
/// many were wrong. That question is answered (docs/WINDOWS_PORT.md §13.1: many of them, including
/// three that were missing capability rather than a wrong name). The entries below are now the
/// surface **actually observed in package 2.9.3**, so this tool's job has changed from discovery
/// to **drift detection**: run it after bumping the pin and it says what the new version moved.
///
/// Still strings rather than typed references, for the same reason as before — a typed check fails
/// to compile on the first rename and reports one problem; this reports all of them.
///
/// Keep in lockstep with WslcFacade.cs.
/// </summary>
internal static class FacadeAssumptions
{
    internal sealed record Assumption(string Type, string Member, Kind MemberKind, string Why);

    internal enum Kind { Method, Property, Event, Constructor, EnumValue, Type }

    internal static readonly Assumption[] All =
    [
        // ---- Service entry point: onboarding (§8 step 2) ----
        new("WslcService", "GetVersion", Kind.Method,
            "hello capabilities — hostd degrades across preview→GA churn on this"),
        new("WslcService", "GetMissingComponents", Kind.Method,
            "components.missing RPC; returns IReadOnlyList<Component>, NOT a flags enum"),
        new("WslcService", "InstallWithDependenciesAsync", Kind.Method,
            "components.install RPC — the ASYNC form, because only it carries InstallProgress"),
        new("InstallProgress", "Component", Kind.Property,
            "which component is installing → components.installProgress status"),
        new("InstallProgress", "Total", Kind.Property,
            "denominator for the install percentage (Progress/Total)"),
        new("Component", "WslPackage", Kind.EnumValue,
            "one of the three components onboarding can report missing"),
        new("ServiceVersion", "Major", Kind.Property, "the version triple reported in hello"),

        // ---- Session: one per channel, hosts every container (§3.2) ----
        new("SessionSettings", ".ctor", Kind.Constructor, "SessionSettings(name, storagePath)"),
        new("SessionSettings", "CpuCount", Kind.Property, "session.ensure cpu"),
        new("SessionSettings", "MemorySizeInMB", Kind.Property,
            "session.ensure memoryMB — NOT MemoryMB; a resize needs a sandbox restart (§3.2)"),
        new("SessionSettings", "Timeout", Kind.Property, "idle timeout for the whole session VM"),
        new("Session", ".ctor", Kind.Constructor,
            "there is NO CreateOrOpen — construction is the only entry point, and it is LAZY: a "
            + "second construction with an existing name succeeds and means nothing. Start() is "
            + "where the service is consulted, and it refuses with ERROR_ALREADY_EXISTS, which is "
            + "why broker reattach (§2.3) cannot be served from this surface"),
        new("Session", "ProcessCrashed", Kind.Event,
            "ProcessCrashInformation — the only crash detail wslc offers, and what makes a "
            + "SIGKILLed agent explicable in the host log (the Swift diagnoseKill seam)"),
        new("Session", "Start", Kind.Method, "brings the session VM up after construction"),
        new("Session", "Terminate", Kind.Method, "session.terminate RPC"),
        new("Session", "Terminated", Kind.Event,
            "session.down notification (SessionTerminationReason) → hostd's reconcile sweep"),
        new("SessionTerminationReason", "Crashed", Kind.EnumValue,
            "distinguishes a crash from an orderly shutdown in the session.down reason"),

        // ---- Images ----
        new("Session", "PullImageAsync", Kind.Method,
            "image.pull RPC (naros-agent from GHCR). The async form specifically: the sync "
            + "PullImage reports no progress at all"),
        new("PullImageOptions", ".ctor", Kind.Constructor, "PullImageOptions(uri)"),
        new("PullImageOptions", "RegistryAuth", Kind.Property,
            "GHCR auth — a STRING, not a credentials object"),
        new("Session", "Authenticate", Kind.Method,
            "where that string COMES FROM: Authenticate(registryUri, user, password) mints the "
            + "identity token PullImageOptions.RegistryAuth wants. Without this the auth field "
            + "has no documented producer and a private GHCR pull cannot work"),
        new("ImageProgress", "CurrentBytes", Kind.Property,
            "→ image.pullProgress → the existing controlDownloadProgress UI surface"),
        new("ImageProgressStatus", "Downloading", Kind.EnumValue, "pull progress phase"),
        new("Session", "GetImages", Kind.Method, "image.list / image.inspect"),
        new("ImageInfo", "Name", Kind.Property, "image ref — NOT .Reference"),
        new("ImageInfo", "Sha256", Kind.Property,
            "image digest — NOT .Digest, and an IBuffer of raw bytes rather than a string, so the "
            + "facade hex-encodes it into the sha256:<hex> the rest of Nucleic speaks"),
        new("Session", "DeleteImage", Kind.Method, "image.delete"),

        // ---- Containers ----
        new("Session", "CreateContainer", Kind.Method, "container.create"),
        new("ContainerSettings", ".ctor", Kind.Constructor, "ContainerSettings(imageName)"),
        new("ContainerSettings", "Name", Kind.Property, "channel-suffixed container naming"),
        new("ContainerSettings", "HostName", Kind.Property, "container.create hostname — capital N"),
        new("ContainerSettings", "NetworkingMode", Kind.Property,
            "None | Bridged — NOT the NAT/mirrored pair §5 assumed"),
        new("ContainerSettings", "Volumes", Kind.Property, "the NTFS worktree bind mount (D8)"),
        new("ContainerSettings", "InitProcess", Kind.Property, "naros-init as PID 1 (docs/NAROS.md)"),
        new("ContainerVolume", ".ctor", Kind.Constructor,
            "ContainerVolume(windowsPath, containerPath, readOnly)"),
        new("ContainerNetworkingMode", "Bridged", Kind.EnumValue,
            "the mode a container needs to reach the host at all (§5)"),
        new("Container", "Start", Kind.Method, "container.start"),
        new("Container", "Stop", Kind.Method, "container.stop(Signal, TimeSpan)"),
        new("Container", "Delete", Kind.Method, "container.delete(DeleteContainerOption)"),
        new("Container", "State", Kind.Property, "container.state → running/stopped/absent"),
        new("Container", "Inspect", Kind.Method,
            "the ONLY per-container introspection there is — there is no GetStatistics(), so "
            + "container.stats has to exec cgroup reads instead (§13.1 finding 2)"),
        // NOTE the absence: there is no Container.Name and no Session.GetContainers(), so a
        // container is only ever reachable through the handle CreateContainer returned. That is
        // why the facade keeps its own name→handle roster, and why container.list cannot see
        // anything created before a broker restart (§13.1 finding 1).
        new("Container", "Id", Kind.Property,
            "the only identity the SDK gives back — there is NO Name property to match on"),
        new("Container", "CreateProcess", Kind.Method,
            "proc.exec — NOT RunProcess, and it does not start the process"),
        new("ContainerState", "Running", Kind.EnumValue, "the one state the facade tests by name"),
        new("ContainerState", "Deleted", Kind.EnumValue,
            "folds to \"absent\" — a deleted handle is gone as far as the Swift policy layer cares"),
        new("DeleteContainerOption", "Force", Kind.EnumValue, "container.delete force"),
        new("Error", "ContainerNotFound", Kind.EnumValue,
            "structured failure codes — a better source for the RPC's data.kind than string matching"),

        // ---- Processes: the agent stdio path (§3.2 WslcProcessHandle) ----
        new("ProcessSettings", "CommandLine", Kind.Property, "argv — NOT CmdLine"),
        new("ProcessSettings", "EnvironmentVariables", Kind.Property, "env — NOT Environment"),
        new("ProcessSettings", "WorkingDirectory", Kind.Property, "cwd"),
        new("ProcessSettings", "OutputMode", Kind.Property, "event-mode stdio, not polling"),
        new("ProcessOutputMode", "Event", Kind.EnumValue,
            "the mode that makes stdio push-based; polling would change the broker design"),
        new("Process", "Start", Kind.Method,
            "the second half of exec — handlers are attached between CreateProcess and this, which "
            + "is precisely why the API is split in two"),
        new("Process", "OutputReceived", Kind.Event, "→ proc.stdout notifications"),
        new("Process", "ErrorReceived", Kind.Event,
            "→ proc.stderr — a SEPARATE event, not a stderr flag on one handler"),
        new("Process", "Exited", Kind.Event, "→ proc.exit; must never overtake output (OutboundWriter)"),
        new("Process", "GetInputStream", Kind.Method,
            "proc.stdin — a WinRT IOutputStream written through a DataWriter, not a WriteStdin "
            + "call; disposing the STREAM is what the guest sees as EOF, i.e. proc.closeStdin"),
        new("Process", "Signal", Kind.Method, "proc.signal — the agent's real POSIX Stop path"),
        new("Signal", "SIGKILL", Kind.EnumValue,
            "signals are a NAMED enum; the RPC carries POSIX ints, so the broker maps them, and "
            + "anything outside None/HUP/INT/QUIT/KILL/TERM is unavailable"),
    ];
}
