"""Best-of-N-Attempts — the attempt-counted variant of Best-of-N.

Identical to :mod:`galapagos.scaffolds.best_of_n` except for the SelectionPolicy's counting rule:
here every attempt (iteration) spends one unit of the N budget, valid or not, so the parent rotates
on a fixed cadence of N iterations. The other five components are shared with ``best_of_n`` (a flat
keep-all population, the default multi-section prompt, a SEARCH/REPLACE diff proposer, no memory).

  selection_policy.py  -> BestOfNAttemptsPolicy  (spend budget per attempt; see best_of_n for the
                                                  valid-counted original)
  population/prompt_builder/proposer/memory       reused from ``best_of_n``
  scaffold.py          -> BestOfNAttemptsScaffold (the orchestrator that composes the six)
"""
from __future__ import annotations

from ...config import GalapagosConfig
from ...models import GalapagosModel
from ..base_scaffold import GalapagosScaffold
from ..registry import register_scaffold
# the five non-policy components are identical to Best-of-N — reuse them rather than duplicate
from ..best_of_n.memory import BestOfNMemory
from ..best_of_n.population import BestOfNPopulation
from ..best_of_n.prompt_builder import BestOfNPromptBuilder
from ..best_of_n.proposer import BestOfNProposer
from .selection_policy import BestOfNAttemptsPolicy


@register_scaffold("best_of_n_attempts")
class BestOfNAttemptsScaffold(GalapagosScaffold):
    name = "best_of_n_attempts"

    @classmethod
    def build_components(cls, config: GalapagosConfig, model: GalapagosModel | None) -> dict:
        seed = int(config.seed)
        sel = config.selection_policy
        return {
            "population": BestOfNPopulation(capacity=config.population.capacity),
            "selection_policy": BestOfNAttemptsPolicy(
                seed=seed,
                n=int(sel.best_of_n),
                num_inspirations=int(sel.num_inspirations),
            ),
            "prompt_builder": BestOfNPromptBuilder(),
            "proposer": BestOfNProposer(),
            "memory": BestOfNMemory(),
        }
