"""Failure taxonomy helpers — create and validate failure records."""

from __future__ import annotations

import uuid
from datetime import UTC, datetime
from enum import Enum
from typing import Any

from abi_control_core.sdk.validate import validate_json


class FailureClass(Enum):
    """Classification of failure types in AI agent task execution."""

    SCOPE_EXPANSION = "scope_expansion"
    SCHEMA_DRIFT = "schema_drift"
    INVARIANT_VIOLATION = "invariant_violation"
    HALLUCINATED_PATH = "hallucinated_path"
    TESTS_PASS_BEHAVIOR_WRONG = "tests_pass_behavior_wrong"
    ACCESSIBILITY_VIOLATION = "accessibility_violation"
    PARTIAL_REFACTOR_BREAK = "partial_refactor_break"
    IMPORT_CHAIN_BREAK = "import_chain_break"
    CONFIG_NAMING_DRIFT = "config_naming_drift"
    EVENT_PAYLOAD_MISMATCH = "event_payload_mismatch"
    STUB_NOT_WIRED = "stub_not_wired"
    DEPENDENCY_VERSION_CONFLICT = "dependency_version_conflict"
    OTHER = "other"


class FailureSeverity(Enum):
    """Impact severity level of failures."""

    CRITICAL = "critical"
    HIGH = "high"
    MEDIUM = "medium"
    LOW = "low"


def create_failure_record(
    run_id: str,
    task_id: str,
    failure_class: FailureClass | str,
    severity: FailureSeverity | str,
    agent: str,
    task_category: str,
    repo: str,
    summary: str,
    evidence: dict[str, Any],
    mitigation: dict[str, str] | None = None,
) -> dict[str, Any]:
    """Create a failure record with all required fields.

    Args:
        run_id: The dogfood/orchestrator run ID that produced this failure.
        task_id: The specific task identifier that failed.
        failure_class: Classification of the failure type (enum or string value).
        severity: Impact severity level (enum or string value).
        agent: Which agent produced the failure (e.g., claude_code, codex, qwen, human).
        task_category: Category of task (e.g., code_generation, test_generation, documentation).
        repo: Which repository the failure occurred in.
        summary: One-line human-readable description of the failure (max 500 chars).
        evidence: Evidence dict with required 'file_paths' array and optional
            'line_ranges', 'error_output'.
        mitigation: Optional dict with 'suggested_eval', 'suggested_gate', 'suggested_hil'.

    Returns:
        A validated failure record dict conforming to failure_record.schema.json.

    Raises:
        SchemaValidationError: If the constructed record fails schema validation.

    Example:
        >>> record = create_failure_record(
        ...     run_id="abc12345",
        ...     task_id="task-001",
        ...     failure_class=FailureClass.HALLUCINATED_PATH,
        ...     severity=FailureSeverity.HIGH,
        ...     agent="claude_code",
        ...     task_category="code_generation",
        ...     repo="abi-core",
        ...     summary="Agent referenced non-existent module path",
        ...     evidence={
        ...         "file_paths": ["src/foo/bar.py"],
        ...         "error_output": "ModuleNotFoundError: No module named 'nonexistent'"
        ...     }
        ... )
    """
    # Convert enums to string values if needed
    if isinstance(failure_class, FailureClass):
        failure_class = failure_class.value
    if isinstance(severity, FailureSeverity):
        severity = severity.value

    record: dict[str, Any] = {
        "failure_id": str(uuid.uuid4()),
        "run_id": run_id,
        "task_id": task_id,
        "failure_class": failure_class,
        "severity": severity,
        "agent": agent,
        "task_category": task_category,
        "repo": repo,
        "failure_summary": summary,
        "evidence": evidence,
        "timestamp": datetime.now(UTC).isoformat(),
    }

    if mitigation is not None:
        record["mitigation"] = mitigation

    # Validate against schema before returning
    validate_json(record, "failure_record.schema.json")
    return record


def validate_failure_record(record: dict[str, Any]) -> bool:
    """Validate a failure record against the schema.

    Args:
        record: The failure record dict to validate.

    Returns:
        True if validation succeeds.

    Raises:
        SchemaValidationError: If validation fails, with detailed error messages.
    """
    validate_json(record, "failure_record.schema.json")
    return True
