#!/usr/bin/python3

import typing

import pytest

import ecological


def test_regular_types(monkeypatch):
    monkeypatch.setenv("INTEGER", "42")
    monkeypatch.setenv("BOOLEAN", "False")
    monkeypatch.setenv("ANY_STR", "AnyStr Example")
    monkeypatch.setenv("TEXT", "Text Example")
    monkeypatch.setenv("DICT", "{'key': 'value'}")
    monkeypatch.setenv("LIST", "[1, 2, 3]")

    class Configuration(ecological.AutoConfig):
        integer: int
        boolean: bool
        any_str: typing.AnyStr
        default: str = "Default Value"
        text: typing.Text
        dict: typing.Dict[str, str]
        list: typing.List[int]

    assert Configuration.integer == 42
    assert Configuration.boolean is False
    assert Configuration.any_str == "AnyStr Example"
    assert Configuration.default == "Default Value"
    assert Configuration.text == "Text Example"
    assert Configuration.dict == {'key': 'value'}
    assert Configuration.list == [1, 2, 3]


def test_nested(monkeypatch):
    monkeypatch.setenv("INTEGER", "42")
    monkeypatch.setenv("NESTED_BOOLEAN", "False")

    class Configuration(ecological.AutoConfig):
        integer: int

        class Nested(ecological.AutoConfig, prefix='nested'):
            boolean: bool

    assert Configuration.integer == 42
    assert Configuration.Nested.boolean is False


def test_explicit_variable(monkeypatch):
    monkeypatch.setenv("TEST_Integer", "42")

    class Configuration(ecological.AutoConfig, prefix="this_is_going_to_be_ignored"):
        var1a = ecological.Variable("TEST_Integer", transform=lambda v, wt: int(v))
        var1b: str = ecological.Variable("TEST_Integer", transform=lambda v, wt: v * 2)
        var2: bool = ecological.Variable("404", default=False)

    assert Configuration.var1a == 42
    assert Configuration.var1b == "4242"
    assert Configuration.var2 is False


def test_prefix(monkeypatch):
    monkeypatch.setenv("PREFIX_INTEGER", "42")
    monkeypatch.setenv("PREFIX_BOOLEAN", "False")
    monkeypatch.setenv("PREFIX_NOT_DEFAULT", "Not Default")

    class Configuration(ecological.AutoConfig, prefix="prefix"):
        integer: int
        boolean: bool
        default: str = "Default"
        not_default: typing.AnyStr

    assert Configuration.integer == 42
    assert Configuration.boolean is False
    assert Configuration.default == "Default"
    assert Configuration.not_default == "Not Default"


def test_invalid_value_regular_type(monkeypatch):
    monkeypatch.setenv("PARAM_REGULAR_TYPE", "not an integer")

    with pytest.raises(ValueError):
        class Configuration(ecological.AutoConfig):
            param_regular_type: int


def test_invalid_value_parsed_type(monkeypatch):
    monkeypatch.setenv("PARAM_PARSED_TYPE", "not a list")

    with pytest.raises(ValueError):
        class Configuration(ecological.AutoConfig):
            param_parsed_type: list = ['param_1', 'param_2']


def test_no_default():
    with pytest.raises(AttributeError):
        class Configuration(ecological.AutoConfig):
            no_default: int
            bool_var: bool = False


def test_simple_newtype(monkeypatch):
    monkeypatch.setenv("INTEGER", "2")

    Integer = typing.NewType("Integer", int)

    class Configuration(ecological.AutoConfig):
        integer: Integer

    assert Configuration.integer == 2


def test_nested_newtype(monkeypatch):
    monkeypatch.setenv("ID", "2")

    Integer = typing.NewType("Integer", int)
    Id = typing.NewType("Id", Integer)

    class Configuration(ecological.AutoConfig):
        id: Id

    assert Configuration.id == 2

@@ -3576,12 +3576,756 @@
 ion.id == 2%0A
+%0A%0Adef test_parametric_newtype(monkeypatch):%0A    monkeypatch.setenv(%22INTEGERS%22, %22%5B1, 2, 3%5D%22)%0A%0A    ListOfIntegers = typing.NewType(%22ListOfIntegers%22, typing.List%5Bint%5D)%0A%0A    class Configuration(ecological.AutoConfig):%0A        integers: ListOfIntegers%0A%0A    assert Configuration.integers == %5B1, 2, 3%5D%0A%0A%0Adef test_parametric_newtype_with_newtype_parameter(monkeypatch):%0A    monkeypatch.setenv(%22MEMBER_IDS%22, %22%5B1, 2, 3%5D%22)%0A%0A    Integer = typing.NewType(%22Integer%22, int)%0A    Id = typing.NewType(%22Id%22, Integer)%0A%0A    ListOfIds = typing.NewType(%22ListOfIds%22, typing.List%5BId%5D)%0A%0A    MemberIds = typing.NewType(%22MemberIds%22, ListOfIds)%0A%0A    class Configuration(ecological.AutoConfig):%0A        member_ids: MemberIds%0A%0A    assert Configuration.member_ids == %5B1, 2, 3%5D%0A

add more complex (but already passing) NewType tests