"""ASV benchmarks for phase reversion state machine.

Measures the performance of:
- Plan.can_revert_to() validation
- PlanLifecycleService.revert_plan() overhead
- PlanLifecycleService.try_auto_revert_from_apply() overhead
- Decision recording during reversion
- Reversion loop guard check overhead
"""

from __future__ import annotations

import sys
from pathlib import Path

try:
    from cleveragents.application.services.plan_lifecycle_service import (
        PlanLifecycleService,
    )
    from cleveragents.config.settings import Settings
    from cleveragents.domain.models.core.plan import (
        AutomationProfileProvenance,
        AutomationProfileRef,
        PlanPhase,
    )
except ModuleNotFoundError:
    sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
    from cleveragents.application.services.plan_lifecycle_service import (
        PlanLifecycleService,
    )
    from cleveragents.config.settings import Settings
    from cleveragents.domain.models.core.plan import (
        AutomationProfileProvenance,
        AutomationProfileRef,
        PlanPhase,
    )


def _make_service() -> PlanLifecycleService:
    return PlanLifecycleService(settings=Settings())


def _create_plan_in_execute(
    service: PlanLifecycleService,
    action_name: str = "local/bench-action",
    profile: str = "manual",
) -> str:
    service.create_action(
        name=action_name,
        description="Benchmark action",
        definition_of_done="Tests pass",
        strategy_actor="local/strategist",
        execution_actor="local/executor",
    )
    plan = service.use_action(action_name)
    plan.automation_profile = AutomationProfileRef(
        profile_name=profile,
        provenance=AutomationProfileProvenance.PLAN,
    )
    plan_id = plan.identity.plan_id
    service.start_strategize(plan_id)
    service.complete_strategize(plan_id)
    service.execute_plan(plan_id)
    return plan_id


class CanRevertToSuite:
    """Benchmark Plan.can_revert_to() validation."""

    def setup(self) -> None:
        service = _make_service()
        plan_id = _create_plan_in_execute(service, "local/bench-can-revert")
        self.plan = service.get_plan(plan_id)

    def time_can_revert_to_valid(self) -> None:
        self.plan.can_revert_to(PlanPhase.STRATEGIZE)

    def time_can_revert_to_invalid(self) -> None:
        self.plan.can_revert_to(PlanPhase.APPLY)


class RevertPlanSuite:
    """Benchmark PlanLifecycleService.revert_plan() overhead."""

    def setup(self) -> None:
        self.service = _make_service()
        self.counter = 0

    def time_revert_plan(self) -> None:
        self.counter += 1
        name = f"local/bench-revert-{self.counter}"
        plan_id = _create_plan_in_execute(self.service, name)
        self.service.revert_plan(plan_id, PlanPhase.STRATEGIZE, reason="benchmark")


class AutoRevertSuite:
    """Benchmark auto-reversion from constrained apply."""

    def setup(self) -> None:
        self.service = _make_service()
        self.counter = 0

    def time_auto_revert_from_apply(self) -> None:
        self.counter += 1
        name = f"local/bench-auto-{self.counter}"
        self.service.create_action(
            name=name,
            description="Benchmark action",
            definition_of_done="Tests pass",
            strategy_actor="local/strategist",
            execution_actor="local/executor",
        )
        plan = self.service.use_action(name)
        plan.automation_profile = AutomationProfileRef(
            profile_name="ci",
            provenance=AutomationProfileProvenance.PLAN,
        )
        plan_id = plan.identity.plan_id
        self.service.start_strategize(plan_id)
        # complete_strategize auto-progresses to EXECUTE with "ci" profile
        self.service.complete_strategize(plan_id)
        plan = self.service.get_plan(plan_id)
        if plan.phase != PlanPhase.EXECUTE:
            self.service.execute_plan(plan_id)
        self.service.start_execute(plan_id)
        # complete_execute auto-progresses to APPLY with "ci" profile
        self.service.complete_execute(plan_id)
        self.service.start_apply(plan_id)
        self.service.constrain_apply(plan_id, "benchmark constraint")
        self.service.try_auto_revert_from_apply(plan_id, "benchmark")


class LoopGuardSuite:
    """Benchmark loop guard check overhead."""

    def setup(self) -> None:
        self.service = _make_service()
        plan_id = _create_plan_in_execute(self.service, "local/bench-guard")
        self.plan = self.service.get_plan(plan_id)

    def time_loop_guard_under_limit(self) -> None:
        self.plan.reversion_count = 2
        self.plan.can_revert_to(PlanPhase.STRATEGIZE)

    def time_loop_guard_at_limit(self) -> None:
        self.plan.reversion_count = 3
        self.plan.can_revert_to(PlanPhase.STRATEGIZE)
