from typing import Optional, Dict, Any
from django.template import TemplateSyntaxError
from django.test import TestCase
from django.template import Template, Context


def render_tpl(tpl: str, context: Optional[Dict[str, Any]] = None) -> str:
    return Template("{% load mjml %}" + tpl).render(Context(context))


class MJMLFixtures:
    TPLS = {
        "simple": """
            {% mjml %}
                <mjml>
                <mj-body>
                <mj-container>
                    <mj-section>
                        <mj-column>
                            <mj-image src="img/test.png"></mj-image>
                            <mj-text font-size="20px" align="center">Test title</mj-text>
                        </mj-column>
                    </mj-section>
                    <mj-section>
                        <mj-column>
                            <mj-button background-color="#ffcc00" font-size="15px">Test button</mj-button>
                        </mj-column>
                    </mj-section>
                </mj-container>
                </mj-body>
                </mjml>
            {% endmjml %}
        """,
        "with_text_context": """
            {% mjml %}
                <mjml>
                <mj-body>
                <mj-container>
                    <mj-section>
                        <mj-column>
                            <mj-text>{{ text }}</mj-text>
                        </mj-column>
                    </mj-section>
                </mj-container>
                </mj-body>
                </mjml>
            {% endmjml %}
        """,
        "with_text_context_and_unicode": """
            {% mjml %}
                <mjml>
                <mj-body>
                <mj-container>
                    <mj-section>
                        <mj-column>
                            <mj-text>Український текст {{ text }} ©</mj-text>
                        </mj-column>
                    </mj-section>
                </mj-container>
                </mj-body>
                </mjml>
            {% endmjml %}
        """,
    }
    SYMBOLS = {
        "smile": "\u263a",
        "checkmark": "\u2713",
        "candy": "\U0001f36d",  # b'\xf0\x9f\x8d\xad'.decode('utf-8')
    }
    TEXTS = {
        "unicode": SYMBOLS["smile"] + SYMBOLS["checkmark"] + SYMBOLS["candy"],
    }


class TestMJMLTemplatetag(MJMLFixtures, TestCase):
    def test_simple(self) -> None:
        html = render_tpl(self.TPLS["simple"])
        self.assertIn("<html ", html)
        self.assertIn("<body", html)
        self.assertIn("20px ", html)
        self.assertIn("Test title", html)
        self.assertIn("Test button", html)

    def test_with_vars(self) -> None:
        context = {
            "title": "Test title",
            "title_size": "20px",
            "btn_label": "Test button",
            "btn_color": "#ffcc00",
        }
        html = render_tpl(
            """
            {% mjml %}
                <mjml>
                <mj-body>
                <mj-container>
                    <mj-section>
                        <mj-column>
                            <mj-image src="img/test.png"></mj-image>
                            <mj-text font-size="{{ title_size }}" align="center">{{ title }}</mj-text>
                        </mj-column>
                    </mj-section>
                    <mj-section>
                        <mj-column>
                            <mj-button background-color="{{ btn_color }}" font-size="15px">{{ btn_label }}</mj-button>
                        </mj-column>
                    </mj-section>
                </mj-container>
                </mj-body>
                </mjml>
            {% endmjml %}
        """,
            context,
        )
        self.assertIn("<html ", html)
        self.assertIn("<body", html)
        for val in context.values():
            self.assertIn(val, html)

    def test_with_tags(self) -> None:
        items = ["test one", "test two", "test three"]
        context = {
            "items": items,
        }
        html = render_tpl(
            """
            {% mjml %}
                <mjml>
                <mj-body>
                <mj-container>
                    <mj-section>
                        <mj-column>
                            <mj-image src="img/test.png"></mj-image>
                            <mj-text font-size="20px" align="center">Test title</mj-text>
                        </mj-column>
                    </mj-section>
                    <mj-section>
                        <mj-column>
                            {# test_comment #}
                            {% for item in items %}
                                <mj-text align="center">{{ item }}</mj-text>
                            {% endfor %}
                            <mj-button background-color="#ffcc00" font-size="15px">Test button</mj-button>
                        </mj-column>
                    </mj-section>
                </mj-container>
                </mj-body>
                </mjml>
            {% endmjml %}
        """,
            context,
        )
        self.assertIn("<html ", html)
        self.assertIn("<body", html)
        for item in items:
            self.assertIn(item, html)
        self.assertNotIn("test_comment", html)

    def test_error(self) -> None:
        with self.assertRaises(TemplateSyntaxError):
            render_tpl(
                """
                {% mjml "var"%}
                    <mjml><mj-body><mj-container></mj-container></mj-body></mjml>
                {% endmjml %}
            """
            )

        with self.assertRaises(TemplateSyntaxError):
            render_tpl(
                """
                {% mjml var %}
                    <mjml><mj-body><mj-container></mj-container></mj-body></mjml>
                {% endmjml %}
            """,
                {"var": "test"},
            )

    def test_unicode(self) -> None:
        html = render_tpl(
            self.TPLS["with_text_context_and_unicode"],
            {
                "text": self.TEXTS["unicode"],
            },
        )
        self.assertIn("<html ", html)
        self.assertIn("<body", html)
        self.assertIn("Український текст", html)
        self.assertIn(self.TEXTS["unicode"], html)
        self.assertIn("©", html)
