//! Canonical URL and hreflang alternate language tags.

use html_escape::encode_double_quoted_attribute;

use crate::types::PageSeo;

/// Render `<link rel="canonical">` and one `<link rel="alternate" hreflang>`
/// per entry in `seo.hreflang`.
pub fn render_canonical_tags(seo: &PageSeo) -> String {
    let mut out = String::new();
    out.push_str(&format!(
        r#"<link rel="canonical" href="{}">"#,
        encode_double_quoted_attribute(&seo.canonical)
    ));
    for alt in &seo.hreflang {
        out.push_str(&format!(
            r#"<link rel="alternate" hreflang="{}" href="{}">"#,
            encode_double_quoted_attribute(&alt.lang),
            encode_double_quoted_attribute(&alt.href)
        ));
    }
    out
}

/// Build a fully-qualified URL from a base URL and a path.
///
/// Both inputs are stringly-typed. Trailing slash on `base_url` and leading
/// slash on `path` are tolerated; the result has exactly one `/` between them.
pub fn join_url(base_url: &str, path: &str) -> String {
    let base = base_url.trim_end_matches('/');
    let p = if path.starts_with('/') {
        path.to_string()
    } else {
        format!("/{path}")
    };
    format!("{base}{p}")
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::types::{HreflangAlt, PageSeo};

    #[test]
    fn renders_canonical_only() {
        let seo = PageSeo::new("Home", "https://example.com/about", "en");
        let html = render_canonical_tags(&seo);
        assert_eq!(
            html,
            r#"<link rel="canonical" href="https://example.com/about">"#
        );
    }

    #[test]
    fn renders_hreflang_alternates() {
        let mut seo = PageSeo::new("Home", "https://example.com/about", "en");
        seo.hreflang = vec![
            HreflangAlt {
                lang: "en".into(),
                href: "https://example.com/about".into(),
            },
            HreflangAlt {
                lang: "es".into(),
                href: "https://example.com/es/about".into(),
            },
            HreflangAlt {
                lang: "x-default".into(),
                href: "https://example.com/about".into(),
            },
        ];
        let html = render_canonical_tags(&seo);
        assert!(html.contains(r#"<link rel="alternate" hreflang="en""#));
        assert!(html.contains(r#"<link rel="alternate" hreflang="es""#));
        assert!(html.contains(r#"<link rel="alternate" hreflang="x-default""#));
    }

    #[test]
    fn join_url_handles_slashes() {
        assert_eq!(
            join_url("https://example.com/", "/about"),
            "https://example.com/about"
        );
        assert_eq!(
            join_url("https://example.com", "about"),
            "https://example.com/about"
        );
        assert_eq!(
            join_url("https://example.com/", "/"),
            "https://example.com/"
        );
    }
}
