//! Content grid trigger surface.

use crate::primitives::htmx_path;

/// Render the content grid surface: search/tag-filter controls + initial grid
/// container.
pub fn render_content_grid(content_kind: &str, initial_grid_html: &str) -> String {
    let endpoint = htmx_path(&format!("content/{content_kind}"));
    let ctx = minijinja::context! {
        kind => content_kind,
        endpoint => endpoint,
        initial_grid_html => initial_grid_html,
    };
    rustelo_pages_htmx::fragment_env()
        .and_then(|env| {
            env.get_template("partials/content/grid.j2")
                .and_then(|t| t.render(ctx))
                .ok()
        })
        .unwrap_or_else(|| {
            let kind_attr = html_escape::encode_double_quoted_attribute(content_kind);
            let ep_attr = html_escape::encode_double_quoted_attribute(&endpoint);
            format!(
                r##"<section data-grid-host="{kind_attr}" data-loading-states><form hx-get="{ep_attr}" hx-target="closest [data-grid-host] > [data-content-grid]" hx-swap="morph" hx-trigger="keyup changed delay:300ms from:input[name=q], change from:select[name=tag], submit" hx-push-url="true" hx-include="this" hx-sync="this:replace"><input type="search" name="q" placeholder="Search…" autocomplete="off"><select name="tag"><option value="">All tags</option></select></form>{initial_grid_html}</section>"##,
            )
        })
}

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

    #[test]
    fn carries_morph_swap() {
        let html = render_content_grid("blog", "");
        assert!(html.contains(r#"hx-swap="morph""#));
    }

    #[test]
    fn debounces_search_typing() {
        let html = render_content_grid("blog", "");
        assert!(html.contains("keyup changed delay:300ms"));
    }

    #[test]
    fn includes_form_state_via_hx_include() {
        let html = render_content_grid("blog", "");
        assert!(html.contains(r#"hx-include="this""#));
    }

    #[test]
    fn replaces_in_flight_requests() {
        let html = render_content_grid("blog", "");
        assert!(html.contains(r#"hx-sync="this:replace""#));
    }

    #[test]
    fn endpoint_path_matches_kind() {
        let html = render_content_grid("recipes", "");
        assert!(html.contains("/api/htmx/content/recipes"));
    }

    #[test]
    fn embeds_initial_html() {
        let html = render_content_grid("blog", "<ul>INITIAL</ul>");
        assert!(html.contains("INITIAL"));
    }
}
