from __future__ import annotations

from typing import Any

from app.services.scenes.scene_descriptor import SceneDescriptor
from app.services.scenes.scene_registry import REGISTRY, register_scene  # noqa: F401


def bootstrap_scenes() -> None:
    """注册全部业务场景,并运行时绑定 handler/builder/executor。

    descriptor 声明时 handler/builder/executor 为 None(避免循环 import),
    这里在运行时从各自的服务模块取回实际可调用对象并回填到 descriptor。

    新增场景时:
    1. 新建 scenes/scene_xxx.py,声明 SceneDescriptor(handler 留 None)
    2. 在这里加一行 register 调用
    3. 如有 handler,在 _bind_runtime_callbacks 里加绑定
    """
    # 声明式注册(不依赖任何服务模块)
    from app.services.scenes import (
        scene_expense_application,
        scene_query_travel_standard,
        scene_reimbursement,
    )

    if REGISTRY.all_scene_ids():
        return  # 已注册,避免重复

    scene_expense_application.register()
    scene_reimbursement.register()
    scene_query_travel_standard.register()

    _bind_runtime_callbacks()


def _bind_runtime_callbacks() -> None:
    """运行时把 handler/builder/executor 绑定到 descriptor。

    因为 SceneDescriptor 是 frozen dataclass,这里用替换的方式回填。
    """
    from app.services.steward_action_contracts import StewardActionPlanBuilder
    from app.services.steward_action_executor import StewardActionExecutor
    from app.services.steward_query_executors import (
        build_travel_standard_query_steps,
        execute_travel_standard_query,
    )

    application_builder = StewardActionPlanBuilder()

    # expense_application
    _update_scene(
        "expense_application",
        action_steps_builder=application_builder.build_application_steps,
        executor=StewardActionExecutor._dispatch_application_action,
    )

    # reimbursement
    _update_scene(
        "reimbursement",
        action_steps_builder=application_builder.build_reimbursement_steps,
        executor=StewardActionExecutor._dispatch_reimbursement_action,
    )

    # query_travel_standard
    _update_scene(
        "query_travel_standard",
        action_steps_builder=build_travel_standard_query_steps,
        handler=execute_travel_standard_query,
        executor=execute_travel_standard_query,
    )


def _update_scene(scene_id: str, **overrides: Any) -> None:
    """替换 REGISTRY 里的 descriptor 字段(frozen dataclass 需重建)。"""
    scene = REGISTRY.get(scene_id)
    if scene is None:
        return
    updated = SceneDescriptor(**{**scene.__dict__, **overrides})
    REGISTRY.register(updated)


# import 即注册
bootstrap_scenes()
