"""Execution DTOs — contracts for pathway execution.

PathwayRecord is here because it references Context.
For the pure data models (PathwayEvent, PathwayStatus, PathwayMetrics),
see core.pathways.models.execution.
"""

from __future__ import annotations

from typing import Any

from pydantic import BaseModel, Field, model_validator

from core.common import JsonObject

# Re-export from canonical location for backward compatibility
from core.pathways.models.execution import PathwayEvent, PathwayMetrics, PathwayStatus


def _deep_serialise(value: object) -> object:
    """Recursively convert Pydantic models to dicts so the value is JSON-safe.

    Used at the PathwayRecord boundary — the single canonical place where
    typed Python objects become serialisable data for storage / audit.
    """
    if isinstance(value, BaseModel):
        return value.model_dump()
    if isinstance(value, dict):
        return {k: _deep_serialise(v) for k, v in value.items()}
    if isinstance(value, list):
        return [_deep_serialise(v) for v in value]
    return value


class PathwayRecord(BaseModel):
    """Record of a pathway execution.

    This is the **serialisation boundary** between the typed VM pipeline
    and external consumers (storage, HTTP responses, logging).

    The ``inputs`` / ``outputs`` / ``metadata`` fields are ``JsonObject``
    (JSON-serialisable dicts).  A ``model_validator`` automatically
    converts any Pydantic models found in these fields to plain dicts so
    callers never need to worry about pre-serialising.
    """

    model_config = {"extra": "allow", "arbitrary_types_allowed": True}

    id: str
    pathway_id: str
    status: PathwayStatus = PathwayStatus.PENDING
    inputs: JsonObject = Field(default_factory=dict)
    outputs: JsonObject = Field(default_factory=dict)
    provenance: JsonObject = Field(default_factory=dict)
    context: object | None = None  # Runtime type: Context (avoids circular import)
    events: list[PathwayEvent] = Field(default_factory=list)
    metrics: PathwayMetrics = Field(default_factory=PathwayMetrics)
    error: str | None = None
    metadata: JsonObject = Field(default_factory=dict)

    @model_validator(mode="before")
    @classmethod
    def _serialise_typed_fields(cls, values: Any) -> Any:
        """Auto-serialise Pydantic objects in dict fields at construction."""
        if isinstance(values, dict):
            for key in ("inputs", "outputs", "provenance", "metadata"):
                raw = values.get(key)
                if raw is not None:
                    values[key] = _deep_serialise(raw)
        return values

    @property
    def success(self) -> bool:
        """Check if execution completed successfully."""
        return self.status == PathwayStatus.COMPLETED


__all__ = [
    "PathwayEvent",
    "PathwayMetrics",
    "PathwayRecord",
    "PathwayStatus",
]
