"""Orchestrator: 循环编排 + 退出条件判断。"""

from __future__ import annotations

from pathlib import Path

from promptgrad.config import load_config
from promptgrad.evaluator import Evaluator
from promptgrad.executor import Executor
from promptgrad.history import HistoryManager
from promptgrad.loader import Loader


class Orchestrator:
    """
    编排 Executor -> Evaluator -> Optimizer 循环。

    注: 完整循环由 SKILL.md 驱动（宿主模型做 judge/optimize），
    此类提供 Python 侧的组件初始化和退出条件判断。
    """

    def __init__(self, config_path: str):
        self.config = load_config(config_path)
        self.target_score = self.config.target_score
        self.max_iterations = self.config.max_iterations
        self.patience = self.config.patience

        self.loader = Loader()
        self.history = HistoryManager(str(Path(self.config.base_dir) / "history.yaml"))

    def load_test_cases(self):
        """加载测试用例。"""
        return self.loader.load_yaml_dir(self.config.test_cases_dir)

    def create_executor(self, prompt_config: dict | None = None) -> Executor:
        """创建 Executor 实例。"""
        pc = prompt_config or self.config.prompt_config
        return Executor(
            prompt_config=pc,
            model_config=self.config.model_config,
            concurrency=self.config.concurrency,
        )

    def create_evaluator(self) -> Evaluator:
        """创建 Evaluator 实例。"""
        return Evaluator(
            rubric=self.config.raw["eval_rubric"],
            concurrency=self.config.concurrency,
        )

    def _should_stop(self, scores: list[float], iteration: int) -> tuple[bool, str]:
        """
        判断是否退出。

        Returns:
            (should_stop, reason)
        """
        if not scores:
            return False, ""

        latest = scores[-1]

        # 条件 1: 达标
        if latest >= self.target_score:
            return True, f"达标: {latest:.4f} >= {self.target_score}"

        # 条件 2: 到上限
        if iteration >= self.max_iterations:
            return True, f"到上限: 已迭代 {iteration} 轮 (max={self.max_iterations})"

        # 条件 3: 连续 patience 轮无提升
        if len(scores) > self.patience:
            recent = scores[-self.patience - 1 :]
            improvements = [recent[i + 1] - recent[i] for i in range(len(recent) - 1)]
            if all(imp < 0.01 for imp in improvements):
                return True, f"收敛停滞: 连续 {self.patience} 轮提升 < 0.01"

        return False, ""
