"""Helper script for influence DAG traversal Robot Framework tests.

Exercises CorrectionService with both structural tree and influence
DAG edges, plus DecisionService influence dependency recording.
"""

from __future__ import annotations

import sys

from cleveragents.application.services.correction_service import CorrectionService
from cleveragents.application.services.decision_service import DecisionService
from cleveragents.domain.models.core.correction import CorrectionMode

# ---------------------------------------------------------------------------
# Shared fixtures
# ---------------------------------------------------------------------------
_PLAN_ID = "01ARZ3NDEKTSV4RRFFQ69G5FAV"


def _structural_only() -> None:
    """Revert with only structural children."""
    svc = CorrectionService()
    req = svc.request_correction(_PLAN_ID, "D1", CorrectionMode.REVERT)
    tree = {"D1": ["D2", "D3"], "D2": ["D4"]}
    result = svc.execute_revert(req.correction_id, tree)
    assert result.status == "applied"
    assert set(result.reverted_decisions) == {"D1", "D2", "D3", "D4"}
    print("structural-only-ok")


def _influence_only() -> None:
    """Revert with only influence DAG edges."""
    svc = CorrectionService()
    req = svc.request_correction(_PLAN_ID, "D1", CorrectionMode.REVERT)
    tree: dict[str, list[str]] = {}
    influence = {"D1": ["D5", "D6"], "D5": ["D7"]}
    result = svc.execute_revert(req.correction_id, tree, influence)
    assert result.status == "applied"
    assert set(result.reverted_decisions) == {"D1", "D5", "D6", "D7"}
    print("influence-only-ok")


def _combined_revert() -> None:
    """Revert traverses union of structural + influence edges."""
    svc = CorrectionService()
    req = svc.request_correction(_PLAN_ID, "D1", CorrectionMode.REVERT)
    tree = {"D1": ["D2"]}
    influence = {"D1": ["D3"], "D2": ["D4"]}
    result = svc.execute_revert(req.correction_id, tree, influence)
    assert result.status == "applied"
    assert set(result.reverted_decisions) == {"D1", "D2", "D3", "D4"}
    print("combined-revert-ok")


def _cycle_detection() -> None:
    """Corrupt cycle in influence DAG handled gracefully."""
    svc = CorrectionService()
    req = svc.request_correction(_PLAN_ID, "D1", CorrectionMode.REVERT)
    tree: dict[str, list[str]] = {}
    influence = {"D1": ["D2"], "D2": ["D3"], "D3": ["D1"]}
    result = svc.execute_revert(req.correction_id, tree, influence)
    assert result.status == "applied"
    reverted = set(result.reverted_decisions)
    assert reverted == {"D1", "D2", "D3"}, f"Got {reverted}"
    # No duplicates
    assert len(result.reverted_decisions) == len(set(result.reverted_decisions))
    print("cycle-detection-ok")


def _record_deps() -> None:
    """record_decision with dependency_decision_ids populates DAG."""
    svc = DecisionService()
    root = svc.record_decision(
        plan_id=_PLAN_ID,
        decision_type="strategy_choice",
        question="Strategy?",
        chosen_option="Approach A",
    )
    child = svc.record_decision(
        plan_id=_PLAN_ID,
        decision_type="implementation_choice",
        question="Impl?",
        chosen_option="Option B",
        parent_decision_id=root.decision_id,
        dependency_decision_ids=[root.decision_id],
    )
    edges = svc.get_influence_edges(_PLAN_ID)
    assert root.decision_id in edges
    assert child.decision_id in edges[root.decision_id]
    print("record-deps-ok")


def _e2e_cascade() -> None:
    """Full flow: record decisions with deps, then revert cascades."""
    # 1. Record decisions with influence dependencies
    dsvc = DecisionService()
    d1 = dsvc.record_decision(
        plan_id=_PLAN_ID,
        decision_type="strategy_choice",
        question="Strategy?",
        chosen_option="Approach A",
    )
    d2 = dsvc.record_decision(
        plan_id=_PLAN_ID,
        decision_type="resource_selection",
        question="Resource?",
        chosen_option="File X",
        parent_decision_id=d1.decision_id,
    )
    d3 = dsvc.record_decision(
        plan_id=_PLAN_ID,
        decision_type="implementation_choice",
        question="Impl?",
        chosen_option="Option B",
        parent_decision_id=d2.decision_id,
        dependency_decision_ids=[d1.decision_id, d2.decision_id],
    )

    # 2. Build structural tree
    tree = {
        d1.decision_id: [d2.decision_id],
        d2.decision_id: [d3.decision_id],
    }

    # 3. Get influence edges
    influence = dsvc.get_influence_edges(_PLAN_ID)

    # 4. Revert from d1 → should cascade to d2 and d3
    csvc = CorrectionService()
    req = csvc.request_correction(_PLAN_ID, d1.decision_id, CorrectionMode.REVERT)
    result = csvc.execute_revert(req.correction_id, tree, influence)
    assert result.status == "applied"
    reverted = set(result.reverted_decisions)
    assert d1.decision_id in reverted
    assert d2.decision_id in reverted
    assert d3.decision_id in reverted
    print("e2e-cascade-ok")


# ---------------------------------------------------------------------------
# Dispatch
# ---------------------------------------------------------------------------

_COMMANDS = {
    "structural-only": _structural_only,
    "influence-only": _influence_only,
    "combined-revert": _combined_revert,
    "cycle-detection": _cycle_detection,
    "record-deps": _record_deps,
    "e2e-cascade": _e2e_cascade,
}

if __name__ == "__main__":
    if len(sys.argv) < 2 or sys.argv[1] not in _COMMANDS:
        print(f"Usage: {sys.argv[0]} <{'|'.join(_COMMANDS)}>", file=sys.stderr)
        sys.exit(1)
    _COMMANDS[sys.argv[1]]()
