import uuid

from sqlalchemy import ForeignKey, String
from sqlalchemy.dialects.postgresql import JSONB, UUID as PGUUID
from sqlalchemy.orm import Mapped, mapped_column

from app.models.base import Base, TenantScopedMixin, TimestampMixin, UUIDPKMixin


class App(UUIDPKMixin, TenantScopedMixin, TimestampMixin, Base):
    """A curated, named bundle of existing tenant artifacts — see
    crud/app_bundle.py for what "bundle" means at export/import time.
    `items` is a JSONB list of {"type": "form"|"master"|"workflow"|"task"|
    "page"|"dashboard"|"menu", "id": "<uuid>"} — a soft reference list, same
    convention as Menu.target_id/PageBlockDef.data_source elsewhere in this
    codebase (no DB-level FK, since an item can be deleted independently)."""

    __tablename__ = "apps"

    name: Mapped[str] = mapped_column(String(200), nullable=False)
    description: Mapped[str | None] = mapped_column(String(1000))
    items: Mapped[list] = mapped_column(JSONB, nullable=False, server_default="[]")
    created_by: Mapped[uuid.UUID | None] = mapped_column(PGUUID(as_uuid=True), ForeignKey("users.id"))


class AppImportLink(UUIDPKMixin, TenantScopedMixin, TimestampMixin, Base):
    """What one item of another environment (source_tenant_id + item_type +
    source_id) became in this tenant when an App was imported — so the next
    import of that App updates it rather than creating a duplicate. See
    crud/app_bundle.py::import_bundle."""

    __tablename__ = "app_import_links"

    source_tenant_id: Mapped[uuid.UUID] = mapped_column(PGUUID(as_uuid=True), nullable=False)
    item_type: Mapped[str] = mapped_column(String(20), nullable=False)
    source_id: Mapped[uuid.UUID] = mapped_column(PGUUID(as_uuid=True), nullable=False)
    target_id: Mapped[uuid.UUID] = mapped_column(PGUUID(as_uuid=True), nullable=False)
