//! Client-side search runtime module generation.

use serde::Serialize;

const SEARCH_RUNTIME_MODULE: &str = include_str!("search-runtime.js");

/// Resolved options embedded in the client-side search runtime.
#[derive(Clone, Debug, Serialize)]
pub struct SearchRuntimeOptions {
    /// Whether search is enabled.
    ///
    /// Default from the Vite plugin resolver: `true`.
    pub enabled: bool,

    /// Maximum number of results.
    ///
    /// Default from the Vite plugin resolver: `10`.
    pub limit: u32,

    /// Enable prefix matching.
    ///
    /// Default from the Vite plugin resolver: `true`.
    pub prefix: bool,

    /// Search input placeholder.
    ///
    /// Default from the Vite plugin resolver: `"Search documentation..."`.
    pub placeholder: String,

    /// Keyboard shortcut to focus search.
    ///
    /// Default from the Vite plugin resolver: `"/"`.
    pub hotkey: String,
}

/// Generates the client-side search runtime module.
pub fn generate_search_module(options_json: &str, index_path: &str) -> String {
    let index_path_json =
        serde_json::to_string(index_path).unwrap_or_else(|_| "\"/search-index.json\"".to_string());

    SEARCH_RUNTIME_MODULE
        .replace("__OX_CONTENT_SEARCH_OPTIONS__", options_json)
        .replace("__OX_CONTENT_SEARCH_INDEX_PATH__", &index_path_json)
}

/// Generates the client-side search runtime module from typed options.
pub fn generate_search_module_with_options(
    options: &SearchRuntimeOptions,
    index_path: &str,
) -> String {
    let options_json = serde_json::to_string(options).unwrap_or_else(|_| "{}".to_string());
    generate_search_module(&options_json, index_path)
}

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

    #[test]
    fn injects_options_and_json_escaped_index_path() {
        let module = generate_search_module(r#"{"limit":5,"prefix":true}"#, "/docs/search's.json");

        insta::assert_snapshot!(module);
    }

    #[test]
    fn serializes_typed_options() {
        let module = generate_search_module_with_options(
            &SearchRuntimeOptions {
                enabled: true,
                limit: 12,
                prefix: false,
                placeholder: "Find docs".to_string(),
                hotkey: "k".to_string(),
            },
            "/docs/search-index.json",
        );

        insta::assert_snapshot!(module);
    }
}
