//! Data types for the profile executor pipeline.
//!
//! These types carry no execution logic -- they are the nouns of the ranking
//! pipeline. `UserContext` captures pre-computed personalization state for a
//! single query, and `ScoredCandidate` is the output of the scoring pipeline.

use std::collections::HashMap;

use crate::schema::EntityId;

// -- User context -------------------------------------------------------------

/// User-specific scoring context for personalized ranking.
///
/// Pre-computed before scoring to avoid per-candidate lookups. Built by
/// `RetrieveExecutor` in Stage 3 when `FOR USER` is specified.
///
/// This struct is short-lived (per-query), so it uses `std::collections::HashMap`
/// rather than `DashMap` -- no concurrent access is needed.
pub struct UserContext {
    /// `user_id` for this context.
    pub user_id: u64,
    /// Per-item interaction boost: maps `item_id (u32)` -> boost score.
    /// Pre-computed from `InteractionLedger::top_creators()` + `CreatorItemsBitmap`.
    /// Items from creators the user has interacted with get a positive boost
    /// proportional to the interaction weight.
    pub creator_interaction_boosts: HashMap<u32, f64>,
}

// -- Scored candidate ---------------------------------------------------------

/// A candidate entity with its computed score and signal snapshot.
///
/// After the executor pipeline, `score` is normalized to `[0.0, 1.0]`.
/// The `signal_snapshot` captures the top signals that contributed to the score,
/// enabling explain-ability in API responses.
#[derive(Debug, Clone)]
pub struct ScoredCandidate {
    pub entity_id: EntityId,
    pub score: f64,
    pub signal_snapshot: Vec<(String, f64)>,
    /// Creator ID for diversity enforcement (populated in m2p4).
    pub creator_id: Option<EntityId>,
    /// Content format for diversity enforcement (populated in m2p4).
    pub format: Option<String>,
}
