"""向量存储数据模型。

定义向量存储相关的共享数据模型，包括：

- ``CollectionName`` — 知识库向量集合名称字面量类型
- ``VectorDocument`` — 向量文档（业务对象）
- ``VectorSearchResult`` — 检索结果
- ``SearchFilter`` — 检索过滤器
- ``VectorCollectionConfig`` — 集合配置（运行时创建集合用）

这些是业务层的数据模型，可被多个项目复用。
"""

from __future__ import annotations

from datetime import date, datetime
from typing import Any, Literal

from pydantic import BaseModel, Field

CollectionName = Literal["chunks", "communities", "entities", "pictures", "relationships"]
"""知识库向量集合名称字面量类型。"""


class VectorDocument(BaseModel):
    """向量文档（业务对象）。

    表示一个向量化的文档，包含向量、原始文本和元数据。
    这是应用层的数据结构，与底层存储格式解耦。

    Parameters
    ----------
    id : str
        文档唯一标识符。
    vector : list[float]
        向量表示（embedding），通常为 float 列表。
    text : str | None
        原始文本内容（可选）。
    metadata : dict[str, Any]
        元数据字典，可包含任意键值对。
    created_at : datetime | None
        创建时间（可选），由存储后端填充。
    updated_at : datetime | None
        更新时间（可选），由存储后端填充。

    Examples
    --------
    >>> doc = VectorDocument(
    ...     id="doc_123",
    ...     vector=[0.1, 0.2, 0.3],
    ...     text="人工智能正在改变世界",
    ...     metadata={"author": "张三", "category": "AI"},
    ... )
    >>> doc.id
    'doc_123'
    """

    id: str = Field(..., description="文档唯一ID")
    vector: list[float] = Field(..., description="向量（embedding）")
    text: str | None = Field(default=None, description="原始文本内容")
    metadata: dict[str, Any] = Field(
        default_factory=dict,
        description="元数据字典，可包含任意键值对",
    )
    created_at: datetime | None = Field(
        default=None,
        description="创建时间，由支持时间戳的存储后端自动填充",
    )
    updated_at: datetime | None = Field(
        default=None,
        description="更新时间，由支持时间戳的存储后端自动填充",
    )

    model_config = {
        "json_schema_extra": {
            "examples": [
                {
                    "id": "doc_123",
                    "vector": [0.1, 0.2, 0.3],
                    "text": "人工智能正在改变世界",
                    "metadata": {
                        "author": "张三",
                        "date": "2024-01-01",
                        "category": "AI",
                    },
                }
            ]
        }
    }

    def __repr__(self) -> str:
        """返回文档的字符串表示。"""
        text_preview = self.text[:50] + "..." if self.text and len(self.text) > 50 else self.text
        return f"VectorDocument(id={self.id!r}, text={text_preview!r}, metadata={self.metadata})"


class VectorSearchResult(BaseModel):
    """向量检索结果。

    表示一个检索结果项，包含文档、相似度分数和排名。

    Parameters
    ----------
    document : VectorDocument
        检索到的文档对象。
    score : float
        相似度分数，范围 0-1，越高表示越相似。
    rank : int
        排名，从 1 开始（1 表示最相似）。

    Notes
    -----
    score 的含义取决于使用的距离度量：

    - cosine similarity: 1 表示完全相同，0 表示完全不相关
    - L2 distance: 0 表示完全相同，值越大越不相似
    - inner product: 值越大越相似

    Examples
    --------
    >>> from hezor_common.data_model.vector_store import (
    ...     VectorDocument, VectorSearchResult,
    ... )
    >>> result = VectorSearchResult(
    ...     document=VectorDocument(
    ...         id="doc_1", vector=[0.1, 0.2], text="示例"
    ...     ),
    ...     score=0.85,
    ...     rank=1,
    ... )
    >>> result.score
    0.85
    """

    document: VectorDocument = Field(..., description="检索到的文档")
    score: float = Field(..., description="相似度分数 (0-1)", ge=0.0, le=1.0)
    rank: int = Field(..., description="排名 (1-based)", ge=1)

    model_config = {
        "json_schema_extra": {
            "examples": [
                {
                    "document": {
                        "id": "doc_1",
                        "vector": [0.1, 0.2, 0.3],
                        "text": "人工智能应用示例",
                        "metadata": {"category": "AI"},
                    },
                    "score": 0.85,
                    "rank": 1,
                }
            ]
        }
    }

    def __repr__(self) -> str:
        """返回检索结果的字符串表示。"""
        return (
            f"VectorSearchResult(rank={self.rank}, score={self.score:.3f}, "
            f"doc_id={self.document.id!r})"
        )


