"""ASV benchmarks for plan resume overhead baseline.

Measures the cost of:
- Resume eligibility validation
- Step checkpoint recording
- Resume summary building (dry-run)
- Live resume state transitions
"""

from __future__ import annotations

from ulid import ULID

from cleveragents.application.services.plan_lifecycle_service import (
    PlanLifecycleService,
)
from cleveragents.application.services.plan_resume_service import (
    PlanResumeService,
)
from cleveragents.config.settings import Settings
from cleveragents.domain.models.core.plan import (
    ProjectLink,
)
from cleveragents.domain.models.core.resume import ResumeMetadata

_CB32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
_bench_counter = 9000


def _bench_ulid() -> str:
    global _bench_counter
    _bench_counter += 1
    n = _bench_counter
    suffix = ""
    for _ in range(8):
        suffix = _CB32[n % 32] + suffix
        n //= 32
    return f"01HGZ6FE0AQDYTR4BX{suffix}"


def _make_services() -> tuple[PlanLifecycleService, PlanResumeService]:
    settings = Settings()
    lifecycle = PlanLifecycleService(settings=settings)
    resume = PlanResumeService(lifecycle_service=lifecycle)
    return lifecycle, resume


def _create_action(lifecycle: PlanLifecycleService, suffix: str) -> str:
    name = f"local/bench-resume-{suffix}"
    lifecycle.create_action(
        name=name,
        description="Benchmark resume action",
        definition_of_done="Step 1\nStep 2\nStep 3",
        strategy_actor="local/stub-strategy",
        execution_actor="local/stub-execute",
    )
    return name


def _make_errored_plan(lifecycle: PlanLifecycleService, action_name: str) -> str:
    plan = lifecycle.use_action(
        action_name=action_name,
        project_links=[ProjectLink(project_name="local/bench-proj")],
    )
    pid = plan.identity.plan_id
    lifecycle.start_strategize(pid)
    p = lifecycle.get_plan(pid)
    p.decision_root_id = str(ULID())
    lifecycle._commit_plan(p)
    lifecycle.complete_strategize(pid)
    lifecycle.execute_plan(pid)
    lifecycle.start_execute(pid)
    lifecycle.fail_execute(pid, "bench error")
    return pid


class TimeResumeEligibility:
    """Benchmark resume eligibility validation."""

    timeout = 30.0

    def setup(self) -> None:
        self.lifecycle, self.resume = _make_services()
        action = _create_action(self.lifecycle, _bench_ulid())
        self.plan_id = _make_errored_plan(self.lifecycle, action)

    def time_validate_eligibility(self) -> None:
        self.resume.validate_eligibility(self.plan_id)


class TimeCheckpointRecording:
    """Benchmark step checkpoint recording."""

    timeout = 30.0

    def setup(self) -> None:
        self.lifecycle, self.resume = _make_services()
        action = _create_action(self.lifecycle, _bench_ulid())
        plan = self.lifecycle.use_action(
            action_name=action,
            project_links=[ProjectLink(project_name="local/bench-proj")],
        )
        pid = plan.identity.plan_id
        self.lifecycle.start_strategize(pid)
        p = self.lifecycle.get_plan(pid)
        p.decision_root_id = str(ULID())
        self.lifecycle._commit_plan(p)
        self.lifecycle.complete_strategize(pid)
        self.lifecycle.execute_plan(pid)
        self.lifecycle.start_execute(pid)
        self.plan_id = pid
        self.resume.set_total_steps(pid, 100)
        self.step_counter = 0

    def time_record_checkpoint(self) -> None:
        idx = self.step_counter
        self.step_counter += 1
        if idx >= 100:
            return
        self.resume.record_step_checkpoint(
            self.plan_id, idx, f"DEC-{idx}", f"Step {idx}"
        )


class TimeDryRunResume:
    """Benchmark dry-run resume summary building."""

    timeout = 30.0

    def setup(self) -> None:
        self.lifecycle, self.resume = _make_services()
        action = _create_action(self.lifecycle, _bench_ulid())
        self.plan_id = _make_errored_plan(self.lifecycle, action)
        self.resume.set_total_steps(self.plan_id, 10)
        self.resume.record_step_checkpoint(self.plan_id, 5, "DEC-5", "Step 5")

    def time_dry_run_resume(self) -> None:
        self.resume.resume_plan(self.plan_id, dry_run=True)


class TimeResumeMetadataProperties:
    """Benchmark ResumeMetadata property access."""

    timeout = 30.0

    def setup(self) -> None:
        self.metadata = ResumeMetadata(
            last_completed_step=42,
            total_steps=100,
        )

    def time_has_progress(self) -> None:
        _ = self.metadata.has_progress

    def time_next_step_index(self) -> None:
        _ = self.metadata.next_step_index

    def time_is_complete(self) -> None:
        _ = self.metadata.is_complete
