"""
Refinement loop for iterative quality improvement.

Implements FR-10: Halting and Refinement Policy
Execute → Validate → Halt or Refine cycle.
"""

from typing import Callable, List, Optional, Tuple

from markitect.prompts.quality.models import (
    HaltDecision,
    QualityPolicy,
    RefinementResult,
    ValidationResult,
)
from markitect.prompts.quality.policy import HaltingPolicyEngine
from markitect.prompts.quality.validator import QualityValidator


class RefinementLoop:
    """
    Iterative refinement loop with quality gate checks.

    Executes a cycle of: execute → validate → check halting → refine
    until a halting condition is met.
    """

    def __init__(
        self,
        validator: QualityValidator,
        policy: QualityPolicy,
    ):
        """
        Initialize with validator and policy.

        Args:
            validator: Quality validator with configured gates
            policy: Halting policy configuration
        """
        self.validator = validator
        self.policy = policy
        self.policy_engine = HaltingPolicyEngine(policy)

    def run(
        self,
        execution_callback: Callable[[int, List[ValidationResult]], Tuple[str, str, str]],
        artifact_id: str,
    ) -> RefinementResult:
        """
        Execute the refinement loop.

        The execution_callback is called each iteration with:
        - iteration number (1-based)
        - previous validation results (empty list on first iteration)

        It should return a tuple of (run_id, content, artifact_id).

        Args:
            execution_callback: Callable that executes/refines and returns
                (run_id, content, artifact_id)
            artifact_id: ID of the artifact being refined

        Returns:
            RefinementResult with complete iteration history
        """
        result = RefinementResult(iterations_run=0)
        score_history: List[float] = []
        prev_results: List[ValidationResult] = []

        for iteration in range(1, self.policy.max_iterations + 1):
            # Execute / refine
            run_id, content, art_id = execution_callback(iteration, prev_results)
            result.run_ids.append(run_id)

            # Validate
            current_results = self.validator.validate_artifact(
                content, art_id, run_id=run_id if self.validator.db_path else None,
            )
            result.all_results.append(current_results)
            result.iterations_run = iteration

            # Evaluate halting
            halting_record = self.policy_engine.evaluate(
                results=current_results,
                iteration=iteration,
                score_history=score_history,
                total_runs=len(result.run_ids),
            )

            current_score = self.policy_engine._aggregate_score(current_results)
            score_history.append(current_score)

            if halting_record.decision != HaltDecision.CONTINUE:
                result.final_results = current_results
                result.halting_record = halting_record
                return result

            prev_results = current_results

        # Reached max iterations without explicit halt
        result.final_results = prev_results
        result.halting_record = self.policy_engine.evaluate(
            results=prev_results,
            iteration=self.policy.max_iterations,
            score_history=score_history,
            total_runs=len(result.run_ids),
        )
        return result