class SearchFilter(BaseModel):
    """检索过滤器。

    用于在向量检索时进行额外的过滤，支持元数据过滤、
    日期范围过滤和全文查询。所有过滤条件是 AND 关系。

    Parameters
    ----------
    metadata_filter : dict[str, Any] | None
        元数据过滤条件，字典形式。
    date_range : tuple[date, date] | None
        日期范围过滤（开始日期，结束日期）。
    text_query : str | None
        全文搜索查询字符串。

    Notes
    -----
    - metadata_filter 支持精确匹配，不同后端可能支持更
      复杂的查询（如范围、正则等）
    - text_query 的行为取决于后端的全文搜索实现
    - 并非所有后端都支持所有过滤选项

    Examples
    --------
    >>> from datetime import date
    >>> f = SearchFilter(
    ...     metadata_filter={"author": "张三"},
    ...     date_range=(date(2024, 1, 1), date(2024, 12, 31)),
    ... )
    >>> f.metadata_filter
    {'author': '张三'}
    """

    metadata_filter: dict[str, Any] | None = Field(
        default=None,
        description="元数据过滤条件，如 {'author': '张三', 'category': 'AI'}",
    )
    date_range: tuple[date, date] | None = Field(
        default=None,
        description="日期范围过滤，如 (date(2024,1,1), date(2024,12,31))",
    )
    text_query: str | None = Field(
        default=None,
        description="全文搜索查询字符串",
    )

    model_config = {
        "json_schema_extra": {
            "examples": [
                {
                    "metadata_filter": {"author": "张三", "category": "AI"},
                    "date_range": ["2024-01-01", "2024-12-31"],
                    "text_query": "人工智能",
                }
            ]
        }
    }


class VectorCollectionConfig(BaseModel):
    """向量集合配置（运行时）。

    用于在运行时创建向量集合，定义集合的业务属性。

    Parameters
    ----------
    name : str
        集合名称。
    dimension : int
        向量维度（如 768, 1536 等）。
    distance_metric : Literal["cosine", "l2", "inner_product"]
        距离度量方式（默认 ``"cosine"``）。
    index_type : Literal["hnsw", "ivfflat", "flat"]
        索引类型（默认 ``"hnsw"``）。
    index_params : dict[str, Any] | None
        索引参数（可选）。

    Notes
    -----
    - distance_metric:
        - ``"cosine"``: 余弦相似度（推荐，范围归一化）
        - ``"l2"``: 欧氏距离（适合绝对距离）
        - ``"inner_product"``: 内积（适合已归一化的向量）
    - index_type:
        - ``"hnsw"``: 高性能 ANN 索引（推荐，适合大规模）
        - ``"ivfflat"``: IVF 倒排索引（适合中等规模）
        - ``"flat"``: 暴力搜索（精确但慢，适合小规模）

    Examples
    --------
    >>> config = VectorCollectionConfig(
    ...     name="documents",
    ...     dimension=768,
    ...     distance_metric="cosine",
    ...     index_type="hnsw",
    ... )
    >>> config.name
    'documents'
    """

    name: str = Field(..., description="集合名称")
    dimension: int = Field(..., description="向量维度", gt=0)
    distance_metric: Literal["cosine", "l2", "inner_product"] = Field(
        default="cosine",
        description="距离度量方式",
    )
    index_type: Literal["hnsw", "ivfflat", "flat"] = Field(
        default="hnsw",
        description="索引类型",
    )
    index_params: dict[str, Any] | None = Field(
        default=None,
        description="索引参数，如 HNSW 的 {'m': 16, 'ef_construction': 64}",
    )

    model_config = {
        "json_schema_extra": {
            "examples": [
                {
                    "name": "documents",
                    "dimension": 768,
                    "distance_metric": "cosine",
                    "index_type": "hnsw",
                    "index_params": {"m": 16, "ef_construction": 64},
                }
            ]
        }
    }

    def __repr__(self) -> str:
        """返回集合配置的字符串表示。"""
        return (
            f"VectorCollectionConfig(name={self.name!r}, "
            f"dimension={self.dimension}, metric={self.distance_metric}, "
            f"index={self.index_type})"
        )


__all__ = [
    "CollectionName",
    "SearchFilter",
    "VectorCollectionConfig",
    "VectorDocument",
    "VectorSearchResult",
]
