import os
import unittest

from splitnodes import (markdown_to_blocks, markdown_to_html_node,
                        split_nodes_delimiter, split_nodes_image,
                        split_nodes_link, text_to_text_node)
from textnode import TextNode, TextType


class TestSplitNodes(unittest.TestCase):
    def test_split_nodes_delimiter_when_given_empty_list_it_should_return_empty_list(
        self,
    ):
        expected = []

        result = split_nodes_delimiter([], "`", TextType.CODE)

        self.assertListEqual(result, expected)

    def test_split_nodes_delimiter_when_given_no_plain_type_it_should_return_with_no_changes(
        self,
    ):
        code_node = TextNode("test", TextType.CODE)
        expected = [code_node]

        result = split_nodes_delimiter([code_node], "`", TextType.CODE)

        self.assertListEqual(result, expected)

    def test_split_nodes_delimiter_when_given_no_matching_delimiter_it_should_raise_error(
        self,
    ):
        text_node = TextNode("This is text with a `code", TextType.PLAIN)

        with self.assertRaises(RuntimeError):
            split_nodes_delimiter([text_node], "`", TextType.CODE)

    def test_split_nodes_delimiter_when_given_bold_input_it_should_return_expected_list(
        self,
    ):
        expected = [
            TextNode("This is text with a ", TextType.PLAIN),
            TextNode("bolded phrase", TextType.BOLD),
            TextNode(" in the middle", TextType.PLAIN),
        ]

        text_node = TextNode(
            "This is text with a **bolded phrase** in the middle", TextType.PLAIN
        )

        result = split_nodes_delimiter([text_node], "**", TextType.BOLD)

        self.assertListEqual(result, expected)

    def test_split_nodes_delimiter_when_given_italics_input_it_should_return_expected_list(
        self,
    ):
        expected = [
            TextNode("This is text with a ", TextType.PLAIN),
            TextNode("italicized phrase", TextType.ITALIC),
            TextNode(" in the middle", TextType.PLAIN),
        ]

        text_node = TextNode(
            "This is text with a _italicized phrase_ in the middle", TextType.PLAIN
        )

        result = split_nodes_delimiter([text_node], "_", TextType.ITALIC)

        self.assertListEqual(result, expected)

    def test_split_nodes_delimiter_when_given_code_input_it_should_return_expected_list(
        self,
    ):
        expected = [
            TextNode("This is text with a ", TextType.PLAIN),
            TextNode("code phrase", TextType.CODE),
            TextNode(" in the middle", TextType.PLAIN),
        ]

        text_node = TextNode(
            "This is text with a `code phrase` in the middle", TextType.PLAIN
        )

        result = split_nodes_delimiter([text_node], "`", TextType.CODE)

        self.assertListEqual(result, expected)

    def test_split_nodes_image_when_given_image_it_should_return_expected_list(self):
        expected = [
            TextNode("This is text with an ", TextType.PLAIN),
            TextNode("image", TextType.IMAGE, "https://i.imgur.com/zjjcJKZ.png"),
            TextNode(" and another ", TextType.PLAIN),
            TextNode("second image", TextType.IMAGE, "https://i.imgur.com/3elNhQu.png"),
        ]

        node = TextNode(
            "This is text with an ![image](https://i.imgur.com/zjjcJKZ.png) and another ![second image](https://i.imgur.com/3elNhQu.png)",
            TextType.PLAIN,
        )

        result = split_nodes_image([node])

        self.assertListEqual(result, expected)

    def test_split_nodes_link_when_given_link_it_should_return_expected_list(self):
        expected = [
            TextNode("This is text with a link ", TextType.PLAIN),
            TextNode("to boot dev", TextType.LINK, "https://www.boot.dev"),
            TextNode(" and ", TextType.PLAIN),
            TextNode(
                "to youtube", TextType.LINK, "https://www.youtube.com/@bootdotdev"
            ),
        ]

        node = TextNode(
            "This is text with a link [to boot dev](https://www.boot.dev) and [to youtube](https://www.youtube.com/@bootdotdev)",
            TextType.PLAIN,
        )

        result = split_nodes_link([node])

        self.assertListEqual(result, expected)

    def test_text_to_text_node_when_called_it_should_return_expected_list(self):
        expected = [
            TextNode("This is ", TextType.PLAIN),
            TextNode("text", TextType.BOLD),
            TextNode(" with an ", TextType.PLAIN),
            TextNode("italic", TextType.ITALIC),
            TextNode(" word and a ", TextType.PLAIN),
            TextNode("code block", TextType.CODE),
            TextNode(" and an ", TextType.PLAIN),
            TextNode(
                "obi wan image", TextType.IMAGE, "https://i.imgur.com/fJRm4Vk.jpeg"
            ),
            TextNode(" and a ", TextType.PLAIN),
            TextNode("link", TextType.LINK, "https://boot.dev"),
        ]

        text = "This is **text** with an _italic_ word and a `code block` and an ![obi wan image](https://i.imgur.com/fJRm4Vk.jpeg) and a [link](https://boot.dev)"

        result = text_to_text_node(text)

        self.maxDiff = None
        self.assertListEqual(result, expected)

    def test_markdown_to_bocks_when_called_with_md_it_should_return_expected_blocks(
        self,
    ):
        expected = [
            "This is **bolded** paragraph",
            "This is another paragraph with _italic_ text and `code` here\nThis is the same paragraph on a new line",
            "- This is a list\n- with items",
        ]

        md = """
This is **bolded** paragraph

This is another paragraph with _italic_ text and `code` here
This is the same paragraph on a new line

- This is a list
- with items
"""

        result = markdown_to_blocks(md)

        self.assertListEqual(result, expected)

    def test_paragraphs(self):
        expected = "<div><p>This is <b>bolded</b> paragraph text in a p tag here</p><p>This is another paragraph with <i>italic</i> text and <code>code</code> here</p></div>"

        md = """
This is **bolded** paragraph
text in a p
tag here

This is another paragraph with _italic_ text and `code` here

"""

        node = markdown_to_html_node(md)
        html = node.to_html()

        self.assertEqual(html, expected)

    def test_codeblock(self):
        expected = "<div><pre><code>This is text that _should_ remain\nthe **same** even with inline stuff\n</code></pre></div>"

        md = """
```
This is text that _should_ remain
the **same** even with inline stuff
```
"""

        node = markdown_to_html_node(md)
        html = node.to_html()

        with open("output.txt", "w") as file:
            file.write(expected)
            file.write("\n\n")
            file.write(html)

        self.assertEqual(html, expected)
