from abc import ABC, abstractmethod
from typing import List

from ghostos.container import Container
from ghostos.core.moss.abcd import Moss as Parent
from ghostos.prompter import ModelPrompter
from inspect import getmembers, getsource
from pydantic import BaseModel


class Foo(ABC):
    """定义一个本地类, 用来做依赖注入测试. """

    @abstractmethod
    def foo(self) -> str:
        pass


def plus(a: int, b: int) -> int:
    """ 验证本地方法存在于 prompt. """
    return a + b


class TestPrompter(ModelPrompter):
    line: str = "TestPrompter"

    def self_prompt(self, container: Container) -> str:
        return self.line

    def get_title(self) -> str:
        return ""


class Moss(Parent, ABC):
    """
    本地定义的 Moss 类. 每个 MOSS 文件里都应该有一个 Moss 类, 可以是 import 的也可以是本地定义的.
    记得它要继承自 Moss.
    """
    life: List[str] = []
    """测试 attr 方法用来定义可持久化的属性. """

    foo: Foo
    """依赖注入 Foo 的测试用例. """

    tester: TestPrompter


# <moss-hide>
# !!! 使用 `# <moss-hide>` 和 `# </moss-hide>` 包裹的代码不会对大模型呈现.

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from ghostos.core.moss.abcd import MossCompiler, AttrPrompts, MossPrompter, Execution


def __moss_compile__(compiler: "MossCompiler") -> "MossCompiler":
    """
    从 compile 中获取 MOSSRuntime, 并对它进行初始化.
    可选的魔术方法. 如果定义的话, MOSS 执行 compile 的阶段会默认执行它.

    主要解决各种注入方面的需求:
    """
    # 单测里应该有这个. moss.bar == 123
    compiler.injects(bar=123, tester=TestPrompter())
    # 插入生命周期事件, 直接赋值到 moss 上.
    Moss.life.append("__moss_compile__")

    # 准备依赖注入 Foo.
    class FooImpl(Foo):
        def foo(self) -> str:
            return "hello"

    from ghostos.container import provide
    # 用这种方式, 可以预期 Moss 被依赖注入了 Foo, 注入的是 FooImpl
    provider = provide(Foo, singleton=False)(lambda con: FooImpl())
    compiler.register(provider)

    return compiler


def __moss_attr_prompts__() -> "AttrPrompts":
    return [
        # 重写了 getsource 的 prompt, 它就应该不存在了.
        ("getsource", ""),
        # 添加一个意义不明的注释. 也应该在 prompt 里.
        ("9527", "# hello world")
    ]


def __moss_prompt__(prompter: "MossPrompter") -> str:
    # 测试生命周期生效.
    from ghostos.core.moss.lifecycle import __moss_module_prompt__
    return __moss_module_prompt__(prompter)


def __moss_exec__(*args, **kwargs) -> "Execution":
    # 测试生命周期生效.
    from ghostos.core.moss.lifecycle import __moss_exec__
    return __moss_exec__(*args, **kwargs)


def test_main(moss: Moss) -> int:
    """
    模拟一个 main 方法, 测试 moss 的调用.
    assert 返回值是 3. 外部的 MOSSRuntime 调用这个方法.
    """
    print("hello world")
    return plus(1, 2)


if __name__ == "__test__":
    def main(moss: Moss) -> int:
        """
        模拟一个 main 方法, 测试 moss 的调用.
        assert 返回值是 4. 外部的 MOSSRuntime 调用这个方法.
        """
        return plus(2, 2)

# </moss-hide>
