use serde::Serialize;
use std::sync::OnceLock;

pub const NATIVE_BACKEND_NOT_IMPLEMENTED: &str = "native-backend-not-implemented";
pub const NATIVE_AARCH64_SUBSET: &str = "native-aarch64-subset";
pub const NATIVE_OBJECT_SUBSET: &str = "native-object-subset";
pub const BYTECODE_BACKEND_SUBSET: &str = "bytecode-vm-subset";

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TargetId {
    Bytecode,
    Native,
}

impl TargetId {
    #[must_use]
    pub const fn as_str(self) -> &'static str {
        match self {
            TargetId::Bytecode => "bytecode",
            TargetId::Native => "native",
        }
    }

    #[must_use]
    pub fn parse(name: &str) -> Option<Self> {
        match name {
            "bytecode" => Some(TargetId::Bytecode),
            "native" => Some(TargetId::Native),
            _ => None,
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct TargetSpec {
    pub name: &'static str,
    pub implemented: bool,
    pub stage: &'static str,
    pub reason_code: &'static str,
    pub reason: &'static str,
    pub input_stage: &'static str,
    pub artifact_kind: &'static str,
    pub host_triple: Option<&'static str>,
    pub backend_artifact_supported: bool,
}

const BYTECODE_TARGET: TargetSpec = TargetSpec {
    name: "bytecode",
    implemented: true,
    stage: "owned-runtime-subset",
    reason_code: BYTECODE_BACKEND_SUBSET,
    reason: "inauguration owns this bytecode assembly format, SIL-to-bytecode lowering path, and stack VM runtime for the supported Core IR subset",
    input_stage: "core-ir-to-textual-sil",
    artifact_kind: "bytecode-assembly",
    host_triple: None,
    backend_artifact_supported: true,
};

#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
const NATIVE_TARGET: TargetSpec = TargetSpec {
    name: "native",
    implemented: true,
    stage: "owned-native-subset",
    reason_code: NATIVE_AARCH64_SUBSET,
    reason: "inauguration owns a Mach-O executable emitter and AArch64 lowering path for a checked Core IR scalar subset on Apple ARM64 hosts",
    input_stage: "core-ir",
    artifact_kind: "mach-o-executable",
    host_triple: Some("aarch64-apple-darwin"),
    backend_artifact_supported: false,
};

#[cfg(not(all(target_os = "macos", target_arch = "aarch64")))]
const NATIVE_TARGET: TargetSpec = TargetSpec {
    name: "native",
    implemented: false,
    stage: "contract-only",
    reason_code: NATIVE_BACKEND_NOT_IMPLEMENTED,
    reason: "inauguration currently has no in-tree object-file emitter, linker driver, ABI lowering, or owned machine runtime for native code generation",
    input_stage: "core-ir-or-textual-sil",
    artifact_kind: "none",
    host_triple: None,
    backend_artifact_supported: false,
};

const IN_EQUIVALENT_TARGETS: &[&str] = &[
    "aarch64-apple-darwin",
    "aarch64-apple-ios",
    "aarch64-apple-ios-macabi",
    "aarch64-apple-ios-sim",
    "aarch64-apple-tvos",
    "aarch64-apple-tvos-sim",
    "aarch64-apple-visionos",
    "aarch64-apple-visionos-sim",
    "aarch64-apple-watchos",
    "aarch64-apple-watchos-sim",
    "aarch64-kmc-solid_asp3",
    "aarch64-linux-android",
    "aarch64-nintendo-switch-freestanding",
    "aarch64-pc-windows-gnullvm",
    "aarch64-pc-windows-msvc",
    "aarch64-unknown-freebsd",
    "aarch64-unknown-fuchsia",
    "aarch64-unknown-helenos",
    "aarch64-unknown-hermit",
    "aarch64-unknown-illumos",
    "aarch64-unknown-linux-gnu",
    "aarch64-unknown-linux-gnu_ilp32",
    "aarch64-unknown-linux-musl",
    "aarch64-unknown-linux-ohos",
    "aarch64-unknown-managarm-mlibc",
    "aarch64-unknown-netbsd",
    "aarch64-unknown-none",
    "aarch64-unknown-none-softfloat",
    "aarch64-unknown-nto-qnx700",
    "aarch64-unknown-nto-qnx710",
    "aarch64-unknown-nto-qnx710_iosock",
    "aarch64-unknown-nto-qnx800",
    "aarch64-unknown-nuttx",
    "aarch64-unknown-openbsd",
    "aarch64-unknown-redox",
    "aarch64-unknown-teeos",
    "aarch64-unknown-trusty",
    "aarch64-unknown-uefi",
    "aarch64-uwp-windows-msvc",
    "aarch64-wrs-vxworks",
    "aarch64_be-unknown-hermit",
    "aarch64_be-unknown-linux-gnu",
    "aarch64_be-unknown-linux-gnu_ilp32",
    "aarch64_be-unknown-linux-musl",
    "aarch64_be-unknown-netbsd",
    "aarch64_be-unknown-none-softfloat",
    "amdgcn-amd-amdhsa",
    "arm-linux-androideabi",
    "arm-unknown-linux-gnueabi",
    "arm-unknown-linux-gnueabihf",
    "arm-unknown-linux-musleabi",
    "arm-unknown-linux-musleabihf",
    "arm64_32-apple-watchos",
    "arm64e-apple-darwin",
    "arm64e-apple-ios",
    "arm64e-apple-tvos",
    "arm64ec-pc-windows-msvc",
    "armeb-unknown-linux-gnueabi",
    "armebv7r-none-eabi",
    "armebv7r-none-eabihf",
    "armv4t-none-eabi",
    "armv4t-unknown-linux-gnueabi",
    "armv5te-none-eabi",
    "armv5te-unknown-linux-gnueabi",
    "armv5te-unknown-linux-musleabi",
    "armv5te-unknown-linux-uclibceabi",
    "armv6-unknown-freebsd",
    "armv6-unknown-netbsd-eabihf",
    "armv6k-nintendo-3ds",
    "armv7-linux-androideabi",
    "armv7-rtems-eabihf",
    "armv7-sony-vita-newlibeabihf",
    "armv7-unknown-freebsd",
    "armv7-unknown-linux-gnueabi",
    "armv7-unknown-linux-gnueabihf",
    "armv7-unknown-linux-musleabi",
    "armv7-unknown-linux-musleabihf",
    "armv7-unknown-linux-ohos",
    "armv7-unknown-linux-uclibceabi",
    "armv7-unknown-linux-uclibceabihf",
    "armv7-unknown-netbsd-eabihf",
    "armv7-unknown-trusty",
    "armv7-wrs-vxworks-eabihf",
    "armv7a-kmc-solid_asp3-eabi",
    "armv7a-kmc-solid_asp3-eabihf",
    "armv7a-none-eabi",
    "armv7a-none-eabihf",
    "armv7a-nuttx-eabi",
    "armv7a-nuttx-eabihf",
    "armv7a-vex-v5",
    "armv7k-apple-watchos",
    "armv7r-none-eabi",
    "armv7r-none-eabihf",
    "armv7s-apple-ios",
    "armv8r-none-eabihf",
    "avr-none",
    "bpfeb-unknown-none",
    "bpfel-unknown-none",
    "csky-unknown-linux-gnuabiv2",
    "csky-unknown-linux-gnuabiv2hf",
    "hexagon-unknown-linux-musl",
    "hexagon-unknown-none-elf",
    "hexagon-unknown-qurt",
    "i386-apple-ios",
    "i586-unknown-linux-gnu",
    "i586-unknown-linux-musl",
    "i586-unknown-netbsd",
    "i586-unknown-redox",
    "i686-apple-darwin",
    "i686-linux-android",
    "i686-pc-nto-qnx700",
    "i686-pc-windows-gnu",
    "i686-pc-windows-gnullvm",
    "i686-pc-windows-msvc",
    "i686-unknown-freebsd",
    "i686-unknown-haiku",
    "i686-unknown-helenos",
    "i686-unknown-hurd-gnu",
    "i686-unknown-linux-gnu",
    "i686-unknown-linux-musl",
    "i686-unknown-netbsd",
    "i686-unknown-openbsd",
    "i686-unknown-uefi",
    "i686-uwp-windows-gnu",
    "i686-uwp-windows-msvc",
    "i686-win7-windows-gnu",
    "i686-win7-windows-msvc",
    "i686-wrs-vxworks",
    "loongarch32-unknown-none",
    "loongarch32-unknown-none-softfloat",
    "loongarch64-unknown-linux-gnu",
    "loongarch64-unknown-linux-musl",
    "loongarch64-unknown-linux-ohos",
    "loongarch64-unknown-none",
    "loongarch64-unknown-none-softfloat",
    "m68k-unknown-linux-gnu",
    "m68k-unknown-none-elf",
    "mips-mti-none-elf",
    "mips-unknown-linux-gnu",
    "mips-unknown-linux-musl",
    "mips-unknown-linux-uclibc",
    "mips64-openwrt-linux-musl",
    "mips64-unknown-linux-gnuabi64",
    "mips64-unknown-linux-muslabi64",
    "mips64el-unknown-linux-gnuabi64",
    "mips64el-unknown-linux-muslabi64",
    "mipsel-mti-none-elf",
    "mipsel-sony-psp",
    "mipsel-sony-psx",
    "mipsel-unknown-linux-gnu",
    "mipsel-unknown-linux-musl",
    "mipsel-unknown-linux-uclibc",
    "mipsel-unknown-netbsd",
    "mipsel-unknown-none",
    "mipsisa32r6-unknown-linux-gnu",
    "mipsisa32r6el-unknown-linux-gnu",
    "mipsisa64r6-unknown-linux-gnuabi64",
    "mipsisa64r6el-unknown-linux-gnuabi64",
    "msp430-none-elf",
    "nvptx64-nvidia-cuda",
    "powerpc-unknown-freebsd",
    "powerpc-unknown-helenos",
    "powerpc-unknown-linux-gnu",
    "powerpc-unknown-linux-gnuspe",
    "powerpc-unknown-linux-musl",
    "powerpc-unknown-linux-muslspe",
    "powerpc-unknown-netbsd",
    "powerpc-unknown-openbsd",
    "powerpc-wrs-vxworks",
    "powerpc-wrs-vxworks-spe",
    "powerpc64-ibm-aix",
    "powerpc64-unknown-freebsd",
    "powerpc64-unknown-linux-gnu",
    "powerpc64-unknown-linux-musl",
    "powerpc64-unknown-openbsd",
    "powerpc64-wrs-vxworks",
    "powerpc64le-unknown-freebsd",
    "powerpc64le-unknown-linux-gnu",
    "powerpc64le-unknown-linux-musl",
    "riscv32-wrs-vxworks",
    "riscv32e-unknown-none-elf",
    "riscv32em-unknown-none-elf",
    "riscv32emc-unknown-none-elf",
    "riscv32gc-unknown-linux-gnu",
    "riscv32gc-unknown-linux-musl",
    "riscv32i-unknown-none-elf",
    "riscv32im-risc0-zkvm-elf",
    "riscv32im-unknown-none-elf",
    "riscv32ima-unknown-none-elf",
    "riscv32imac-esp-espidf",
    "riscv32imac-unknown-none-elf",
    "riscv32imac-unknown-nuttx-elf",
    "riscv32imac-unknown-xous-elf",
    "riscv32imafc-esp-espidf",
    "riscv32imafc-unknown-none-elf",
    "riscv32imafc-unknown-nuttx-elf",
    "riscv32imc-esp-espidf",
    "riscv32imc-unknown-none-elf",
    "riscv32imc-unknown-nuttx-elf",
    "riscv64-linux-android",
    "riscv64-wrs-vxworks",
    "riscv64a23-unknown-linux-gnu",
    "riscv64gc-unknown-freebsd",
    "riscv64gc-unknown-fuchsia",
    "riscv64gc-unknown-hermit",
    "riscv64gc-unknown-linux-gnu",
    "riscv64gc-unknown-linux-musl",
    "riscv64gc-unknown-managarm-mlibc",
    "riscv64gc-unknown-netbsd",
    "riscv64gc-unknown-none-elf",
    "riscv64gc-unknown-nuttx-elf",
    "riscv64gc-unknown-openbsd",
    "riscv64gc-unknown-redox",
    "riscv64im-unknown-none-elf",
    "riscv64imac-unknown-none-elf",
    "riscv64imac-unknown-nuttx-elf",
    "s390x-unknown-linux-gnu",
    "s390x-unknown-linux-musl",
    "sparc-unknown-linux-gnu",
    "sparc-unknown-none-elf",
    "sparc64-unknown-helenos",
    "sparc64-unknown-linux-gnu",
    "sparc64-unknown-netbsd",
    "sparc64-unknown-openbsd",
    "sparcv9-sun-solaris",
    "thumbv4t-none-eabi",
    "thumbv5te-none-eabi",
    "thumbv6m-none-eabi",
    "thumbv6m-nuttx-eabi",
    "thumbv7a-nuttx-eabi",
    "thumbv7a-nuttx-eabihf",
    "thumbv7a-pc-windows-msvc",
    "thumbv7a-uwp-windows-msvc",
    "thumbv7em-none-eabi",
    "thumbv7em-none-eabihf",
    "thumbv7em-nuttx-eabi",
    "thumbv7em-nuttx-eabihf",
    "thumbv7m-none-eabi",
    "thumbv7m-nuttx-eabi",
    "thumbv7neon-linux-androideabi",
    "thumbv7neon-unknown-linux-gnueabihf",
    "thumbv7neon-unknown-linux-musleabihf",
    "thumbv8m.base-none-eabi",
    "thumbv8m.base-nuttx-eabi",
    "thumbv8m.main-none-eabi",
    "thumbv8m.main-none-eabihf",
    "thumbv8m.main-nuttx-eabi",
    "thumbv8m.main-nuttx-eabihf",
    "wasm32-unknown-emscripten",
    "wasm32-unknown-unknown",
    "wasm32-wali-linux-musl",
    "wasm32-wasip1",
    "wasm32-wasip1-threads",
    "wasm32-wasip2",
    "wasm32-wasip3",
    "wasm32v1-none",
    "wasm64-unknown-unknown",
    "x86_64-apple-darwin",
    "x86_64-apple-ios",
    "x86_64-apple-ios-macabi",
    "x86_64-apple-tvos",
    "x86_64-apple-watchos-sim",
    "x86_64-fortanix-unknown-sgx",
    "x86_64-linux-android",
    "x86_64-lynx-lynxos178",
    "x86_64-pc-cygwin",
    "x86_64-pc-nto-qnx710",
    "x86_64-pc-nto-qnx710_iosock",
    "x86_64-pc-nto-qnx800",
    "x86_64-pc-solaris",
    "x86_64-pc-windows-gnu",
    "x86_64-pc-windows-gnullvm",
    "x86_64-pc-windows-msvc",
    "x86_64-unikraft-linux-musl",
    "x86_64-unknown-dragonfly",
    "x86_64-unknown-freebsd",
    "x86_64-unknown-fuchsia",
    "x86_64-unknown-haiku",
    "x86_64-unknown-helenos",
    "x86_64-unknown-hermit",
    "x86_64-unknown-hurd-gnu",
    "x86_64-unknown-illumos",
    "x86_64-unknown-l4re-uclibc",
    "x86_64-unknown-linux-gnu",
    "x86_64-unknown-linux-gnux32",
    "x86_64-unknown-linux-musl",
    "x86_64-unknown-linux-none",
    "x86_64-unknown-linux-ohos",
    "x86_64-unknown-managarm-mlibc",
    "x86_64-unknown-motor",
    "x86_64-unknown-netbsd",
    "x86_64-unknown-none",
    "x86_64-unknown-openbsd",
    "x86_64-unknown-redox",
    "x86_64-unknown-trusty",
    "x86_64-unknown-uefi",
    "x86_64-uwp-windows-gnu",
    "x86_64-uwp-windows-msvc",
    "x86_64-win7-windows-gnu",
    "x86_64-win7-windows-msvc",
    "x86_64-wrs-vxworks",
    "x86_64h-apple-darwin",
    "xtensa-esp32-espidf",
    "xtensa-esp32-none-elf",
    "xtensa-esp32s2-espidf",
    "xtensa-esp32s2-none-elf",
    "xtensa-esp32s3-espidf",
    "xtensa-esp32s3-none-elf",
];
const RUST_STYLE_TARGET_REASON: &str = "inauguration recognizes this Rust-style target triple as a compiler target identity, but it has no in-tree object-file emitter, linker driver, ABI lowering, or owned machine runtime for this target yet";
static TARGET_REGISTRY: OnceLock<Vec<TargetSpec>> = OnceLock::new();

#[must_use]
pub fn all_target_specs() -> &'static [TargetSpec] {
    TARGET_REGISTRY
        .get_or_init(build_target_registry)
        .as_slice()
}

#[must_use]
pub fn target_spec(id: TargetId) -> TargetSpec {
    match id {
        TargetId::Bytecode => BYTECODE_TARGET,
        TargetId::Native => NATIVE_TARGET,
    }
}

#[must_use]
pub fn bytecode_target_spec() -> TargetSpec {
    BYTECODE_TARGET
}

#[must_use]
pub fn native_target_spec() -> TargetSpec {
    NATIVE_TARGET
}

#[must_use]
pub fn target_spec_by_name(name: &str) -> Option<TargetSpec> {
    all_target_specs()
        .iter()
        .find(|spec| spec.name == name)
        .cloned()
}

#[must_use]
pub fn native_subset_host_available() -> bool {
    cfg!(all(target_os = "macos", target_arch = "aarch64"))
}

fn build_target_registry() -> Vec<TargetSpec> {
    let mut specs = vec![BYTECODE_TARGET, NATIVE_TARGET];
    for &target in IN_EQUIVALENT_TARGETS {
        if specs.iter().any(|spec| spec.name == target) {
            continue;
        }
        specs.push(TargetSpec {
            name: target,
            implemented: implemented_target(target),
            stage: if target == "x86_64-unknown-linux-gnu" {
                "owned-native-and-object-subset"
            } else if target == "x86_64-pc-windows-msvc" {
                "owned-native-subset"
            } else if implemented_target(target) {
                "owned-object-subset"
            } else {
                "contract-only"
            },
            reason_code: if implemented_target(target) {
                NATIVE_OBJECT_SUBSET
            } else {
                NATIVE_BACKEND_NOT_IMPLEMENTED
            },
            reason: if target == "x86_64-unknown-linux-gnu" {
                "inauguration owns ELF64 relocatable object emission and a Linux syscall-exit executable subset for const-evaluable scalar entry functions on this target"
            } else if target == "aarch64-unknown-linux-gnu" {
                "inauguration owns ELF64 AArch64 relocatable object emission for const-evaluable scalar entry functions on this target"
            } else if target == "aarch64-apple-darwin" {
                "inauguration owns Mach-O static archive and .app bundle emission for const-evaluable scalar entry functions on this target"
            } else if target == "x86_64-pc-windows-msvc" {
                "inauguration owns PE32+ .exe emission for const-evaluable scalar entry functions on this target"
            } else if target == "armv7-unknown-linux-gnueabihf" {
                "inauguration owns ELF32 ARM relocatable object emission for const-evaluable scalar entry functions on this target"
            } else if target == "wasm32-unknown-unknown" {
                "inauguration owns WebAssembly module emission for const-evaluable scalar entry functions on this target"
            } else {
                RUST_STYLE_TARGET_REASON
            },
            input_stage: "core-ir-or-textual-sil",
            artifact_kind: if target == "x86_64-unknown-linux-gnu" {
                "elf-relocatable-object+elf-executable"
            } else if target == "aarch64-unknown-linux-gnu" {
                "elf-relocatable-object"
            } else if target == "aarch64-apple-darwin" {
                "mach-o-static-archive+app-bundle"
            } else if target == "x86_64-pc-windows-msvc" {
                "pe-executable"
            } else if target == "armv7-unknown-linux-gnueabihf" {
                "elf32-relocatable-object"
            } else if target == "wasm32-unknown-unknown" {
                "wasm-module"
            } else {
                "none"
            },
            host_triple: Some(target),
            backend_artifact_supported: implemented_target(target),
        });
    }
    specs
}

fn implemented_target(target: &str) -> bool {
    matches!(
        target,
        "x86_64-unknown-linux-gnu"
            | "aarch64-unknown-linux-gnu"
            | "aarch64-apple-darwin"
            | "armv7-unknown-linux-gnueabihf"
            | "x86_64-pc-windows-msvc"
            | "wasm32-unknown-unknown"
    )
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn registry_lists_bytecode_and_native_targets() {
        let specs = all_target_specs();
        assert!(specs.len() > 2);
        assert_eq!(specs[0].name, "bytecode");
        assert_eq!(specs[1].name, "native");
    }

    #[test]
    fn registry_lists_rust_style_compiler_targets() {
        let specs = all_target_specs();
        assert_eq!(specs.len(), IN_EQUIVALENT_TARGETS.len() + 2);
        let names: Vec<&str> = specs.iter().map(|spec| spec.name).collect();
        for target in [
            "x86_64-unknown-none",
            "x86_64-unknown-linux-gnu",
            "aarch64-apple-darwin",
            "aarch64-unknown-linux-gnu",
            "armv7-unknown-linux-gnueabihf",
            "x86_64-pc-windows-msvc",
            "wasm32-unknown-unknown",
            "riscv64gc-unknown-none-elf",
        ] {
            assert!(names.contains(&target), "{target}");
            let spec = target_spec_by_name(target).expect("target spec");
            if target == "x86_64-unknown-linux-gnu" {
                assert!(spec.implemented, "{target}");
                assert_eq!(spec.stage, "owned-native-and-object-subset");
                assert_eq!(spec.artifact_kind, "elf-relocatable-object+elf-executable");
                assert!(spec.backend_artifact_supported);
                continue;
            }
            if target == "aarch64-apple-darwin" {
                assert!(spec.implemented, "{target}");
                assert_eq!(spec.stage, "owned-object-subset");
                assert_eq!(spec.artifact_kind, "mach-o-static-archive+app-bundle");
                assert!(spec.backend_artifact_supported);
                continue;
            }
            if target == "x86_64-pc-windows-msvc" {
                assert!(spec.implemented, "{target}");
                assert_eq!(spec.stage, "owned-native-subset");
                assert_eq!(spec.artifact_kind, "pe-executable");
                assert!(spec.backend_artifact_supported);
                continue;
            }
            if target == "aarch64-unknown-linux-gnu" {
                assert!(spec.implemented, "{target}");
                assert_eq!(spec.stage, "owned-object-subset");
                assert_eq!(spec.artifact_kind, "elf-relocatable-object");
                assert!(spec.backend_artifact_supported);
                continue;
            }
            if target == "armv7-unknown-linux-gnueabihf" {
                assert!(spec.implemented, "{target}");
                assert_eq!(spec.stage, "owned-object-subset");
                assert_eq!(spec.artifact_kind, "elf32-relocatable-object");
                assert!(spec.backend_artifact_supported);
                continue;
            }
            if target == "wasm32-unknown-unknown" {
                assert!(spec.implemented, "{target}");
                assert_eq!(spec.stage, "owned-object-subset");
                assert_eq!(spec.artifact_kind, "wasm-module");
                assert!(spec.backend_artifact_supported);
                continue;
            }
            assert!(!spec.implemented, "{target}");
            assert_eq!(spec.stage, "contract-only");
            assert_eq!(spec.reason_code, NATIVE_BACKEND_NOT_IMPLEMENTED);
            assert_eq!(spec.input_stage, "core-ir-or-textual-sil");
            assert_eq!(spec.artifact_kind, "none");
            assert!(!spec.backend_artifact_supported);
        }
    }

    #[test]
    fn reports_bytecode_target_as_owned_runtime_subset() {
        let spec = bytecode_target_spec();
        assert!(spec.implemented);
        assert_eq!(spec.stage, "owned-runtime-subset");
        assert_eq!(spec.reason_code, BYTECODE_BACKEND_SUBSET);
        assert_eq!(spec.input_stage, "core-ir-to-textual-sil");
        assert_eq!(spec.artifact_kind, "bytecode-assembly");
        assert!(spec.backend_artifact_supported);
    }

    #[cfg(not(all(target_os = "macos", target_arch = "aarch64")))]
    #[test]
    fn reports_native_target_contract_on_unsupported_hosts() {
        let spec = native_target_spec();
        assert!(!spec.implemented);
        assert_eq!(spec.stage, "contract-only");
        assert_eq!(spec.reason_code, NATIVE_BACKEND_NOT_IMPLEMENTED);
        assert_eq!(spec.input_stage, "core-ir-or-textual-sil");
        assert_eq!(spec.artifact_kind, "none");
        assert!(!spec.backend_artifact_supported);
        assert!(spec.host_triple.is_none());
    }

    #[cfg(all(target_os = "macos", target_arch = "aarch64"))]
    #[test]
    fn reports_native_target_aarch64_subset_on_host() {
        let spec = native_target_spec();
        assert!(spec.implemented);
        assert_eq!(spec.stage, "owned-native-subset");
        assert_eq!(spec.reason_code, NATIVE_AARCH64_SUBSET);
        assert_eq!(spec.input_stage, "core-ir");
        assert_eq!(spec.artifact_kind, "mach-o-executable");
        assert_eq!(spec.host_triple, Some("aarch64-apple-darwin"));
        assert!(!spec.backend_artifact_supported);
    }

    #[test]
    fn target_id_round_trips_known_names() {
        assert_eq!(TargetId::parse("bytecode"), Some(TargetId::Bytecode));
        assert_eq!(TargetId::parse("native"), Some(TargetId::Native));
        assert_eq!(TargetId::parse("wasm"), None);
    }
}
