package com.tzld.piaoquan.recommend.server.service.funnel;

import lombok.Data;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * 单次推荐请求的漏斗中间态容器，挂在 RecallParam + RankParam 上跨服务传递。
 * 末尾由 FunnelAggregator 序列化成一条 SLS 日志（8 个 step JSON 字段）。
 *
 * 并发安全说明：
 * - stages123RecallByStrategy 被 30+ 召回 strategy 子线程并发写 → ConcurrentMap
 * - 同 pushFrom 的 List 由 FilterService 单次写入，不会并发追加
 * - 阶段 4-8 由主线程顺序写
 */
@Data
public class FunnelContext {
    // ===== base =====
    private String traceId;
    private String recommendTraceId;
    private String sessionId;
    private String subSessionId;
    private String rootSessionId;
    private String mid;
    private String uid;
    private int    appType;
    private String newExpGroup;
    private Set<String> abExpCodes;

    // ===== 固定字段: 风险/地域上下文 =====
    private Long   hotSceneType;
    private String province;
    private String city;
    private boolean ifNewUser;
    private boolean ifRiskMid;
    private boolean ifRiskUid;

    /** Step 1-3: 召回 / 过滤 / 截断（per pushFrom，字段在 RecallVideoEntry 上分组） */
    private ConcurrentMap<String, List<RecallVideoEntry>> stages123RecallByStrategy = new ConcurrentHashMap<>();

    /** Step 4: 合并去重后顺序 */
    private List<Long>         step4MergedVideoIds = new ArrayList<>();
    /** Step 4: vid -> 合并时归因到哪条 pushFrom */
    private Map<Long, String>  step4MergedAttribution = new HashMap<>();

    /** Step 5: rank 模型打分结果 */
    private Map<Long, RankVideoEntry> step5RankedData = new HashMap<>();

    /** Step 6: 排序截断后顺序（rank_index = list 中位置 + 1） */
    private List<Long>         step6RankTruncatedVideoIds = new ArrayList<>();

    /** Step 7: 冷启替换标记 */
    private Map<Long, ColdStartAction> step7ColdStartActions = new HashMap<>();

    /** Step 8: 最终下发顺序（output_index = list 中位置 + 1） */
    private List<Long>         step8OutputVideoIds = new ArrayList<>();
}
