"""Step model — one node/agent action within a run (build plan Section 5)."""

from __future__ import annotations

import uuid

from sqlalchemy import JSON, Float, ForeignKey, Index, Integer, String, Text, Uuid
from sqlalchemy import Enum as SAEnum
from sqlalchemy.orm import Mapped, mapped_column

from legate.agent.enums import StepType
from legate.db.base import Base, TimestampMixin, UUIDPrimaryKeyMixin


class Step(UUIDPrimaryKeyMixin, TimestampMixin, Base):
    __tablename__ = "steps"
    __table_args__ = (Index("ix_steps_run_idx", "run_id", "idx", unique=True),)

    run_id: Mapped[uuid.UUID] = mapped_column(
        Uuid, ForeignKey("runs.id", ondelete="CASCADE"), index=True, nullable=False
    )
    # Denormalized for tenant-scoped queries without a join.
    workspace_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True, nullable=False)
    # Monotonic position within the run.
    idx: Mapped[int] = mapped_column(Integer, nullable=False)
    type: Mapped[StepType] = mapped_column(
        SAEnum(
            StepType,
            native_enum=False,
            length=20,
            values_callable=lambda e: [m.value for m in e],
        ),
        nullable=False,
    )
    name: Mapped[str] = mapped_column(String(255), nullable=False, default="")
    status: Mapped[str] = mapped_column(String(20), nullable=False, default="ok")
    input: Mapped[dict] = mapped_column(JSON, nullable=False, default=dict)
    output: Mapped[dict] = mapped_column(JSON, nullable=False, default=dict)
    error: Mapped[str | None] = mapped_column(Text, nullable=True)
    tokens: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
    cost: Mapped[float | None] = mapped_column(Float, nullable=True)

    def __repr__(self) -> str:  # pragma: no cover - debug helper
        return f"<Step run={self.run_id} idx={self.idx} type={self.type}>"
