"""RAG 平台 Pydantic 数据模型。

这些是领域模型（非 ORM），ORM 模型定义在 store.py（U2）。
与 memory/knowledge_base.py 的 KnowledgeBase protocol 分离 —
rag_platform 服务企业知识库场景，memory/ 服务 Agent 运行时记忆。
"""

from __future__ import annotations

import uuid
from datetime import datetime, timezone
from enum import Enum

from pydantic import BaseModel, ConfigDict, Field


def _utcnow() -> datetime:
    return datetime.now(timezone.utc)


def _uuid() -> str:
    return str(uuid.uuid4())


class KBStatus(str, Enum):
    active = "active"
    archived = "archived"


class DocumentStatus(str, Enum):
    """文档处理状态机：pending → parsing → segmenting → vectorizing → indexed | failed。"""

    pending = "pending"
    parsing = "parsing"
    segmenting = "segmenting"
    vectorizing = "vectorizing"
    indexed = "indexed"
    failed = "failed"


class QueryMode(str, Enum):
    """检索模式：embedding 语义 / keywords 全文 / blend 双索引合并。"""

    embedding = "embedding"
    keywords = "keywords"
    blend = "blend"


class KnowledgeBase(BaseModel):
    """知识库领域模型。"""

    model_config = ConfigDict(from_attributes=True)

    id: str = Field(default_factory=_uuid)
    name: str
    description: str = ""
    owner: str
    status: KBStatus = KBStatus.active
    # 检索与命中处理默认配置（Agent 运行时可覆盖）
    default_query_mode: QueryMode = QueryMode.blend
    default_hit_processing: str = "model_opt"  # model_opt | direct
    caching_disabled: bool = False
    created_at: datetime = Field(default_factory=_utcnow)
    updated_at: datetime = Field(default_factory=_utcnow)


class Document(BaseModel):
    """知识库文档领域模型。"""

    model_config = ConfigDict(from_attributes=True)

    id: str = Field(default_factory=_uuid)
    kb_id: str
    filename: str
    file_type: str
    file_size: int
    status: DocumentStatus = DocumentStatus.pending
    error_message: str | None = None
    created_at: datetime = Field(default_factory=_utcnow)
    updated_at: datetime = Field(default_factory=_utcnow)


class Chunk(BaseModel):
    """文档分段后的文本块。"""

    model_config = ConfigDict(from_attributes=True)

    id: str = Field(default_factory=_uuid)
    document_id: str
    kb_id: str
    content: str
    metadata: dict = Field(default_factory=dict)
    embedding: list[float] | None = None


class QueryResult(BaseModel):
    """检索结果条目。"""

    model_config = ConfigDict(from_attributes=True)

    chunk_id: str
    content: str
    score: float
    metadata: dict = Field(default_factory=dict)
    document_id: str
    kb_id: str


class RetrievalRequest(BaseModel):
    """检索请求 — 支持覆盖 KB 默认配置。

    retrieval_mode / hit_processing_mode 为 None 时使用 KB 默认值。
    """

    model_config = ConfigDict()

    query: str
    kb_ids: list[str]
    retrieval_mode: QueryMode | None = None  # None = 使用 KB 默认
    hit_processing_mode: str | None = None  # None = 使用 KB 默认
    top_k: int = 5
    user_id: str | None = None  # 用于 ACL 过滤


# ---------------------------------------------------------------------------
# ORM Models (SQLAlchemy 2 DeclarativeBase + Mapped)
# ---------------------------------------------------------------------------

from sqlalchemy import DateTime, ForeignKey, String, Text, UniqueConstraint  # noqa: E402
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column  # noqa: E402


class ORMBase(DeclarativeBase):
    """rag_platform ORM 基类 — 与 memory/models.py 的 declarative_base() 独立。"""

    pass


class KBModel(ORMBase):
    """知识库 ORM 模型。"""

    __tablename__ = "rag_platform_kbs"

    id: Mapped[str] = mapped_column(String, primary_key=True, default=_uuid)
    name: Mapped[str] = mapped_column(String(255))
    description: Mapped[str] = mapped_column(Text, default="")
    owner: Mapped[str] = mapped_column(String(255), index=True)
    status: Mapped[str] = mapped_column(String(32), default="active", index=True)
    default_query_mode: Mapped[str] = mapped_column(String(32), default="blend")
    default_hit_processing: Mapped[str] = mapped_column(String(32), default="model_opt")
    caching_disabled: Mapped[bool] = mapped_column(default=False)
    created_at: Mapped[datetime] = mapped_column(DateTime, default=_utcnow)
    updated_at: Mapped[datetime] = mapped_column(DateTime, default=_utcnow)


class DocumentModel(ORMBase):
    """知识库文档 ORM 模型。"""

    __tablename__ = "rag_platform_documents"

    id: Mapped[str] = mapped_column(String, primary_key=True, default=_uuid)
    kb_id: Mapped[str] = mapped_column(
        String, ForeignKey("rag_platform_kbs.id", ondelete="CASCADE"), index=True
    )
    filename: Mapped[str] = mapped_column(String(512))
    file_type: Mapped[str] = mapped_column(String(64))
    file_size: Mapped[int] = mapped_column(default=0)
    status: Mapped[str] = mapped_column(String(32), default="pending", index=True)
    error_message: Mapped[str | None] = mapped_column(Text, nullable=True)
    created_at: Mapped[datetime] = mapped_column(DateTime, default=_utcnow)
    updated_at: Mapped[datetime] = mapped_column(DateTime, default=_utcnow)


class KBAclModel(ORMBase):
    """Per-KB 访问控制 ORM 模型。

    kb_id FK → rag_platform_kbs.id ON DELETE CASCADE（KTD5 不变量）。
    ACL 条目与 KB 元数据共享事务边界（同一 PG DB）。
    """

    __tablename__ = "rag_platform_kb_acl"
    __table_args__ = (UniqueConstraint("kb_id", "user_id", name="uq_kb_acl_kb_user"),)

    id: Mapped[str] = mapped_column(String, primary_key=True, default=_uuid)
    kb_id: Mapped[str] = mapped_column(
        String, ForeignKey("rag_platform_kbs.id", ondelete="CASCADE"), index=True
    )
    user_id: Mapped[str] = mapped_column(String(255), index=True)
    role: Mapped[str] = mapped_column(String(32), default="viewer")  # owner | viewer
    created_at: Mapped[datetime] = mapped_column(DateTime, default=_utcnow)
