"""Controller interfaces and deterministic MVP controller."""

from __future__ import annotations

from typing import Protocol

from .bytecode import CognitiveOp, Instruction
from .workspace import Workspace


class Controller(Protocol):
    def next_instruction(self, workspace: Workspace) -> Instruction:
        ...


class HeuristicController:
    """Deterministic controller used before learned control exists.

    The policy is simple by design. It creates stable traces for tests and
    future training data.
    """

    def next_instruction(self, workspace: Workspace) -> Instruction:
        stage = str(workspace.metadata.get("stage", "created"))

        if stage == "created":
            return Instruction(CognitiveOp.PARSE_INPUT, rationale="Turn task text into workspace state")
        if stage == "parsed":
            return Instruction(CognitiveOp.CLASSIFY_TASK, rationale="Classify the task before planning")
        if stage == "classified":
            return Instruction(CognitiveOp.CREATE_GOAL, rationale="Create the primary goal")
        if stage == "goal_created":
            return Instruction(CognitiveOp.RETRIEVE_MEMORY, args={"query": workspace.task}, rationale="Look for related episodes")
        if stage == "memory_retrieved":
            return Instruction(CognitiveOp.RETRIEVE_SKILL, args={"query": workspace.task}, rationale="Look for reusable skills")
        if stage == "skill_retrieved":
            if _has_verified_reuse_signal(workspace):
                return Instruction(CognitiveOp.VERIFY, rationale="Verify the promoted skill reuse path")
            return Instruction(CognitiveOp.CREATE_HYPOTHESIS, rationale="Form a first operational hypothesis")
        if stage == "hypothesis_created":
            return Instruction(CognitiveOp.VERIFY, rationale="Verify whether enough evidence exists for an answer")
        if stage == "verified":
            return Instruction(CognitiveOp.ANSWER, rationale="Return final answer")

        if workspace.has_answer():
            return Instruction(CognitiveOp.STORE_EPISODE, rationale="Persist the completed episode")

        return Instruction(CognitiveOp.ANSWER, rationale="Fallback answer when budget is almost exhausted")


def _has_verified_reuse_signal(workspace: Workspace) -> bool:
    return (
        int(workspace.metadata.get("memory_hit_count", 0)) > 0
        and int(workspace.metadata.get("promoted_skill_match_count", 0)) > 0
    )
