import sys
from dataclasses import dataclass

from cli.core import (
    DEFAULT_CORE_SERVICES,
    CliApplicationBuilder,
    CompletionDispatcher,
    ProjectRuntimeLocator,
)


@dataclass(frozen=True)
class CliImportArgvScope:
    """
    CLI 导入期参数作用域。

    该对象负责在根应用构建阶段暂时切换 `sys.argv`，只保留导入期
    需要的最小参数集，避免该过程继续以内联 `try/finally` 形式散落
    在入口运行器中。

    :param project_runtime_locator: CLI 项目运行时定位器
    """

    project_runtime_locator: ProjectRuntimeLocator

    def run(self, callback: object) -> object:
        """
        在导入期参数作用域内执行回调。

        :param callback: 待执行回调
        :return: 回调执行结果
        """
        original_argv = list(sys.argv)
        try:
            sys.argv = self.project_runtime_locator.extract_import_argv(original_argv)
            return callback()
        finally:
            sys.argv = original_argv


@dataclass(frozen=True)
class CliMainRunner:
    """
    CLI 根入口运行器。

    该运行器负责串联项目目录定位、导入期参数裁剪、根应用构建、
    completion 分发与 Typer 应用启动，避免 `main.py` 继续停留在
    模块级散乱编排状态。

    :param project_runtime_locator: CLI 项目运行时定位器
    :param completion_dispatcher: shell completion 分发器
    :param application_builder: 根应用构建器
    """

    project_runtime_locator: ProjectRuntimeLocator
    completion_dispatcher: CompletionDispatcher
    application_builder: CliApplicationBuilder
    import_argv_scope: CliImportArgvScope

    def build_cli(self) -> object:
        """
        构建 CLI 根应用，并在导入期仅保留最小化参数集。

        :return: Typer 根应用
        """
        self.project_runtime_locator.ensure_backend_dir_on_sys_path()
        return self.import_argv_scope.run(self.application_builder.build)

    def run(self) -> None:
        """
        执行 Typer CLI 根应用。

        :return: None
        """
        cli = self.build_cli()
        self.completion_dispatcher.dispatch(cli)
        cli(prog_name='shierfeng')


CLI_APPLICATION_BUILDER = CliApplicationBuilder(output_renderer=DEFAULT_CORE_SERVICES.output_renderer)
PROJECT_RUNTIME_LOCATOR = ProjectRuntimeLocator()
CLI_MAIN_RUNNER = CliMainRunner(
    project_runtime_locator=PROJECT_RUNTIME_LOCATOR,
    completion_dispatcher=CompletionDispatcher(),
    application_builder=CLI_APPLICATION_BUILDER,
    import_argv_scope=CliImportArgvScope(project_runtime_locator=PROJECT_RUNTIME_LOCATOR),
)


def main() -> None:
    """
    执行 CLI 根入口运行器。

    :return: None
    """
    CLI_MAIN_RUNNER.run()


if __name__ == '__main__':
    main()
