/**
 * Ranking Algorithm for sojorn Feed
 *
 * Design intent:
 * - Attention moves slowly.
 * - Nothing competes for dominance.
 * - Clean content is protected from suppression.
 *
 * Principles:
 * - Saves > likes (intentional curation over quick reaction)
 * - Steady appreciation over time > viral spikes
 * - Low block rate = content is not harmful
 * - Low trusted report rate = content is genuinely clean
 * - Ignore comment count (we don't reward arguments)
 * - Ignore report spikes on high-CIS posts (brigading protection)
 */

export interface PostForRanking {
  id: string;
  created_at: string;
  cis_score: number;
  tone_label: string;
  save_count: number;
  like_count: number;
  view_count: number;
  author_harmony_score: number;
  author_tier: string;
  blocks_received_24h: number;
  trusted_reports: number;
  total_reports: number;
}

/**
 * Calculate calm velocity score
 * Measures steady appreciation rather than viral spikes
 */
function calculateCalmVelocity(post: PostForRanking): number {
  const ageInHours = (Date.now() - new Date(post.created_at).getTime()) / (1000 * 60 * 60);

  if (ageInHours === 0 || post.view_count === 0) return 0;

  // Saves are weighted 3x more than likes
  const engagementScore = post.save_count * 3 + post.like_count;

  // Engagement rate (relative to views)
  const engagementRate = engagementScore / Math.max(post.view_count, 1);

  // Calm velocity = steady engagement over time (not spiky)
  // Using logarithmic scaling to prevent runaway viral effects
  const velocity = Math.log1p(engagementRate * 100) / Math.log1p(ageInHours + 1);

  return velocity;
}

/**
 * Calculate safety score
 * Lower score = content has triggered negative signals
 */
function calculateSafetyScore(post: PostForRanking): number {
  let score = 1.0;

  // Penalize if blocks received in last 24h
  if (post.blocks_received_24h > 0) {
    score -= post.blocks_received_24h * 0.2;
  }

  // Penalize trusted reports heavily
  if (post.trusted_reports > 0) {
    score -= post.trusted_reports * 0.3;
  }

  // Ignore report spikes if CIS is high (brigading protection)
  if (post.cis_score < 0.7 && post.total_reports > 2) {
    score -= 0.15;
  }

  return Math.max(score, 0);
}

/**
 * Calculate author influence multiplier
 * Based on harmony score and tier
 */
function calculateAuthorInfluence(post: PostForRanking): number {
  const harmonyMultiplier = post.author_harmony_score / 100; // 0-1 range

  const tierMultiplier: Record<string, number> = {
    new: 0.5,
    trusted: 1.0,
    established: 1.3,
    restricted: 0.2,
  };

  return harmonyMultiplier * (tierMultiplier[post.author_tier] || 1.0);
}

/**
 * Calculate final ranking score for sojorn feed
 */
export function calculateRankingScore(post: PostForRanking): number {
  // Base score from content integrity
  const cisBonus = post.cis_score;

  // Tone eligibility (handled in feed query, but can boost here)
  const toneBonus = post.tone_label === 'positive' ? 1.2 : post.tone_label === 'neutral' ? 1.0 : 0.8;

  // Calm velocity (steady appreciation)
  const velocity = calculateCalmVelocity(post);

  // Safety (no blocks or trusted reports)
  const safety = calculateSafetyScore(post);

  // Author influence
  const influence = calculateAuthorInfluence(post);

  // Final score
  const score = cisBonus * toneBonus * velocity * safety * influence;

  return score;
}

/**
 * Rank posts for feed
 * Returns sorted array with scores attached
 */
export function rankPosts(posts: PostForRanking[]): Array<PostForRanking & { rank_score: number }> {
  return posts
    .map((post) => ({
      ...post,
      rank_score: calculateRankingScore(post),
    }))
    .sort((a, b) => b.rank_score - a.rank_score);
}
