from typing import Any, Generator

from ldnode.calculator.operators import stk_event_backtest
from ldnode.loader.files import STK_DATA

from ._factor_analysis_core import _compute_factor_analysis
from .models import TaskResponse
from .models.factor_analysis import STKFactorAnalysisParameters
from .utils import error_response, wrap_handler


@wrap_handler("股票因子分析", is_generator=True)
def handle_stk_factor_analysis(
    parameters: STKFactorAnalysisParameters,
) -> Generator[TaskResponse[Any], None, None]:
    """响应股票因子分析任务

    入参包含完整 STKBacktestStrategyConfig（需含 rank_factors）及滚动窗口期数。
    流式 yield 三帧：factor_ic_stats / factor_ic_series / factor_correlation_matrix。
    """
    strategy_config = parameters["strategy_config"]
    rank_factors = strategy_config.get("rank_factors") or []

    # 验收标准：rank_factors 为空时提前退出
    if not rank_factors:
        yield error_response("rank_factors 为空，无法进行因子分析")
        return

    factor_keys: list[str] = [f["factor"] for f in rank_factors]
    rolling_period: int = parameters["rolling_period"]

    # 调用事件驱动回测，返回三元组：(res_df, _, screen_df)
    res_df, _, screen_df = stk_event_backtest(
        lf=STK_DATA.output_lazyframe(),
        parameters=strategy_config,
        record_history=False,
        return_screen_df=True,
    )

    # 委托核心函数计算并 yield 三帧
    yield from _compute_factor_analysis(
        res_df=res_df,
        screen_df=screen_df,
        factor_keys=factor_keys,
        rolling_period=rolling_period,
        task_id=parameters["task_id"],
        log_prefix="股票因子分析",
    )
