"""Tool Definition Manifest model."""

import uuid
from typing import TYPE_CHECKING

from sqlalchemy import Boolean, ForeignKey, JSON, String, Text
from sqlalchemy import Uuid as UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship

from src.models.base import Base, TimestampMixin, UUIDPrimaryKeyMixin

if TYPE_CHECKING:
    from src.models.user import User


class ToolDefinitionManifest(UUIDPrimaryKeyMixin, TimestampMixin, Base):
    """A declarative manifest that compiles to Dockerfile + Compose.

    Can be either:
    - A base definition (is_base=True) with a FROM image and common packages
    - A tool definition (is_base=False) that references a base + adds specifics
    """

    __tablename__ = "tool_definition_manifests"

    name: Mapped[str] = mapped_column(String(64), unique=True, nullable=False)
    display_name: Mapped[str] = mapped_column(String(128), nullable=False)
    description: Mapped[str | None] = mapped_column(Text, nullable=True)
    category: Mapped[str | None] = mapped_column(String(64), nullable=True)
    interface_type: Mapped[str] = mapped_column(String(16), nullable=False)

    # Base: either a direct image or a reference to another manifest
    base_image: Mapped[str | None] = mapped_column(String(256), nullable=True)
    base_definition_id: Mapped[uuid.UUID | None] = mapped_column(
        UUID(),
        ForeignKey("tool_definition_manifests.id"),
        nullable=True,
    )
    base_version: Mapped[str] = mapped_column(
        String(32), nullable=False, default="latest"
    )

    # The full manifest JSON
    manifest: Mapped[dict] = mapped_column(JSON, nullable=False)

    # Caches for quick inspection
    dockerfile_cache: Mapped[str | None] = mapped_column(Text, nullable=True)
    compose_cache: Mapped[str | None] = mapped_column(Text, nullable=True)

    # Versioning
    version: Mapped[str] = mapped_column(String(32), nullable=False, default="v1")
    is_base: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)

    created_by_id: Mapped[uuid.UUID | None] = mapped_column(
        UUID(),
        ForeignKey("users.id"),
        nullable=True,
    )

    # Relationships
    created_by: Mapped["User | None"] = relationship(
        foreign_keys=[created_by_id],
    )
    base_definition: Mapped["ToolDefinitionManifest | None"] = relationship(
        remote_side="ToolDefinitionManifest.id",
        foreign_keys=[base_definition_id],
    )
