import { createHash } from "node:crypto";
function clampHeat(v) {
    const n = Math.round(Number(v));
    if (!Number.isFinite(n))
        return 3;
    return Math.min(5, Math.max(1, n));
}
function normCompetition(v) {
    return v === "低" || v === "中" || v === "高" ? v : "中";
}
function normOpportunity(v) {
    return v === "金矿" || v === "蓝海" || v === "红海" ? v : "蓝海";
}
function toStringArray(v) {
    return Array.isArray(v) ? v.map((x) => String(x)) : [];
}
const SEARCH_BASE = {
    youtube: "https://www.youtube.com/results?search_query=",
    tiktok: "https://www.tiktok.com/search?q=",
    xiaohongshu: "https://www.xiaohongshu.com/search_result?keyword=",
    douyin: "https://www.douyin.com/search/",
};
function searchUrlFor(platform, title) {
    const base = SEARCH_BASE[platform] ?? SEARCH_BASE.xiaohongshu;
    return base + encodeURIComponent(title);
}
function topicToItem(topic, platform, idx, collectedAt) {
    const title = String(topic.title ?? `Trend ${idx + 1}`).slice(0, 200);
    // Salt the hash with the array index so duplicate titles can't collide on the
    // same id (the #41 enrichment-collision lesson, applied to synthesized ids).
    const hash = createHash("sha1")
        .update(`${idx}:${title}`)
        .digest("hex")
        .slice(0, 12);
    return {
        id: `legacy_${platform}_${hash}`,
        platform,
        title,
        sourceUrl: searchUrlFor(platform, title),
        source: "agent_websearch",
        scrapedAt: collectedAt,
        // Legacy topics carry no cover; TrendingPanel renders no thumbnail (rank is
        // the visual anchor), so an empty placeholder is safe.
        cover: { url: "", aspect: "9:16" },
        metrics: null,
        analysis: {
            heat: clampHeat(topic.heat),
            competition: normCompetition(topic.competition),
            opportunity: normOpportunity(topic.opportunity),
            description: String(topic.description ?? ""),
            tags: toStringArray(topic.tags),
            contentAngles: toStringArray(topic.contentAngles),
            exampleHook: String(topic.exampleHook ?? ""),
            category: String(topic.category ?? "趋势"),
        },
    };
}
/**
 * Returns a payload the frontend's `{items}` contract understands. Already-new
 * `{items}` payloads pass through untouched; legacy `{topics}` payloads are
 * mapped to `{items}`. Anything else is returned as-is.
 */
export function normalizeTrendsPayload(data, platform, collectedAtFallback) {
    if (!data || typeof data !== "object")
        return data;
    const obj = data;
    if (Array.isArray(obj.items))
        return obj; // current schema — leave alone
    if (Array.isArray(obj.topics)) {
        const collectedAt = typeof obj.collectedAt === "string" ? obj.collectedAt : collectedAtFallback;
        const items = obj.topics.map((topic, idx) => topicToItem(topic, platform, idx, collectedAt));
        return {
            platform,
            items,
            collectedAt,
            pipelineStatus: "ok",
        };
    }
    return obj;
}
//# sourceMappingURL=normalize.js.map