import pytest

from jinja2.environment import Environment
from jinja2.exceptions import TemplateNotFound
from jinja2.exceptions import TemplatesNotFound
from jinja2.exceptions import TemplateSyntaxError
from jinja2.exceptions import UndefinedError
from jinja2.loaders import DictLoader


@pytest.fixture
def test_env():
    env = Environment(
        loader=DictLoader(
            dict(
                module="{% macro test() %}[{{ foo }}|{{ bar }}]{% endmacro %}",
                header="[{{ foo }}|{{ 23 }}]",
                o_printer="({{ o }})",
            )
        )
    )
    env.globals["bar"] = 23
    return env


class TestImports:
    def test_context_imports(self, test_env):
        t = test_env.from_string('{% import "module" as m %}{{ m.test() }}')
        assert t.render(foo=42) == "[|23]"
        t = test_env.from_string(
            '{% import "module" as m without context %}{{ m.test() }}'
        )
        assert t.render(foo=42) == "[|23]"
        t = test_env.from_string(
            '{% import "module" as m with context %}{{ m.test() }}'
        )
        assert t.render(foo=42) == "[42|23]"
        t = test_env.from_string('{% from "module" import test %}{{ test() }}')
        assert t.render(foo=42) == "[|23]"
        t = test_env.from_string(
            '{% from "module" import test without context %}{{ test() }}'
        )
        assert t.render(foo=42) == "[|23]"
        t = test_env.from_string(
            '{% from "module" import test with context %}{{ test() }}'
        )
        assert t.render(foo=42) == "[42|23]"

    def test_import_needs_name(self, test_env):
        test_env.from_string('{% from "foo" import bar %}')
        test_env.from_string('{% from "foo" import bar, baz %}')

        with pytest.raises(TemplateSyntaxError):
            test_env.from_string('{% from "foo" import %}')

    def test_no_trailing_comma(self, test_env):
        with pytest.raises(TemplateSyntaxError):
            test_env.from_string('{% from "foo" import bar, %}')

        with pytest.raises(TemplateSyntaxError):
            test_env.from_string('{% from "foo" import bar,, %}')

        with pytest.raises(TemplateSyntaxError):
            test_env.from_string('{% from "foo" import, %}')

    def test_trailing_comma_with_context(self, test_env):
        test_env.from_string('{% from "foo" import bar, baz with context %}')
        test_env.from_string('{% from "foo" import bar, baz, with context %}')
        test_env.from_string('{% from "foo" import bar, with context %}')
        test_env.from_string('{% from "foo" import bar, with, context %}')
        test_env.from_string('{% from "foo" import bar, with with context %}')

        with pytest.raises(TemplateSyntaxError):
            test_env.from_string('{% from "foo" import bar,, with context %}')

        with pytest.raises(TemplateSyntaxError):
            test_env.from_string('{% from "foo" import bar with context, %}')

    def test_exports(self, test_env):
        m = test_env.from_string(
            """
            {% macro toplevel() %}...{% endmacro %}
            {% macro __private() %}...{% endmacro %}
            {% set variable = 42 %}
            {% for item in [1] %}
                {% macro notthere() %}{% endmacro %}
            {% endfor %}
        """
        ).module
        assert m.toplevel() == "..."
        assert not hasattr(m, "__missing")
        assert m.variable == 42
        assert not hasattr(m, "notthere")

    def test_not_exported(self, test_env):
        t = test_env.from_string("{% from 'module' import nothing %}{{ nothing() }}")

        with pytest.raises(UndefinedError, match="does not export the requested name"):
            t.render()

    def test_import_with_globals(self, test_env):
        env = Environment(
            loader=DictLoader(
                {
                    "macros": "{% macro test() %}foo: {{ foo }}{% endmacro %}",
                    "test": "{% import 'macros' as m %}{{ m.test() }}",
                    "test1": "{% import 'macros' as m %}{{ m.test() }}",
                }
            )
        )
        tmpl = env.get_template("test", globals={"foo": "bar"})
        assert tmpl.render() == "foo: bar"

        tmpl = env.get_template("test1")
        assert tmpl.render() == "foo: "

    def test_import_with_globals_override(self, test_env):
        env = Environment(
            loader=DictLoader(
                {
                    "macros": "{% set foo = '42' %}{% macro test() %}"
                    "foo: {{ foo }}{% endmacro %}",
                    "test": "{% from 'macros' import test %}{{ test() }}",
                }
            )
        )
        tmpl = env.get_template("test", globals={"foo": "bar"})
        assert tmpl.render() == "foo: 42"

    def test_from_import_with_globals(self, test_env):
        env = Environment(
            loader=DictLoader(
                {
                    "macros": "{% macro testing() %}foo: {{ foo }}{% endmacro %}",
                    "test": "{% from 'macros' import testing %}{{ testing() }}",
                }
            )
        )
        tmpl = env.get_template("test", globals={"foo": "bar"})
        assert tmpl.render() == "foo: bar"


