"""Robot Framework helper for invariant reconciliation actor integration tests.

Exercises the full reconciliation pipeline: collect → reconcile → enforce,
then verifies the reconciled set is respected by subsequent operations.
"""

from __future__ import annotations

import json
import sys
from pathlib import Path

# Ensure source tree is importable
_SRC = str(Path(__file__).resolve().parents[1] / "src")
if _SRC not in sys.path:
    sys.path.insert(0, _SRC)

from cleveragents.actor.reconciliation import (  # noqa: E402
    InvariantReconciliationActor,
)
from cleveragents.application.services.decision_service import (  # noqa: E402
    DecisionService,
)
from cleveragents.application.services.invariant_service import (  # noqa: E402
    InvariantService,
)
from cleveragents.domain.models.core.decision import DecisionType  # noqa: E402
from cleveragents.domain.models.core.invariant import InvariantScope  # noqa: E402


def _run_reconciliation_pipeline() -> dict[str, object]:
    """Run the full reconciliation pipeline and return results as dict."""
    inv_svc = InvariantService()
    dec_svc = DecisionService()

    # Add invariants across scopes
    inv_svc.add_invariant(
        "Never delete production data",
        InvariantScope.GLOBAL,
        "system",
    )
    inv_svc.add_invariant(
        "Use ORM for all queries",
        InvariantScope.PROJECT,
        "local/api-service",
    )
    inv_svc.add_invariant(
        "Separate commits per file",
        InvariantScope.ACTION,
        "local/code-coverage",
    )
    inv_svc.add_invariant(
        "Mock all network calls",
        InvariantScope.PLAN,
        "01JQAAAAAAAAAAAAAAAAAAAA01",
    )

    actor = InvariantReconciliationActor(
        invariant_service=inv_svc,
        decision_service=dec_svc,
    )

    result = actor.run(
        plan_id="01JQAAAAAAAAAAAAAAAAAAAA01",
        project_name="local/api-service",
        action_name="local/code-coverage",
    )

    return {
        "invariant_count": len(result.reconciled_set.invariants),
        "conflict_count": len(result.conflicts),
        "decision_count": len(result.enforced_decision_ids),
        "invariant_texts": [inv.text for inv in result.reconciled_set.invariants],
    }


def _run_conflict_resolution() -> dict[str, object]:
    """Run reconciliation with conflicts and verify resolution."""
    inv_svc = InvariantService()
    dec_svc = DecisionService()

    inv_svc.add_invariant(
        "All tests must pass",
        InvariantScope.GLOBAL,
        "system",
    )
    inv_svc.add_invariant(
        "All tests must pass",
        InvariantScope.PLAN,
        "01JQAAAAAAAAAAAAAAAAAAAA01",
    )

    actor = InvariantReconciliationActor(
        invariant_service=inv_svc,
        decision_service=dec_svc,
    )

    result = actor.run(plan_id="01JQAAAAAAAAAAAAAAAAAAAA01")

    winner_scope = ""
    for inv in result.reconciled_set.invariants:
        if inv.text.lower() == "all tests must pass":
            winner_scope = inv.scope.value
            break

    return {
        "invariant_count": len(result.reconciled_set.invariants),
        "conflict_count": len(result.conflicts),
        "winner_scope": winner_scope,
    }


def _run_non_overridable_test() -> dict[str, object]:
    """Verify non_overridable global invariants block overrides."""
    inv_svc = InvariantService()
    dec_svc = DecisionService()

    inv = inv_svc.add_invariant(
        "Payment processing must be idempotent",
        InvariantScope.GLOBAL,
        "system",
    )
    inv.non_overridable = True

    inv_svc.add_invariant(
        "Payment processing must be idempotent",
        InvariantScope.PLAN,
        "01JQAAAAAAAAAAAAAAAAAAAA01",
    )

    actor = InvariantReconciliationActor(
        invariant_service=inv_svc,
        decision_service=dec_svc,
    )

    result = actor.run(plan_id="01JQAAAAAAAAAAAAAAAAAAAA01")

    winner_scope = ""
    for r_inv in result.reconciled_set.invariants:
        if "idempotent" in r_inv.text.lower():
            winner_scope = r_inv.scope.value
            break

    return {
        "invariant_count": len(result.reconciled_set.invariants),
        "conflict_count": len(result.conflicts),
        "winner_scope": winner_scope,
        "has_non_overridable_reason": any(
            "non_overridable" in c.reason for c in result.conflicts
        ),
    }


def _run_decision_verification() -> dict[str, object]:
    """Verify invariant_enforced decisions are properly recorded."""
    inv_svc = InvariantService()
    dec_svc = DecisionService()

    inv_svc.add_invariant(
        "Never delete production data",
        InvariantScope.GLOBAL,
        "system",
    )
    inv_svc.add_invariant(
        "Mock all network calls",
        InvariantScope.PLAN,
        "01JQAAAAAAAAAAAAAAAAAAAA01",
    )

    actor = InvariantReconciliationActor(
        invariant_service=inv_svc,
        decision_service=dec_svc,
    )

    result = actor.run(plan_id="01JQAAAAAAAAAAAAAAAAAAAA01")

    # Verify decisions
    all_correct_type = True
    all_correct_plan = True
    for did in result.enforced_decision_ids:
        decision = dec_svc.get_decision(did)
        if decision.decision_type != DecisionType.INVARIANT_ENFORCED:
            all_correct_type = False
        if decision.plan_id != "01JQAAAAAAAAAAAAAAAAAAAA01":
            all_correct_plan = False

    return {
        "decision_count": len(result.enforced_decision_ids),
        "all_correct_type": all_correct_type,
        "all_correct_plan": all_correct_plan,
    }


def main() -> None:
    """Entry point for Robot Framework helper."""
    if len(sys.argv) < 2:
        print("Usage: helper_invariant_reconciliation.py <command>")
        sys.exit(1)

    command = sys.argv[1]
    handlers = {
        "reconcile": _run_reconciliation_pipeline,
        "conflict": _run_conflict_resolution,
        "non-overridable": _run_non_overridable_test,
        "decisions": _run_decision_verification,
    }

    handler = handlers.get(command)
    if handler is None:
        print(f"Unknown command: {command}")
        sys.exit(1)

    result = handler()
    print(json.dumps(result))
    print("reconciliation-ok")


if __name__ == "__main__":
    main()
