#![allow(missing_docs, reason = "allow in tests")]
#![allow(clippy::unwrap_used, reason = "allow in tests")]

use std::fmt::Write;

use skymark::HtmlToMarkdown;

fn translate_as_block(html: &str) -> String {
    HtmlToMarkdown::new().translate(&format!("<pre><code>{html}</code></pre>"))
}

fn fenced(s: &str) -> String {
    format!("```\n{s}\n```")
}

#[test]
fn codeblock_line_break_br() {
    assert_eq!(translate_as_block("a<br>b"), fenced("a\nb"));
}

#[test]
fn codeblock_horizontal_rule_hr() {
    assert_eq!(translate_as_block("a<hr>b"), fenced("a\n\n---\n\nb"));
}

#[test]
fn codeblock_non_processed_elements() {
    let tags = [
        "b",
        "strong",
        "del",
        "s",
        "strike",
        "em",
        "i",
        "code",
        "a",
        "pre",
        "blockquote",
    ];
    let html = tags
        .iter()
        .map(|tag| format!("<{tag}>{tag}</{tag}>"))
        .collect::<Vec<_>>()
        .join(" ");
    assert_eq!(
        translate_as_block(&html),
        fenced("b strong del s strike em i code a pre blockquote")
    );
}

#[test]
fn codeblock_image_img() {
    assert_eq!(
        translate_as_block("a<img src=\"https://www.google.com/\">b"),
        fenced("ab")
    );
}

#[test]
fn codeblock_headings_h1_to_h6() {
    let html = (1..8).fold(String::new(), |mut out, i| {
        write!(&mut out, "<h{i}>a</h{i}>").unwrap();
        out
    });
    assert_eq!(
        translate_as_block(&html),
        fenced("\n[a]\n[a]\n[a]\n[a]\n[a]\n[a]\na")
    );
}

#[test]
fn codeblock_multi_level_ordered_list() {
    // COMPAT: html5ever preserves surrounding whitespace around the empty list item
    // slightly differently than node-html-parser inside <pre><code> blocks.
    let res = translate_as_block(
        r#"
        <ol>
          <li>a<br><br><s>b</s></li>
          <li> </li>
          <li>b
            <ol><li>c<br>d</li></ol>
            <ul><li>e<br>f</li></ul>
          </li>
        </ol>
      "#,
    );
    assert_eq!(
        res,
        fenced(
            "\n        \n          a\n\nb\n          \n          b\n            c\nd\n            e\nf\n        \n      "
        )
    );
}

#[test]
fn codeblock_multi_level_unordered_list() {
    // COMPAT: html5ever preserves surrounding whitespace around the empty list item
    // slightly differently than node-html-parser inside <pre><code> blocks.
    let res = translate_as_block(
        r#"
        <ul>
          <li>a<br><br><s>b</s></li>
          <li> </li>
          <li>b
            <ul><li>c<br>d</li></ul>
            <ol><li>e<br>f</li></ol>
          </li>
        </ul>
      "#,
    );
    assert_eq!(
        res,
        fenced(
            "\n        \n          a\n\nb\n          \n          b\n            c\nd\n            e\nf\n        \n      "
        )
    );
}

#[test]
fn codeblock_block_elements_do_not_add_extra_newlines() {
    assert_eq!(translate_as_block("a<div>b</div>c"), fenced("abc"));
    assert_eq!(translate_as_block("x<p>y</p>z"), fenced("xyz"));
    assert_eq!(
        translate_as_block("foo<blockquote>bar</blockquote>baz"),
        fenced("foobarbaz")
    );
}

#[test]
fn codeblock_table_elements_do_not_add_extra_newlines() {
    assert_eq!(
        translate_as_block("a<tr>b</tr>c<table><td>X</td></table>d"),
        fenced("abcXd")
    );
}

#[test]
fn codeblock_list_elements_do_not_add_extra_newlines() {
    assert_eq!(
        translate_as_block("start<ul><li>item</li></ul>end"),
        fenced("startitemend")
    );
}
