from __future__ import annotations

import uuid
from datetime import datetime

from sqlalchemy import (
    Boolean,
    CheckConstraint,
    DateTime,
    ForeignKey,
    Index,
    Integer,
    String,
    Text,
    func,
)
from sqlalchemy.orm import Mapped, mapped_column

from app.db.base_class import Base


class KnowledgeOnlyOfficeSession(Base):
    __tablename__ = "knowledge_onlyoffice_sessions"
    __table_args__ = (
        CheckConstraint(
            "resource_scope IN ('tenant', 'platform')",
            name="ck_knowledge_onlyoffice_sessions_scope",
        ),
        CheckConstraint(
            "status IN ('active', 'processing', 'consumed', 'failed', 'revoked')",
            name="ck_knowledge_onlyoffice_sessions_status",
        ),
        CheckConstraint(
            "tenant_id IS NOT NULL AND "
            "(resource_scope = 'tenant' OR "
            "(resource_scope = 'platform' AND editable = false))",
            name="ck_knowledge_onlyoffice_sessions_scope_tenant",
        ),
        CheckConstraint(
            "(status = 'active' AND claimed_at IS NULL AND consumed_at IS NULL) OR "
            "(status IN ('processing', 'failed') AND claimed_at IS NOT NULL "
            "AND consumed_at IS NULL) OR "
            "(status = 'consumed' AND claimed_at IS NOT NULL AND consumed_at IS NOT NULL) OR "
            "(status = 'revoked' AND consumed_at IS NULL)",
            name="ck_knowledge_onlyoffice_sessions_lifecycle",
        ),
        Index(
            "ix_knowledge_onlyoffice_sessions_tenant_document",
            "tenant_id",
            "document_id",
            "created_at",
        ),
        Index(
            "ix_knowledge_onlyoffice_sessions_status_expiry",
            "status",
            "expires_at",
        ),
    )

    jti: Mapped[str] = mapped_column(
        String(36),
        primary_key=True,
        default=lambda: str(uuid.uuid4()),
    )
    tenant_id: Mapped[str] = mapped_column(
        String(64),
        ForeignKey("tenants.tenant_id", ondelete="CASCADE"),
        nullable=False,
    )
    resource_scope: Mapped[str] = mapped_column(String(16), nullable=False)
    document_id: Mapped[str] = mapped_column(String(64), nullable=False)
    document_key: Mapped[str] = mapped_column(String(160), nullable=False)
    document_version: Mapped[int] = mapped_column(Integer, nullable=False)
    audience: Mapped[str] = mapped_column(String(80), nullable=False)
    editable: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
    status: Mapped[str] = mapped_column(String(16), nullable=False, default="active")
    created_by: Mapped[str] = mapped_column(String(100), nullable=False)
    expires_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
    claimed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    consumed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    failure_reason: Mapped[str] = mapped_column(Text, nullable=False, default="")
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        nullable=False,
        server_default=func.now(),
    )
