"""Data models for behavioral verification and optimization results."""

from __future__ import annotations

import enum
from typing import TYPE_CHECKING

import attrs

if TYPE_CHECKING:
    from pathlib import Path

    from ..benchmarking.models import ConcurrencyMetrics
    from ..testing.models import TestResults


class BehaviorDiffScope(str, enum.Enum):
    """Scope of a behavioral difference between original and candidate."""

    RETURN_VALUE = "return_value"
    STDOUT = "stdout"
    DID_PASS = "did_pass"  # noqa: S105


@attrs.frozen
class BehaviorDiff:
    """A single behavioral difference between original and candidate."""

    scope: BehaviorDiffScope
    original_pass: bool
    candidate_pass: bool
    original_value: str | None = None
    candidate_value: str | None = None
    test_src_code: str | None = None
    candidate_pytest_error: str | None = None
    original_pytest_error: str | None = None


@attrs.frozen
class OriginalCodeBaseline:
    """Complete baseline metrics for the original, unoptimized code."""

    behavior_test_results: TestResults
    benchmarking_test_results: TestResults
    runtime: int
    line_profile_results: TestResults
    functions_to_remove: tuple[str, ...] = ()
    coverage_database_file: Path | None = None
    coverage_config_file: Path | None = None
    async_throughput: int | None = None
    concurrency_metrics: ConcurrencyMetrics | None = None


@attrs.frozen
class OptimizedCandidateResult:
    """Result of behavioral and performance tests on a candidate."""

    max_loop_count: int
    best_test_runtime: int
    behavior_test_results: TestResults
    benchmarking_test_results: TestResults
    optimization_candidate_index: int
    total_candidate_timing: int
    async_throughput: int | None = None
    concurrency_metrics: ConcurrencyMetrics | None = None
