from __future__ import annotations

from datetime import datetime
from typing import Any

from sqlalchemy import (
    Boolean,
    DateTime,
    Index,
    JSON,
    String,
    Text,
    UniqueConstraint,
    func,
)
from sqlalchemy.orm import Mapped, mapped_column

from supply_infra.db.base import Base


class PipelineOutbox(Base):
    """Ledger of dispatched AIGC write effects."""

    __tablename__ = "pipeline_outbox"
    __table_args__ = (
        UniqueConstraint("idempotency_key", name="uk_pipeline_outbox_idempotency"),
        Index("idx_pipeline_outbox_run", "run_id", "step_run_id"),
        Index("idx_pipeline_outbox_status", "status", "created_at"),
    )

    outbox_id: Mapped[str] = mapped_column(String(36), primary_key=True)
    run_id: Mapped[str] = mapped_column(
        String(36),
        nullable=False,
    )
    step_run_id: Mapped[str] = mapped_column(
        String(36),
        nullable=False,
    )
    effect_type: Mapped[str] = mapped_column(String(64), nullable=False)
    idempotency_key: Mapped[str] = mapped_column(String(191), nullable=False)
    payload_hash: Mapped[str] = mapped_column(String(64), nullable=False)
    payload_json: Mapped[dict[str, Any] | None] = mapped_column(JSON, nullable=True)
    payload_uri: Mapped[str | None] = mapped_column(String(1024), nullable=True)
    status: Mapped[str] = mapped_column(
        String(32),
        nullable=False,
        default="dispatched",
    )
    dry_run: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
    record_error: Mapped[str | None] = mapped_column(Text, nullable=True)
    created_at: Mapped[datetime] = mapped_column(
        DateTime,
        nullable=False,
        server_default=func.now(),
    )
    updated_at: Mapped[datetime] = mapped_column(
        DateTime,
        nullable=False,
        server_default=func.now(),
        onupdate=func.now(),
    )
