# #region DatasetReviewSessionModels [C:3] [TYPE Module] [SEMANTICS sqlalchemy, dataset, review, session, model]
# @BRIEF Session aggregate root and collaborator models for dataset review orchestration.
# @LAYER Domain
# @RELATION DEPENDS_ON -> [DatasetReviewEnums]
# @RELATION DEPENDS_ON -> [MappingModels]
# @INVARIANT  Session and profile entities are strictly scoped to an authenticated user.
# @PRE  Database engine initialized
# @POST  Session ORM models registered with optimistic locking
# @SIDE_EFFECT  Defines dataset review session tables
# @DATA_CONTRACT  SessionData -> SessionRecord

from datetime import UTC, datetime
import uuid

from sqlalchemy import (
    Column,
    DateTime,
    Enum as SQLEnum,
    ForeignKey,
    Integer,
    String,
)
from sqlalchemy.orm import relationship

from src.models.dataset_review_pkg._enums import (
    ReadinessState,
    RecommendedAction,
    SessionCollaboratorRole,
    SessionPhase,
    SessionStatus,
)
from src.models.mapping import Base


# #region SessionCollaborator [C:2] [TYPE Class]
# @BRIEF RBAC collaborator record linking a user to a dataset review session with a specific role.
# @RELATION DEPENDS_ON -> [DatasetReviewSession]
class SessionCollaborator(Base):
    __tablename__ = "session_collaborators"

    id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
    session_id = Column(
        String, ForeignKey("dataset_review_sessions.session_id"), nullable=False
    )
    user_id = Column(String, ForeignKey("users.id"), nullable=False)
    role = Column(SQLEnum(SessionCollaboratorRole), nullable=False)
    added_at = Column(DateTime, default=lambda: datetime.now(UTC), nullable=False)

    session = relationship("DatasetReviewSession", back_populates="collaborators")
    user = relationship("User")


# #endregion SessionCollaborator


# #region DatasetReviewSession [C:3] [TYPE Class]
# @BRIEF Aggregate root for the dataset review lifecycle, owning all child entities and driving readiness transitions.
# @RELATION DEPENDS_ON -> [SessionCollaborator]
# @RELATION DEPENDS_ON -> [DatasetProfile]
# @RELATION DEPENDS_ON -> [ValidationFinding]
# @RELATION DEPENDS_ON -> [SemanticSource]
# @RELATION DEPENDS_ON -> [SemanticFieldEntry]
# @RELATION DEPENDS_ON -> [ImportedFilter]
# @RELATION DEPENDS_ON -> [TemplateVariable]
# @RELATION DEPENDS_ON -> [ExecutionMapping]
# @RELATION DEPENDS_ON -> [ClarificationSession]
# @RELATION DEPENDS_ON -> [CompiledPreview]
# @RELATION DEPENDS_ON -> [DatasetRunContext]
# @RELATION DEPENDS_ON -> [ExportArtifact]
# @RELATION DEPENDS_ON -> [SessionEvent]
# @INVARIANT  Optimistic-lock version column prevents lost-update races on concurrent mutations.
class DatasetReviewSession(Base):
    __tablename__ = "dataset_review_sessions"

    session_id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
    user_id = Column(String, ForeignKey("users.id"), nullable=False)
    environment_id = Column(String, ForeignKey("environments.id", ondelete="CASCADE"), nullable=False)
    source_kind = Column(String, nullable=False)
    source_input = Column(String, nullable=False)
    dataset_ref = Column(String, nullable=False)
    dataset_id = Column(Integer, nullable=True)
    dashboard_id = Column(Integer, nullable=True)
    readiness_state = Column(
        SQLEnum(ReadinessState), nullable=False, default=ReadinessState.EMPTY
    )
    recommended_action = Column(
        SQLEnum(RecommendedAction),
        nullable=False,
        default=RecommendedAction.IMPORT_FROM_SUPERSET,
    )
    version = Column(Integer, nullable=False, default=0)
    __mapper_args__ = {"version_id_col": version, "version_id_generator": False}
    status = Column(
        SQLEnum(SessionStatus), nullable=False, default=SessionStatus.ACTIVE
    )
    current_phase = Column(
        SQLEnum(SessionPhase), nullable=False, default=SessionPhase.INTAKE
    )
    active_task_id = Column(String, nullable=True)
    last_preview_id = Column(String, nullable=True)
    last_run_context_id = Column(String, nullable=True)
    created_at = Column(DateTime, default=lambda: datetime.now(UTC), nullable=False)
    updated_at = Column(
        DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC), nullable=False
    )
    last_activity_at = Column(DateTime, default=lambda: datetime.now(UTC), nullable=False)
    closed_at = Column(DateTime, nullable=True)

    owner = relationship("User")
    collaborators = relationship(
        "SessionCollaborator", back_populates="session", cascade="all, delete-orphan"
    )
    profile = relationship(
        "DatasetProfile",
        back_populates="session",
        uselist=False,
        cascade="all, delete-orphan",
    )
    findings = relationship(
        "ValidationFinding", back_populates="session", cascade="all, delete-orphan"
    )
    semantic_sources = relationship(
        "SemanticSource", back_populates="session", cascade="all, delete-orphan"
    )
    semantic_fields = relationship(
        "SemanticFieldEntry", back_populates="session", cascade="all, delete-orphan"
    )
    imported_filters = relationship(
        "ImportedFilter", back_populates="session", cascade="all, delete-orphan"
    )
    template_variables = relationship(
        "TemplateVariable", back_populates="session", cascade="all, delete-orphan"
    )
    execution_mappings = relationship(
        "ExecutionMapping", back_populates="session", cascade="all, delete-orphan"
    )
    clarification_sessions = relationship(
        "ClarificationSession", back_populates="session", cascade="all, delete-orphan"
    )
    previews = relationship(
        "CompiledPreview", back_populates="session", cascade="all, delete-orphan"
    )
    run_contexts = relationship(
        "DatasetRunContext", back_populates="session", cascade="all, delete-orphan"
    )
    export_artifacts = relationship(
        "ExportArtifact", back_populates="session", cascade="all, delete-orphan"
    )
    events = relationship(
        "SessionEvent", back_populates="session", cascade="all, delete-orphan"
    )


# #endregion DatasetReviewSession


# #endregion DatasetReviewSessionModels
