use microformats::types::{PropertyValue, UrlValue};

use crate::algorithms::representative_hcard::for_url;

#[tokio::test]
async fn directly_on_page() {
    let mut client = crate::test::Client::new().await;
    let page_mock = client
        .mock_server
        .mock("GET", "/rep-hcard/on-page")
        .expect(1)
        .match_header(
            "accept",
            mockito::Matcher::Regex("(.*)text/html(.*)".into()),
        )
        .with_header("content-type", "text/html")
        .with_body(
            r#"<html>
    <body class="h-card">
        <a href="" class="u-uid u-url"></a>
    </body>
</html>"#,
        )
        .create_async()
        .await;

    let item_result = for_url(
        &client,
        &format!("{}/rep-hcard/on-page", client.mock_server.url())
            .parse()
            .unwrap(),
    )
    .await;
    assert_eq!(
        item_result.as_ref().err(),
        None,
        "no errors when parsing rep h-card"
    );
    page_mock.assert_async().await;
}

#[tokio::test]
async fn rel_me_association_on_page() {
    let mut client = crate::test::Client::new().await;
    let page_mock = client
        .mock_server
        .mock("GET", "/rep-hcard/via-relme")
        .expect(1)
        .match_header(
            "accept",
            mockito::Matcher::Regex("(.*)text/html(.*)".into()),
        )
        .with_header("content-type", "text/html")
        .with_body(
            r#"<html>
    <head>
        <link rel="me" href="/foo-bar" />
    </head>
    <body class="h-card">
        <a href="/foo-bar" class="u-url"></a>
    </body>
</html>"#,
        )
        .create_async()
        .await;

    let r = for_url(
        &client,
        &format!("{}/rep-hcard/via-relme", client.mock_server.url())
            .parse()
            .unwrap(),
    )
    .await;
    assert_eq!(r.as_ref().err(), None, "no errors when parsing rep h-card");
    page_mock.assert_async().await;
}

#[tracing_test::traced_test]
#[tokio::test]
async fn solo_card() {
    let mut client = crate::test::Client::new().await;
    let page_mock = client
        .mock_server
        .mock("GET", "/rep-hcard/only-one")
        .expect(1)
        .match_header(
            "accept",
            mockito::Matcher::Regex("(.*)text/html(.*)".into()),
        )
        .with_header("content-type", "text/html")
        .with_body(
            r#"<html>
    <head>
    </head>
    <body class="h-card">
        <a href="/solo-dolo" class="u-url"></a>
    </body>
</html>"#,
        )
        .create_async()
        .await;

    let r = for_url(
        &client,
        &format!("{}/rep-hcard/only-one", client.mock_server.url())
            .parse()
            .unwrap(),
    )
    .await;
    assert_eq!(r.as_ref().err(), None, "no errors when parsing rep h-card");
    page_mock.assert_async().await;
    assert_eq!(
        r.map(|i| i.get_property("url"))
            .ok()
            .flatten()
            .and_then(|v| v.first().cloned()),
        format!("{}/solo-dolo", client.mock_server.url())
            .parse()
            .ok()
            .map(|url| PropertyValue::Url(UrlValue::new(url))),
        "gave expected URL"
    );
}
