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

use std::fmt::Write;

mod common;

#[test]
fn line_break_br() {
    assert_eq!(common::translate("a<br>b"), "a  \nb");
}

#[test]
fn horizontal_rule_hr() {
    assert_eq!(common::translate("a<hr>b"), "a\n\n---\n\nb");
}

#[test]
fn bold_b_strong() {
    let res = common::translate(
        "<b>a<del>b</del><br><br>c<br>d</b><strong>a<del>b</del><br><br>c<br>d</strong>",
    );
    let exp = "**a~~b~~** \n  \n**c** \n**d**";
    assert_eq!(res, format!("{exp} {exp}"));
}

#[test]
fn strikethrough_del_s_strike() {
    let res = common::translate(
        "<del>a<em>b</em><br><br>c<br>d</del><s>a<em>b</em><br><br>c<br>d</s><strike>a<em>b</em><br><br>c<br>d</strike>",
    );
    let exp = "~~a_b_~~ \n  \n~~c~~ \n~~d~~";
    assert_eq!(res, format!("{exp} {exp} {exp}"));
}

#[test]
fn italic_emphasis_em_i() {
    let res = common::translate("<em>a <s>b</s><br><br>c<br>d</em><i>a <s>b</s><br><br>c<br>d</i>");
    let exp = "_a ~~b~~_ \n  \n_c_ \n_d_";
    assert_eq!(res, format!("{exp} {exp}"));
}

#[test]
fn block_quote_blockquote() {
    let res = common::translate("<blockquote>a<br>b<br>c<blockquote>def</blockquote>");
    assert_eq!(res, "> a  \n> b  \n> c\n> \n>> def");
}

#[test]
fn headings_h1_to_h6() {
    let html = "<h1>a<b>b</b></h1><h2>a<b>b</b></h2><h3>a<b>b</b></h3><h4>a<b>b</b></h4><h5>a<b>b</b></h5><h6>a<b>b</b></h6>";
    let expected = (1..=6)
        .fold(String::new(), |mut out, i| {
            write!(&mut out, "{} a**b**\n\n", "#".repeat(i)).unwrap();
            out
        })
        .trim()
        .to_owned();
    assert_eq!(common::translate(html), expected);
}

#[test]
fn link_a() {
    let url = "http://www.github.com/crosstype";
    let special_url = "http://www.github.com/crosstype/**/_test(123)";
    let encoded_special_url = "http://www.github.com/crosstype/%2A%2A/%5Ftest%28123%29";
    let res = common::translate(&format!(
        r#"
        <a href="{url}">a<br><br>b<strong>c</strong></a>
        <a>a<strong>b</strong></a>
        <a href="{url}">{url}</a>
        <a href="{url}">a<a href="2">nested</a><img src="{url}">b</a>
        <b><i><a href="{special_url}" title="a">b</a></i></b>
        "#
    ));
    assert_eq!(
        res,
        format!(
            "[a b**c**]({url}) a**b** <{url}> [a]({url})[nested](2)![]({url})b **_[b]({encoded_special_url} \"a\")_**"
        )
    );
}

#[test]
fn image_img() {
    let url = "http://www.github.com/crosstype/";
    let res = common::translate(&format!(
        r#"
        <img src="{url}1">
        <img title="t2" alt="a2">
        <img src="{url}3" title="t3">
        <img src="{url}4" title="t4" alt="a4">
        <img src="data:image/gif;base64,R/">
        "#
    ));
    assert_eq!(
        res,
        format!("![]({url}1) ![]({url}3 \"t3\") ![a4]({url}4 \"t4\")")
    );
}

#[test]
fn pre_formatted_text_pre() {
    let text = "*   test \t\n1. test\n\\Test";
    let res = common::translate(&format!("<pre>{text}<br><b># hello</b></pre>"));
    assert_eq!(res, format!("{text}  \n**# hello**"));
}

#[test]
fn code_inline_code() {
    let res = common::translate("<code>```` a    \n\nb\n* c</code><code>d</code>");
    assert_eq!(res, "````` ```` a b * c ````` `d`");
}

#[test]
fn code_block_fenced() {
    let text = "* test  \n\n1. test\n\\Test";
    let res = common::translate(&format!(
        "<pre><code class=\"language-fortran\">{text}</code></pre><pre><code>{text}</code></pre>"
    ));
    assert_eq!(res, format!("```fortran\n{text}\n```\n\n```\n{text}\n```"));
}

#[test]
fn code_block_indented() {
    let text = "* test  \n\n1. test\n\\Test";
    let mut converter = skymark::HtmlToMarkdown::new();
    converter.options_mut().code_block_style = skymark::CodeBlockStyle::Indented;
    let res = converter.translate(&format!(
        "<pre><code class=\"language-fortran\">{text}</code></pre><pre><code>{text}</code></pre>"
    ));
    let expected = text.replace('\n', "\n    ");
    assert_eq!(res, format!("    {expected}\n\n    {expected}"));
}

#[test]
fn multi_level_ordered_list() {
    let res = common::translate(
        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,
        "1. a  \n    \n~~b~~\n2. b  \n  1. c  \n  d\n  * e  \n  f"
    );
}

#[test]
fn multi_level_unordered_list() {
    let res = common::translate(
        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,
        "* a  \n    \n~~b~~\n* b  \n  * c  \n  d\n  1. e  \n  f"
    );
}

#[test]
fn list_item_with_block_content() {
    let res = common::translate("<li><div><img src=\"hello.jpg\"></div>a");
    assert_eq!(res, "* ![](hello.jpg)  \na");
}

#[test]
fn three_level_nested_unordered_list() {
    let res = common::translate(
        r#"
        <ul>
          <li>a
            <ul>
              <li>b
                <ul>
                  <li>c</li>
                </ul>
              </li>
            </ul>
          </li>
        </ul>
      "#,
    );
    assert_eq!(res, "* a  \n  * b  \n    * c");
}

#[test]
fn three_level_nested_ordered_list() {
    let res = common::translate(
        r#"
        <ol>
          <li>a
            <ol>
              <li>b
                <ol>
                  <li>c</li>
                </ol>
              </li>
            </ol>
          </li>
        </ol>
      "#,
    );
    assert_eq!(res, "1. a  \n  1. b  \n    1. c");
}

#[test]
fn four_level_nested_unordered_list() {
    let res = common::translate(
        r#"
        <ul>
          <li>a
            <ul>
              <li>b
                <ul>
                  <li>c
                    <ul>
                      <li>d</li>
                    </ul>
                  </li>
                </ul>
              </li>
            </ul>
          </li>
        </ul>
      "#,
    );
    assert_eq!(res, "* a  \n  * b  \n    * c  \n      * d");
}

#[test]
fn four_level_nested_ordered_list() {
    let res = common::translate(
        r#"
        <ol>
          <li>a
            <ol>
              <li>b
                <ol>
                  <li>c
                    <ol>
                      <li>d</li>
                    </ol>
                  </li>
                </ol>
              </li>
            </ol>
          </li>
        </ol>
      "#,
    );
    assert_eq!(res, "1. a  \n  1. b  \n    1. c  \n      1. d");
}

#[test]
fn four_level_mixed_nested_list() {
    let res = common::translate(
        r#"
        <ul>
          <li>a
            <ol>
              <li>b
                <ul>
                  <li>c
                    <ol>
                      <li>d</li>
                    </ol>
                  </li>
                </ul>
              </li>
            </ol>
          </li>
        </ul>
      "#,
    );
    assert_eq!(res, "* a  \n  1. b  \n    * c  \n      1. d");
}
