from datetime import datetime, timezone

from sqlalchemy import Boolean, DateTime, ForeignKey, Index, Integer, Text
from sqlalchemy.dialects.postgresql import ARRAY, JSONB
from sqlalchemy.orm import Mapped, mapped_column

from fabledassistant.models import Base


class GenerationToolLog(Base):
    """One row per assistant turn — what tools the model could/did use.

    Lets the operator answer "does model X actually fire record_moment?"
    empirically across model swaps without relying on anecdote.
    """

    __tablename__ = "generation_tool_log"

    id: Mapped[int] = mapped_column(primary_key=True)
    user_id: Mapped[int] = mapped_column(
        Integer,
        ForeignKey("users.id", ondelete="CASCADE"),
        nullable=False,
    )
    conv_id: Mapped[int] = mapped_column(
        Integer,
        ForeignKey("conversations.id", ondelete="CASCADE"),
        nullable=False,
    )
    # SET NULL (migration matches) so the telemetry row survives if the
    # underlying assistant message is later deleted.
    assistant_message_id: Mapped[int | None] = mapped_column(
        Integer,
        ForeignKey("messages.id", ondelete="SET NULL"),
        nullable=True,
    )
    model: Mapped[str] = mapped_column(Text, nullable=False)
    think_enabled: Mapped[bool] = mapped_column(Boolean, nullable=False)
    tools_available: Mapped[list[str]] = mapped_column(
        ARRAY(Text), nullable=False, default=list
    )
    tools_attempted: Mapped[list[str]] = mapped_column(
        ARRAY(Text), nullable=False, default=list
    )
    tools_succeeded: Mapped[list[str]] = mapped_column(
        ARRAY(Text), nullable=False, default=list
    )
    # JSONB list of {name, error} dicts.
    tools_failed: Mapped[list[dict]] = mapped_column(
        JSONB, nullable=False, default=list
    )
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        default=lambda: datetime.now(timezone.utc),
    )

    __table_args__ = (
        Index("ix_generation_tool_log_user_created", "user_id", created_at.desc()),
        Index("ix_generation_tool_log_conv", "conv_id"),
    )

    def to_dict(self) -> dict:
        return {
            "id": self.id,
            "user_id": self.user_id,
            "conv_id": self.conv_id,
            "assistant_message_id": self.assistant_message_id,
            "model": self.model,
            "think_enabled": self.think_enabled,
            "tools_available": list(self.tools_available or []),
            "tools_attempted": list(self.tools_attempted or []),
            "tools_succeeded": list(self.tools_succeeded or []),
            "tools_failed": list(self.tools_failed or []),
            "created_at": self.created_at.isoformat() if self.created_at else None,
        }
