"""Commercial Runtime SQLAlchemy models — universal registry SoT."""
from __future__ import annotations

import uuid
from datetime import datetime

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

from app.core.database import Base
from app.models.base import TimestampMixin, UUIDPrimaryKeyMixin
from app.models.types import GUID


class CommercialRegistryKind(UUIDPrimaryKeyMixin, TimestampMixin, Base):
    """Meta-registry of commercial object kinds (unlimited future kinds)."""

    __tablename__ = "commercial_registry_kinds"

    kind: Mapped[str] = mapped_column(String(100), nullable=False, unique=True)
    path: Mapped[str] = mapped_column(String(100), nullable=False, unique=True)
    display_name: Mapped[str] = mapped_column(String(200), nullable=False)
    description: Mapped[str | None] = mapped_column(Text, nullable=True)
    code_field: Mapped[str] = mapped_column(String(100), nullable=False, default="code")
    list_envelope: Mapped[str] = mapped_column(String(100), nullable=False, default="items")
    public_read: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
    enabled: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
    sort_order: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
    # meta_data avoids reserved name collision
    meta_data: Mapped[dict | None] = mapped_column("metadata", JSON, nullable=True)


class CommercialRegistryObject(UUIDPrimaryKeyMixin, TimestampMixin, Base):
    """Universal commercial registry object (registry_object_id = id)."""

    __tablename__ = "commercial_registry_objects"

    kind: Mapped[str] = mapped_column(String(100), nullable=False, index=True)
    slug: Mapped[str] = mapped_column(String(200), nullable=False)
    stable_code: Mapped[str] = mapped_column(String(200), nullable=False)
    version_code: Mapped[str] = mapped_column(String(64), nullable=False, default="1")
    display_name: Mapped[str] = mapped_column(String(300), nullable=False)
    description: Mapped[str | None] = mapped_column(Text, nullable=True)
    status: Mapped[str] = mapped_column(String(40), nullable=False, default="draft", index=True)
    visibility: Mapped[str] = mapped_column(String(40), nullable=False, default="public")
    # Platform catalogs: tenant_id NULL. Tenant-scoped commercial rows set tenant_id.
    tenant_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True, index=True)
    payload: Mapped[dict] = mapped_column(JSON, nullable=False, default=dict)
    meta_data: Mapped[dict] = mapped_column("metadata", JSON, nullable=False, default=dict)
    created_by: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    updated_by: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    published_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    archived_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    deleted_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    is_deleted: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False, index=True)
    clone_of_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)

    __table_args__ = (
        UniqueConstraint(
            "kind", "stable_code", "version_code", "tenant_id",
            name="uq_commercial_obj_kind_code_ver_tenant",
        ),
        Index("ix_commercial_obj_kind_status", "kind", "status"),
        Index("ix_commercial_obj_slug", "kind", "slug"),
        Index("ix_commercial_obj_search", "kind", "display_name"),
    )


class CommercialTenantSubscription(UUIDPrimaryKeyMixin, TimestampMixin, Base):
    """Tenant subscription instance (commercial lifecycle — not Payment ledger)."""

    __tablename__ = "commercial_tenant_subscriptions"

    tenant_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False, index=True)
    plan_code: Mapped[str | None] = mapped_column(String(200), nullable=True)
    bundle_code: Mapped[str | None] = mapped_column(String(200), nullable=True)
    pricing_item_code: Mapped[str | None] = mapped_column(String(200), nullable=True)
    status: Mapped[str] = mapped_column(String(40), nullable=False, default="trialing")
    trial_ends_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    current_period_start: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    current_period_end: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    cancel_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    meta_data: Mapped[dict] = mapped_column("metadata", JSON, nullable=False, default=dict)
    created_by: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)

    __table_args__ = (
        Index("ix_commercial_sub_tenant_status", "tenant_id", "status"),
    )


class CommercialTenantLicense(UUIDPrimaryKeyMixin, TimestampMixin, Base):
    """License / entitlement projection for a tenant."""

    __tablename__ = "commercial_tenant_licenses"

    tenant_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False, index=True)
    license_code: Mapped[str] = mapped_column(String(200), nullable=False)
    display_name: Mapped[str | None] = mapped_column(String(300), nullable=True)
    status: Mapped[str] = mapped_column(String(40), nullable=False, default="active")
    capability_codes: Mapped[list] = mapped_column(JSON, nullable=False, default=list)
    product_codes: Mapped[list] = mapped_column(JSON, nullable=False, default=list)
    bundle_code: Mapped[str | None] = mapped_column(String(200), nullable=True)
    quota: Mapped[dict] = mapped_column(JSON, nullable=False, default=dict)
    meta_data: Mapped[dict] = mapped_column("metadata", JSON, nullable=False, default=dict)
    expires_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)

    __table_args__ = (
        UniqueConstraint("tenant_id", "license_code", name="uq_commercial_license_tenant_code"),
    )


class CommercialActivationState(UUIDPrimaryKeyMixin, TimestampMixin, Base):
    """Tenant activation pipeline progress (event-contracted steps)."""

    __tablename__ = "commercial_activation_states"

    tenant_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False, unique=True)
    status: Mapped[str] = mapped_column(String(40), nullable=False, default="pending")
    completion_percent: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
    steps: Mapped[list] = mapped_column(JSON, nullable=False, default=list)
    checklist: Mapped[list] = mapped_column(JSON, nullable=False, default=list)
    meta_data: Mapped[dict] = mapped_column("metadata", JSON, nullable=False, default=dict)
