from typing import (
    Any,
)

from hypothesis import (
    given,
    strategies as st,
)

from resultful import (
    success,
    failure,
    Result,
)

from testplates import (
    new_type,
    verify,
    TestplatesError,
)

from string import (
    printable,
)

from tests.strategies import (
    Draw,
)


@st.composite
def st_name(draw: Draw[str]) -> str:
    return draw(st.text(printable))


# noinspection PyTypeChecker
@given(name=st_name())
def test_cls_repr(name: str) -> None:
    custom_type = new_type(name, int)

    assert repr(custom_type) == f"<class '{name}'>"


# noinspection PyTypeChecker
@given(name=st_name())
def test_cls_validator(name: str) -> None:
    # noinspection PyUnusedLocal
    def validator(data: Any, /) -> Result[None, TestplatesError]:
        assert False

    custom_type = new_type(name, int, success(validator))

    assert verify(custom_type)


# noinspection PyTypeChecker
@given(name=st_name())
def test_cls_validator_failure(name: str) -> None:
    validator_error = TestplatesError()
    custom_type = new_type(name, int, failure(validator_error))

    assert not verify(custom_type)


# noinspection PyTypeChecker
@given(name=st_name(), value=st.integers())
def test_instance_repr(name: str, value: int) -> None:
    custom_type = new_type(name, int)
    custom_instance = custom_type(value)

    assert repr(custom_instance) == f"{name}({value})"


# noinspection PyTypeChecker
@given(name=st_name(), value=st.integers())
def test_instance_validator(name: str, value: int) -> None:
    def validator(data: Any, /) -> Result[None, TestplatesError]:
        assert data is value
        return success(None)

    custom_type = new_type(name, int, success(validator))
    custom_instance = custom_type(value)

    assert verify(custom_instance)


# noinspection PyTypeChecker
@given(name=st_name(), value=st.integers())
def test_instance_validator_failure(name: str, value: int) -> None:
    validator_error = TestplatesError()
    custom_type = new_type(name, int, failure(validator_error))
    custom_instance = custom_type(value)

    assert not verify(custom_instance)


# noinspection PyTypeChecker
@given(name=st_name(), value=st.integers())
def test_instance_validation_failure(name: str, value: int) -> None:
    validation_error = TestplatesError()

    def validator(data: Any, /) -> Result[None, TestplatesError]:
        assert data is value
        return failure(validation_error)

    custom_type = new_type(name, int, success(validator))
    custom_instance = custom_type(value)

    assert not verify(custom_instance)

from typing import (
    Any,
)

from hypothesis import (
    given,
    strategies as st,
)

from resultful import (
    success,
    failure,
    Result,
)

from testplates import (
    new_type,
    verify,
    TestplatesError,
)

from string import (
    printable,
)

from tests.strategies import (
    Draw,
)


@st.composite
def st_name(draw: Draw[str]) -> str:
    return draw(st.text(printable))


# noinspection PyTypeChecker
@given(name=st_name())
def test_cls_repr(name: str) -> None:
    custom_type = new_type(name, int)

    assert repr(custom_type) == f"<class '{name}'>"


# noinspection PyTypeChecker
@given(name=st_name())
def test_cls_validator(name: str) -> None:
    # noinspection PyUnusedLocal
    def validator(data: Any, /) -> Result[None, TestplatesError]:
        assert False

    custom_type = new_type(name, int, success(validator))

    assert verify(custom_type)


# noinspection PyTypeChecker
@given(name=st_name())
def test_cls_validator_failure(name: str) -> None:
    validator_error = TestplatesError()
    custom_type = new_type(name, int, failure(validator_error))

    assert not verify(custom_type)


# noinspection PyTypeChecker
@given(name=st_name(), value=st.integers())
def test_instance_repr(name: str, value: int) -> None:
    custom_type = new_type(name, int)
    custom_instance = custom_type(value)

    assert repr(custom_instance) == f"{name}({value})"


# noinspection PyTypeChecker
@given(name=st_name(), value=st.integers())
def test_instance_validator(name: str, value: int) -> None:
    def validator(data: Any, /) -> Result[None, TestplatesError]:
        assert data is value
        return success(None)

    custom_type = new_type(name, int, success(validator))
    custom_instance = custom_type(value)

    assert verify(custom_instance)


# noinspection PyTypeChecker
@given(name=st_name(), value=st.integers())
def test_instance_validator_failure(name: str, value: int) -> None:
    validator_error = TestplatesError()
    custom_type = new_type(name, int, failure(validator_error))
    custom_instance = custom_type(value)

    assert not verify(custom_instance)


# noinspection PyTypeChecker
@given(name=st_name(), value=st.integers())
def test_instance_validation_failure(name: str, value: int) -> None:
    validation_error = TestplatesError()

    def validator(data: Any, /) -> Result[None, TestplatesError]:
        assert data is value
        return failure(validation_error)

    custom_type = new_type(name, int, success(validator))
    custom_instance = custom_type(value)

    assert not verify(custom_instance)

# noinspection PyTypeChecker # noinspection PyTypeChecker # noinspection PyUnusedLocal # noinspection PyTypeChecker # noinspection PyTypeChecker # noinspection PyTypeChecker # noinspection PyTypeChecker # noinspection PyTypeChecker