from __future__ import annotations

from typing import Any, Literal, Optional

from pydantic import BaseModel, Field

from app.features.personalized_reco.content_repository.types import ContentProfileDTO

Scene = Literal["feed", "push", "widget"]


class ScoredCandidate(BaseModel):
    """
    Soft Scoring 后的候选项（本模块消费的最小字段集合）。

    说明：
    - `content_profile` 用于 Feed 的标签/相似度计算；缺失时需降级为仅使用 author/template 等字段
    """

    content_id: int
    final_score: float

    author_id: Optional[str] = None
    template_id: Optional[str] = None

    content_profile: Optional[ContentProfileDTO] = None

    # 允许透传额外字段（例如 text、breakdown 等），便于上层直接下发
    extra: dict[str, Any] = Field(default_factory=dict)


class RerankConfig(BaseModel):
    """
    重排/频控配置（可调参）。
    """

    # Feed：MMR
    mmr_lambda: float = 0.7
    top_n_for_mmr: int = 200

    # Push/Widget：冷却窗口（V1 主要用于配置与可观测；真正按天需要带时间戳的历史）
    cooldown_sentence_days: int = 14
    cooldown_author_days: int = 7
    cooldown_template_days: int = 7


class RerankMeta(BaseModel):
    candidate_pool_size_after_dedup: int
    candidate_pool_size_after_freqcap: int

    # 例如未提供 recent_author_ids/recent_template_ids 时记录 ["author","template"]
    missing_history_fields: list[str] = Field(default_factory=list)

    # 可选但建议：按维度统计被过滤数量
    freqcap_filtered_counts: dict[str, int] = Field(default_factory=dict)


class RerankResult(BaseModel):
    ranked_items: list[ScoredCandidate] = Field(default_factory=list)
    meta: RerankMeta

