"""Planner for generating solution plans."""

from typing import Callable, List, Optional

from .types import Plan, PlanStep, StepStatus


class Planner:
    """Generates plans for solving problems.

    The Planner creates a step-by-step plan before solving,
    which is the key innovation of the Plan-and-Solve approach.
    """

    def __init__(
        self,
        plan_fn: Optional[Callable[[str], List[str]]] = None,
        max_steps: int = 10,
        verbose: bool = False,
    ):
        """Initialize the planner.

        Args:
            plan_fn: Optional custom planning function.
                    Takes problem description, returns list of step descriptions.
            max_steps: Maximum number of steps in a plan
            verbose: Whether to print debug info
        """
        self._plan_fn = plan_fn
        self._max_steps = max_steps
        self._verbose = verbose

    def create_plan(self, problem: str) -> Plan:
        """Create a plan for the given problem.

        Args:
            problem: Problem description

        Returns:
            A Plan object with steps
        """
        if self._verbose:
            print(f"\n[Planner] Creating plan for: {problem[:50]}...")

        if self._plan_fn:
            step_descriptions = self._plan_fn(problem)
        else:
            step_descriptions = self._default_plan(problem)

        # Limit steps
        step_descriptions = step_descriptions[:self._max_steps]

        plan = Plan(problem=problem)

        for i, desc in enumerate(step_descriptions):
            # Simple dependency: each step depends on previous
            deps = [i] if i > 0 else []
            plan.add_step(description=desc, dependencies=deps)

        if self._verbose:
            print(f"[Planner] Created plan with {len(plan.steps)} steps")

        return plan

    def _default_plan(self, problem: str) -> List[str]:
        """Generate a default plan using heuristics.

        Args:
            problem: Problem description

        Returns:
            List of step descriptions
        """
        # Generic planning template
        return [
            "Understand the problem and identify key requirements",
            "Break down the problem into manageable parts",
            "Identify what information is needed",
            "Develop a solution approach",
            "Execute the solution step by step",
            "Verify the solution meets all requirements",
        ]

    def refine_plan(self, plan: Plan, failed_step: PlanStep, reason: str) -> Plan:
        """Refine a plan after a step fails.

        Args:
            plan: Original plan
            failed_step: The step that failed
            reason: Why it failed

        Returns:
            Refined plan
        """
        if self._verbose:
            print(f"[Planner] Refining plan due to step {failed_step.step_number} failure")

        # Mark failed step
        for step in plan.steps:
            if step.step_number >= failed_step.step_number:
                step.status = StepStatus.PENDING

        # Insert refinement step
        new_step = PlanStep(
            description=f"Address issue: {reason[:50]}",
            step_number=failed_step.step_number,
        )

        # Shift subsequent steps
        plan.steps.insert(failed_step.step_number - 1, new_step)
        for i, step in enumerate(plan.steps):
            step.step_number = i + 1

        return plan