//! Names that Power Automate hardcodes -- action types, runAfter statuses,
//! and the function library. Centralized so the rest of the codebase reads
//! the strings from one place instead of inlining them. If PA ever changes
//! its conventions, this is the file to edit.

/// Run-after status strings as PA writes them in the JSON. These are the
/// canonical PascalCase forms used for both `runAfter` arrays on actions
/// and the `runStatus` field on Terminate.
pub mod status {
    pub const SUCCEEDED: &str = "Succeeded";
    pub const FAILED: &str = "Failed";
    pub const SKIPPED: &str = "Skipped";
    pub const TIMED_OUT: &str = "TimedOut";
    pub const CANCELLED: &str = "Cancelled";
}

/// PA action type strings as they appear in the `type` field of each
/// action's JSON object. Also used as default action-key prefixes when
/// the user doesn't supply a name (e.g., `Compose_x`, `Apply_to_each`).
pub mod action {
    // Variable lifecycle.
    pub const INITIALIZE_VARIABLE: &str = "InitializeVariable";
    pub const SET_VARIABLE: &str = "SetVariable";
    pub const INCREMENT_VARIABLE: &str = "IncrementVariable";
    pub const DECREMENT_VARIABLE: &str = "DecrementVariable";
    pub const APPEND_TO_STRING_VARIABLE: &str = "AppendToStringVariable";
    pub const APPEND_TO_ARRAY_VARIABLE: &str = "AppendToArrayVariable";

    // Compute / data.
    pub const COMPOSE: &str = "Compose";

    // Control flow. Foreach action keys derive from the iterator name in
    // source (`foreach thingy in xs` → action key `thingy`); see the
    // resolver's `Stmt::Foreach` arm.
    pub const IF: &str = "If";
    pub const SWITCH: &str = "Switch";
    pub const SCOPE: &str = "Scope";
    pub const FOREACH: &str = "Foreach";
    pub const UNTIL: &str = "Until";
    pub const TERMINATE: &str = "Terminate";

    // Default action keys generated by paxc when no user name is supplied.
    // These match the keys PA's own designer would assign.
    pub const DEFAULT_KEY_CONDITION: &str = "Condition";
}

/// Default action-key prefixes paxc generates when assigning unique action
/// names. For variable mutations, PA's own designer drops the "Variable"
/// suffix when forming the key (e.g., `InitializeVariable` action type
/// produces an `Initialize_<name>` key); these constants match that
/// convention. For control-flow actions where there's no `_<name>`
/// suffix, the prefix here is also the action type and is the same as
/// the constant in [`action`].
pub mod key_prefix {
    pub const INITIALIZE: &str = "Initialize";
    pub const SET: &str = "Set";
    pub const INCREMENT: &str = "Increment";
    pub const DECREMENT: &str = "Decrement";
    pub const APPEND_TO: &str = "Append_to";
    pub const COMPOSE: &str = "Compose";
    pub const SCOPE: &str = "Scope";
    pub const UNTIL: &str = "Until";
    pub const SWITCH: &str = "Switch";
    pub const TERMINATE: &str = "Terminate";
    pub const CONDITION: &str = "Condition";
}

/// Trigger types as written in the `type` field of each trigger. Named
/// `trigger_type` (not `trigger`) to keep the module-level identifier
/// distinct from the AST's `Trigger` enum and from common local-variable
/// names like `trigger` in emitter functions.
pub mod trigger_type {
    pub const REQUEST: &str = "Request";
}

/// Whether `name` matches a function paxc recognizes (via the central
/// registry) or a PA expression accessor. Used by the resolver-error
/// diagnostic to suggest "did you mean to call it?" when an undefined
/// identifier matches a known PA name.
///
/// Derives from `pa::functions::FUNCTIONS` (which holds all callable PA
/// functions, with or without paxr support) plus `pa::functions::ACCESSORS`
/// (the bare expression-prefix names users sometimes call without parens).
/// Pax type keywords (`array`, `object`) are deliberately not in either
/// list, so they don't trigger false hints on plain identifier typos.
pub fn is_known_function(name: &str) -> bool {
    super::functions::lookup(name).is_some() || super::functions::ACCESSORS.contains(&name)
}

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

    /// `is_known_function` must be a superset of the names paxr actually
    /// evaluates -- otherwise a real function call would yield a misleading
    /// "did you mean to call it?" hint or no hint at all. The registry
    /// refactor will replace both the matches! list above and the interpreter
    /// dispatch with one FunctionDef table; this test continues to enforce
    /// the invariant either way.
    #[test]
    fn is_known_function_is_superset_of_evaluated_set() {
        for name in evaluated_function_names() {
            assert!(
                is_known_function(name),
                "evaluated function `{name}` is missing from is_known_function()"
            );
        }
    }

    /// PA accessors and known-but-unimplemented function names are part of
    /// the diagnostic surface. The refactor must not drop them.
    #[test]
    fn is_known_function_covers_accessors_and_stubs() {
        // Pure accessors (PA expression-prefix names users sometimes call
        // bare). Not evaluated by paxr; included for the "did you mean"
        // hint surface only.
        for name in [
            "body",
            "items",
            "outputs",
            "variables",
            "parameters",
            "triggerBody",
            "triggerOutputs",
        ] {
            assert!(is_known_function(name), "accessor `{name}` missing");
        }
        // Real PA functions paxr does not yet evaluate. Listed so users get
        // the call-site hint when they typo or call them bare.
        for name in ["utcNow", "formatDateTime"] {
            assert!(is_known_function(name), "known stub `{name}` missing");
        }
    }
}
