//! Catalog of NYASH environment variables (AGENTS.md 287)
//!
//! Provides runtime enumeration of all environment variables used by Hakorune.
//! Used for diagnostics, documentation, and CI validation.

use std::fmt;

/// System where the env var applies
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AppliesTo {
    /// Core runtime (VM, interpreter, executor)
    Runtime,
    /// Parser/Compiler (JoinIR, MIR, backend)
    Compiler,
    /// Macro System (MacroBox, engine, expand)
    Macro,
    /// Box Factory (Plugin, builtin, user-defined)
    BoxFactory,
    /// Testing (Test harness, args, filter)
    Testing,
    /// CLI (Command-line options, logging)
    CLI,
    /// Selfhost (Nyash compiler, toolchain)
    Selfhost,
    /// Unknown/Other
    Other,
}

/// Metadata for an environment variable
#[derive(Debug, Clone)]
pub struct EnvVarMeta {
    pub name: &'static str,
    pub description: &'static str,
    pub applies_to: AppliesTo,
    pub default: Option<&'static str>,
}

impl fmt::Display for EnvVarMeta {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} - {}", self.name, self.description)
    }
}

/// Enumerate all known environment variables (Phase 287)
///
/// This function MUST be kept in sync with actual usage.
/// Run `cargo test env_vars_consistency` to validate.
pub fn env_vars() -> Vec<EnvVarMeta> {
    vec![
        // Macro System (Phase 286A)
        EnvVarMeta {
            name: "NYASH_MACRO_DISABLE",
            description: "Disable macro system entirely (1=true)",
            applies_to: AppliesTo::Macro,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_MACRO_ENABLE",
            description: "Enable macro system (1=true)",
            applies_to: AppliesTo::Macro,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_MACRO_TRACE",
            description: "Trace macro expansion (1=true)",
            applies_to: AppliesTo::Macro,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_MACRO_MAX_PASSES",
            description: "Max macro expansion passes",
            applies_to: AppliesTo::Macro,
            default: Some("32"),
        },
        EnvVarMeta {
            name: "NYASH_MACRO_CYCLE_WINDOW",
            description: "Cycle detection window size",
            applies_to: AppliesTo::Macro,
            default: Some("8"),
        },
        EnvVarMeta {
            name: "NYASH_MACRO_DERIVE_ALL",
            description: "Derive all Equals+ToString (1=true)",
            applies_to: AppliesTo::Macro,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_MACRO_DERIVE",
            description: "Comma-separated derive targets (Equals,ToString)",
            applies_to: AppliesTo::Macro,
            default: Some("Equals,ToString"),
        },
        EnvVarMeta {
            name: "NYASH_MACRO_TRACE_JSONL",
            description: "Path to JSONL trace file",
            applies_to: AppliesTo::Macro,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_MACRO_PATHS",
            description: "Comma-separated macro source paths",
            applies_to: AppliesTo::Macro,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_MACRO_BOX_NY",
            description: "Enable Nyash MacroBox loading (1=true)",
            applies_to: AppliesTo::Macro,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_MACRO_BOX_NY_PATHS",
            description: "Legacy alias for NYASH_MACRO_PATHS",
            applies_to: AppliesTo::Macro,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_MACRO_BOX",
            description: "Enable MacroBox execution (1=true)",
            applies_to: AppliesTo::Macro,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_MACRO_BOX_EXAMPLE",
            description: "Enable built-in UppercasePrintMacro (1=true)",
            applies_to: AppliesTo::Macro,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_MACRO_BOX_ENABLE",
            description: "Comma-separated MacroBox names",
            applies_to: AppliesTo::Macro,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_MACRO_STRICT",
            description: "Strict error mode (1=true)",
            applies_to: AppliesTo::Macro,
            default: Some("1"),
        },
        EnvVarMeta {
            name: "NYASH_MACRO_TOPLEVEL_ALLOW",
            description: "Allow top-level static functions (deprecated)",
            applies_to: AppliesTo::Macro,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_MACRO_BOX_CHILD_RUNNER",
            description: "Use runner script for macro expansion (deprecated)",
            applies_to: AppliesTo::Macro,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_MACRO_BOX_CHILD",
            description: "Enable child-process mode for macro expansion",
            applies_to: AppliesTo::Macro,
            default: Some("1"),
        },
        EnvVarMeta {
            name: "NYASH_MACRO_BOX_NY_IDENTITY_ROUNDTRIP",
            description: "Roundtrip identity macros via JSON",
            applies_to: AppliesTo::Macro,
            default: None,
        },
        // Test Harness (Phase 286A)
        EnvVarMeta {
            name: "NYASH_TEST_RUN",
            description: "Enable test harness injection (1=true)",
            applies_to: AppliesTo::Testing,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_TEST_ARGS_JSON",
            description: "JSON args for test functions",
            applies_to: AppliesTo::Testing,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_TEST_ARGS_DEFAULTS",
            description: "Use zero defaults for missing test args (1=true)",
            applies_to: AppliesTo::Testing,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_TEST_FILTER",
            description: "Substring filter for test names",
            applies_to: AppliesTo::Testing,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_TEST_FORCE",
            description: "Force harness injection even with main (1=true)",
            applies_to: AppliesTo::Testing,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_TEST_ENTRY",
            description: "Entry policy: wrap|override",
            applies_to: AppliesTo::Testing,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_TEST_RETURN",
            description: "Return policy: tests|original",
            applies_to: AppliesTo::Testing,
            default: None,
        },
        // Box Factory (Phase 286B)
        EnvVarMeta {
            name: "NYASH_BOX_FACTORY_POLICY",
            description: "Factory policy: strict_plugin_first|compat_plugin_first|builtin_first",
            applies_to: AppliesTo::BoxFactory,
            default: Some("strict_plugin_first"),
        },
        EnvVarMeta {
            name: "NYASH_USE_PLUGIN_BUILTINS",
            description: "Allow plugins to override builtins (1=true)",
            applies_to: AppliesTo::BoxFactory,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_PLUGIN_OVERRIDE_TYPES",
            description: "Comma-separated types plugins may override",
            applies_to: AppliesTo::BoxFactory,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_DISABLE_PLUGINS",
            description: "Disable all plugins (1=true)",
            applies_to: AppliesTo::BoxFactory,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_DEBUG_PLUGIN",
            description: "Debug plugin loading (1=true)",
            applies_to: AppliesTo::BoxFactory,
            default: None,
        },
        // Runtime (Phase 29ab)
        EnvVarMeta {
            name: "NYASH_STR_CP",
            description: "String index mode: 1=codepoint, 0=byte (default)",
            applies_to: AppliesTo::Runtime,
            default: Some("0"),
        },
        // Selfhost (Phase 286B)
        EnvVarMeta {
            name: "NYASH_NY_COMPILER_TIMEOUT_MS",
            description: "Timeout for child Nyash compiler (ms)",
            applies_to: AppliesTo::Selfhost,
            default: Some("2000"),
        },
        EnvVarMeta {
            name: "NYASH_NY_COMPILER_MIN_JSON",
            description: "Minimize JSON output from Nyash compiler (1=true)",
            applies_to: AppliesTo::Selfhost,
            default: None,
        },
        // CLI (Phase 286B)
        EnvVarMeta {
            name: "NYASH_CLI_VERBOSE",
            description: "Verbose CLI output (1=true)",
            applies_to: AppliesTo::CLI,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_ROOT",
            description: "Repo root hint for tools/path resolution (optional)",
            applies_to: AppliesTo::CLI,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_RESOLVE_TRACE",
            description: "Trace using/prelude resolution (1=true)",
            applies_to: AppliesTo::Compiler,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_RESOLVE_SEAM_DEBUG",
            description: "Insert using boundary markers for diagnostics (1=true)",
            applies_to: AppliesTo::Compiler,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_RESOLVE_DUMP_MERGED",
            description: "Dump merged prelude+main source to the given path",
            applies_to: AppliesTo::Compiler,
            default: None,
        },
        // Macro capabilities (Phase 286A)
        EnvVarMeta {
            name: "NYASH_MACRO_CAP_IO",
            description: "Allow IO in macros (FileBox, PathBox)",
            applies_to: AppliesTo::Macro,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_MACRO_CAP_NET",
            description: "Allow network in macros (HTTP, Socket)",
            applies_to: AppliesTo::Macro,
            default: None,
        },
        EnvVarMeta {
            name: "NYASH_MACRO_CAP_ENV",
            description: "Allow env read in macros",
            applies_to: AppliesTo::Macro,
            default: None,
        },
    ]
}

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

    #[test]
    fn test_env_vars_all_have_descriptions() {
        for meta in env_vars() {
            assert!(!meta.description.is_empty(), "{} has no description", meta.name);
            assert!(!meta.name.is_empty(), "empty name found");
        }
    }

    #[test]
    fn test_env_vars_no_duplicates() {
        let names: Vec<&str> = env_vars().iter().map(|m| m.name).collect();
        let mut seen = std::collections::HashSet::new();
        for name in names {
            assert!(
                !seen.contains(name),
                "Duplicate env var: {}",
                name
            );
            seen.insert(name);
        }
    }

    #[test]
    fn test_env_vars_applies_to_valid() {
        for meta in env_vars() {
            // Just ensure it can be compared without panicking
            let _ = format!("{:?}", meta.applies_to);
        }
    }
}
