from typing import Annotated

import pytest

from zayt.di.container import Container
from zayt.di.error import ServiceAlreadyRegisteredError
from zayt.di.inject import Inject


class Service1:
    pass


class Service2:
    service1: Annotated[Service1, Inject]


class Service3:
    pass


class Interface:
    pass


class Implementation(Interface):
    pass


def test_has_service(ioc: Container):
    ioc.register(Service1)
    assert ioc.has(Service1)


async def test_service_with_provided_interface(ioc: Container):
    ioc.register(Implementation, provides=Interface)

    instance = await ioc.get(Interface)
    assert isinstance(instance, Implementation)


async def test_inject_singleton(ioc: Container):
    ioc.register(Service1)
    ioc.register(Service2)

    instance = await ioc.get(Service2)
    assert isinstance(instance, Service2)
    assert isinstance(instance.service1, Service1)

    other_instance = await ioc.get(Service2)
    assert other_instance is instance
    assert other_instance.service1 is instance.service1


async def test_interface_and_implementation(ioc: Container):
    ioc.register(Implementation, provides=Interface)

    instance = await ioc.get(Interface)
    assert isinstance(instance, Implementation)


async def test_register_a_service_twice_should_fail(ioc: Container):
    class Implementation2(Interface):
        pass

    ioc.register(Implementation, provides=Interface)
    with pytest.raises(ServiceAlreadyRegisteredError):
        ioc.register(Implementation2, provides=Interface)