class TestIncludes:
    def test_context_include(self, test_env):
        t = test_env.from_string('{% include "header" %}')
        assert t.render(foo=42) == "[42|23]"
        t = test_env.from_string('{% include "header" with context %}')
        assert t.render(foo=42) == "[42|23]"
        t = test_env.from_string('{% include "header" without context %}')
        assert t.render(foo=42) == "[|23]"

    def test_choice_includes(self, test_env):
        t = test_env.from_string('{% include ["missing", "header"] %}')
        assert t.render(foo=42) == "[42|23]"

        t = test_env.from_string('{% include ["missing", "missing2"] ignore missing %}')
        assert t.render(foo=42) == ""

        t = test_env.from_string('{% include ["missing", "missing2"] %}')
        pytest.raises(TemplateNotFound, t.render)
        with pytest.raises(TemplatesNotFound) as e:
            t.render()

        assert e.value.templates == ["missing", "missing2"]
        assert e.value.name == "missing2"

        def test_includes(t, **ctx):
            ctx["foo"] = 42
            assert t.render(ctx) == "[42|23]"

        t = test_env.from_string('{% include ["missing", "header"] %}')
        test_includes(t)
        t = test_env.from_string("{% include x %}")
        test_includes(t, x=["missing", "header"])
        t = test_env.from_string('{% include [x, "header"] %}')
        test_includes(t, x="missing")
        t = test_env.from_string("{% include x %}")
        test_includes(t, x="header")
        t = test_env.from_string("{% include [x] %}")
        test_includes(t, x="header")

    def test_include_ignoring_missing(self, test_env):
        t = test_env.from_string('{% include "missing" %}')
        pytest.raises(TemplateNotFound, t.render)
        for extra in "", "with context", "without context":
            t = test_env.from_string(
                '{% include "missing" ignore missing ' + extra + " %}"
            )
            assert t.render() == ""

    def test_context_include_with_overrides(self, test_env):
        env = Environment(
            loader=DictLoader(
                dict(
                    main="{% for item in [1, 2, 3] %}{% include 'item' %}{% endfor %}",
                    item="{{ item }}",
                )
            )
        )
        assert env.get_template("main").render() == "123"

    def test_unoptimized_scopes(self, test_env):
        t = test_env.from_string(
            """
            {% macro outer(o) %}
            {% macro inner() %}
            {% include "o_printer" %}
            {% endmacro %}
            {{ inner() }}
            {% endmacro %}
            {{ outer("FOO") }}
        """
        )
        assert t.render().strip() == "(FOO)"

    def test_import_from_with_context(self):
        env = Environment(
            loader=DictLoader({"a": "{% macro x() %}{{ foobar }}{% endmacro %}"})
        )
        t = env.from_string(
            "{% set foobar = 42 %}{% from 'a' import x with context %}{{ x() }}"
        )
        assert t.render() == "42"
