// swift-tools-version: 6.2
import PackageDescription

// Build channel, selected at manifest-evaluation time via the NUCLEIC_CHANNEL
// environment variable (dev | beta | stable); defaults to `dev`. It drives two
// things in lockstep:
//   • the app executable's PRODUCT name — which becomes the on-disk binary and
//     therefore the OS process name (Activity Monitor / `ps`):
//        dev -> nucleic-local   beta -> nucleic-beta   rc -> nucleic-rc   stable -> nucleic
//   • a compile-time define (`NUCLEIC_STABLE/RC/BETA/DEV`) read by NucleicApp for its build
//     identity + warning banner (red local / blue beta / gold release-candidate / none stable),
//     and by NucleicCore's `ContainerManager` to suffix non-release container names.
// Branch mapping (see BUILD.md): dev builds from `dev`, beta from `staging`,
// rc from `rc`, stable from `main`.
let nucleicChannel = (Context.environment["NUCLEIC_CHANNEL"] ?? "dev").lowercased()
let (appProductName, channelDefine): (String, String) = {
    switch nucleicChannel {
    case "stable", "prod", "release": return ("nucleic", "NUCLEIC_STABLE")
    case "rc", "candidate": return ("nucleic-rc", "NUCLEIC_RC")
    case "beta": return ("nucleic-beta", "NUCLEIC_BETA")
    default: return ("nucleic-local", "NUCLEIC_DEV")
    }
}()

let package = Package(
    name: "Nucleic",
    // NucleicProtocol (the shared sync wire layer) must build for iOS too — that's what the
    // NucleicRemote iPhone client links. The host-only targets (NucleicCore/App/spike) use
    // macOS-only APIs and are simply never built for iOS.
    //
    // macOS floor is 26 (Tahoe): the container sandbox is built directly on Apple's
    // `containerization` framework, whose in-process vmnet networking requires macOS 26 + Apple
    // silicon. `containerization` is a dependency of NucleicCore ONLY (never of the iOS-linked
    // NucleicProtocol), so the iOS build resolves the package graph but never compiles it.
    platforms: [.macOS(.v26), .iOS(.v17)],
    products: [
        .library(name: "NucleicProtocol", targets: ["NucleicProtocol"]),
        .library(name: "NucleicCore", targets: ["NucleicCore"]),
        // Product (binary / process) name varies by channel — see `appProductName`.
        .executable(name: appProductName, targets: ["NucleicApp"]),
        .executable(name: "nucleic-spike", targets: ["nucleic-spike"]),
        .executable(name: "fake-claude", targets: ["fake-claude"]),
        .executable(name: "fake-grok", targets: ["fake-grok"]),
        .executable(name: "container-spike", targets: ["container-spike"]),
    ],
    dependencies: [
        .package(url: "https://github.com/groue/GRDB.swift.git", from: "7.0.0"),
        .package(url: "https://github.com/migueldeicaza/SwiftTerm.git", from: "1.2.0"),
        // Apple's containerization framework — the in-process runtime the `container` CLI is built
        // on. **Vendored** (third_party/containerization) at upstream commit 6b7b42ca rather than
        // pulled from github, because we carry a small patch: `LinuxContainer.Configuration` forwards
        // `vmExtensions` into `VMConfiguration.extensions` so we can attach a memory-balloon device
        // (see third_party/containerization/PATCHES.md). The package is pre-1.0 (source stability
        // holds only within a minor version); to bump, re-vendor the new commit and re-apply the
        // patch. All framework calls are centralized in `ContainerEngine`/`MemoryBalloon`.
        .package(path: "third_party/containerization"),
        // Sparkle — in-app auto-update for the directly-distributed (non-App-Store) macOS
        // builds. macOS-only and used ONLY by the NucleicApp executable target, so the iOS
        // resolution of the package graph never compiles it. Updates are delivered as signed,
        // notarized DMGs described by a per-channel appcast (see BUILD.md "Auto-update").
        .package(url: "https://github.com/sparkle-project/Sparkle", from: "2.6.0"),
    ],
    targets: [
        // Pure, platform-agnostic: identifiers, the AgentEvent model, the sync wire
        // protocol (ClientMsg/HostMsg), CBOR framing, and the Noise SecureChannel.
        // No GRDB / Process / Network — compiles for macOS and iOS alike.
        .target(name: "NucleicProtocol"),
        .target(
            name: "NucleicCore",
            dependencies: [
                "NucleicProtocol",
                .product(name: "GRDB", package: "GRDB.swift"),
                // In-process container runtime (host-only). EXT4 unpacking + vmnet networking are
                // reached transitively through `Containerization`; `ContainerizationOCI` provides
                // the `User`/`Platform` types used directly by `ContainerEngine`.
                .product(name: "Containerization", package: "containerization"),
                .product(name: "ContainerizationOCI", package: "containerization"),
                // For `AddressAllocator` — named in the `VZInstanceExtension.configureVZ` signature
                // our `MemoryBalloon` conforms to (it lives here, not in `Containerization`).
                .product(name: "ContainerizationExtras", package: "containerization"),
            ],
            // The build channel reaches the container-naming code here: `ContainerManager` appends a
            // per-channel suffix (e.g. `-beta`, `-local`) to non-release container names so a beta /
            // local-dev build's containers don't collide with a release's on the shared on-disk
            // container store (ContainerEngine.defaultStorageRoot). Same define NucleicApp's banner uses.
            swiftSettings: [.define(channelDefine)]),
        .executableTarget(
            name: "NucleicApp",
            dependencies: [
                "NucleicCore",
                .product(name: "SwiftTerm", package: "SwiftTerm"),
                // Auto-update for direct (non-App-Store) distribution. macOS-only.
                .product(name: "Sparkle", package: "Sparkle"),
            ],
            swiftSettings: [.define(channelDefine)],
            plugins: ["EmbedGitCommit"]),
        // Prebuild plugin: stamps the built-from commit into a generated `GitCommit.swift`
        // at build time, so the hash is baked into the binary (correct even on a
        // packaged beta / rc / stable archive, where git isn't present at runtime).
        .plugin(name: "EmbedGitCommit", capability: .buildTool()),
        .executableTarget(name: "nucleic-spike", dependencies: ["NucleicCore"]),
        .executableTarget(name: "fake-claude", dependencies: ["NucleicCore"]),
        .executableTarget(name: "fake-grok", dependencies: ["NucleicCore"]),
        // Standalone de-risking spike for the container rework: drives the real `ContainerEngine`
        // end-to-end — pulls an image from a registry, boots the VM, execs a process, and streams
        // its stdout through `ContainerizedProcessHandle` (the agent's path). Run signed with
        // signing/spike.entitlements; not shipped.
        .executableTarget(
            name: "container-spike",
            dependencies: [
                "NucleicCore",
                .product(name: "Containerization", package: "containerization"),
                .product(name: "ContainerizationOCI", package: "containerization"),
            ]),
        .testTarget(
            name: "NucleicProtocolTests",
            dependencies: ["NucleicProtocol"]
        ),
        .testTarget(
            name: "NucleicCoreTests",
            dependencies: ["NucleicCore"],
            resources: [.copy("Fixtures")]
        ),
    ]
)
