# #region DatasetReviewSemanticModels [C:3] [TYPE Module] [SEMANTICS sqlalchemy, dataset, review, semantic, enrichment]
# @BRIEF Semantic source, field entry, and candidate models for dictionary-driven semantic enrichment.
# @LAYER Domain
# @RELATION DEPENDS_ON -> [DatasetReviewEnums]
# @RELATION DEPENDS_ON -> [MappingModels]
# @INVARIANT  Manual overrides are never silently replaced by imported, inferred, or AI-generated values.
# @PRE  Database engine initialized
# @POST  Semantic ORM models registered with override protection
# @SIDE_EFFECT  Defines dataset review semantic tables
# @DATA_CONTRACT  SemanticData -> SemanticFieldEntry

from datetime import UTC, datetime
import uuid

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

from src.models.dataset_review_pkg._enums import (
    CandidateMatchType,
    CandidateStatus,
    FieldKind,
    FieldProvenance,
    SemanticSourceStatus,
    SemanticSourceType,
    TrustLevel,
)
from src.models.mapping import Base


# #region SemanticSource [C:2] [TYPE Class]
# @BRIEF Registered semantic enrichment source with trust level and application status.
# @RELATION DEPENDS_ON -> [DatasetReviewSession]
class SemanticSource(Base):
    __tablename__ = "semantic_sources"

    source_id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
    session_id = Column(
        String, ForeignKey("dataset_review_sessions.session_id"), nullable=False
    )
    source_type = Column(SQLEnum(SemanticSourceType), nullable=False)
    source_ref = Column(String, nullable=False)
    source_version = Column(String, nullable=False)
    display_name = Column(String, nullable=False)
    trust_level = Column(SQLEnum(TrustLevel), nullable=False)
    schema_overlap_score = Column(Float, nullable=True)
    status = Column(
        SQLEnum(SemanticSourceStatus),
        nullable=False,
        default=SemanticSourceStatus.AVAILABLE,
    )
    created_at = Column(DateTime, default=lambda: datetime.now(UTC), nullable=False)

    session = relationship("DatasetReviewSession", back_populates="semantic_sources")


# #endregion SemanticSource


# #region SemanticFieldEntry [C:3] [TYPE Class]
# @BRIEF Per-field semantic metadata entry with provenance tracking, lock state, and candidate set.
# @RELATION DEPENDS_ON -> [DatasetReviewSession]
# @RELATION DEPENDS_ON -> [SemanticCandidate]
# @INVARIANT  Locked fields preserve their active value regardless of later candidate proposals.
class SemanticFieldEntry(Base):
    __tablename__ = "semantic_field_entries"

    field_id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
    session_id = Column(
        String, ForeignKey("dataset_review_sessions.session_id"), nullable=False
    )
    field_name = Column(String, nullable=False)
    field_kind = Column(SQLEnum(FieldKind), nullable=False)
    verbose_name = Column(String, nullable=True)
    description = Column(Text, nullable=True)
    display_format = Column(String, nullable=True)
    provenance = Column(
        SQLEnum(FieldProvenance), nullable=False, default=FieldProvenance.UNRESOLVED
    )
    source_id = Column(String, nullable=True)
    source_version = Column(String, nullable=True)
    confidence_rank = Column(Integer, nullable=True)
    is_locked = Column(Boolean, nullable=False, default=False)
    has_conflict = Column(Boolean, nullable=False, default=False)
    needs_review = Column(Boolean, nullable=False, default=True)
    last_changed_by = Column(String, nullable=False)
    user_feedback = 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
    )

    session = relationship("DatasetReviewSession", back_populates="semantic_fields")
    candidates = relationship(
        "SemanticCandidate", back_populates="field", cascade="all, delete-orphan"
    )


# #endregion SemanticFieldEntry


# #region SemanticCandidate [C:2] [TYPE Class]
# @BRIEF One proposed semantic value for a field entry, ranked by match type and confidence.
# @RELATION DEPENDS_ON -> [SemanticFieldEntry]
class SemanticCandidate(Base):
    __tablename__ = "semantic_candidates"

    candidate_id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
    field_id = Column(
        String, ForeignKey("semantic_field_entries.field_id"), nullable=False
    )
    source_id = Column(String, nullable=True)
    candidate_rank = Column(Integer, nullable=False)
    match_type = Column(SQLEnum(CandidateMatchType), nullable=False)
    confidence_score = Column(Float, nullable=False)
    proposed_verbose_name = Column(String, nullable=True)
    proposed_description = Column(Text, nullable=True)
    proposed_display_format = Column(String, nullable=True)
    status = Column(
        SQLEnum(CandidateStatus), nullable=False, default=CandidateStatus.PROPOSED
    )
    created_at = Column(DateTime, default=lambda: datetime.now(UTC), nullable=False)

    field = relationship("SemanticFieldEntry", back_populates="candidates")


# #endregion SemanticCandidate


# #endregion DatasetReviewSemanticModels
