/**
 * News Scout Pipeline — Phase 3: Score & Rank
 *
 * Composite scoring: engagementScore + recencyBoost + credibility weight
 * Cross-source confirmation: stories from 2+ unique sources get boosted
 * Celebrity extraction via dictionary + heuristic
 * Auto-flags: top 3 → is_featured, score > 5000 → is_breaking
 */

import pool from '../../db';
import { ScoutCandidate } from './types';

// ~200 top athlete/celebrity names that frequently appear at sporting events
const CELEBRITY_DICTIONARY: Record<string, { sport: string; role: string }> = {
  // NFL
  'Patrick Mahomes': { sport: 'nfl', role: 'player' },
  'Travis Kelce': { sport: 'nfl', role: 'player' },
  'Josh Allen': { sport: 'nfl', role: 'player' },
  'Lamar Jackson': { sport: 'nfl', role: 'player' },
  'Jalen Hurts': { sport: 'nfl', role: 'player' },
  'Joe Burrow': { sport: 'nfl', role: 'player' },
  'Justin Jefferson': { sport: 'nfl', role: 'player' },
  'Tyreek Hill': { sport: 'nfl', role: 'player' },
  'Saquon Barkley': { sport: 'nfl', role: 'player' },
  'Derrick Henry': { sport: 'nfl', role: 'player' },
  'CeeDee Lamb': { sport: 'nfl', role: 'player' },
  'Ja\'Marr Chase': { sport: 'nfl', role: 'player' },
  'Dak Prescott': { sport: 'nfl', role: 'player' },
  'Aaron Rodgers': { sport: 'nfl', role: 'player' },
  'Tua Tagovailoa': { sport: 'nfl', role: 'player' },
  'Brock Purdy': { sport: 'nfl', role: 'player' },
  'Micah Parsons': { sport: 'nfl', role: 'player' },
  'Nick Bosa': { sport: 'nfl', role: 'player' },
  'TJ Watt': { sport: 'nfl', role: 'player' },
  'Davante Adams': { sport: 'nfl', role: 'player' },
  // NBA
  'LeBron James': { sport: 'nba', role: 'player' },
  'Stephen Curry': { sport: 'nba', role: 'player' },
  'Kevin Durant': { sport: 'nba', role: 'player' },
  'Giannis Antetokounmpo': { sport: 'nba', role: 'player' },
  'Luka Doncic': { sport: 'nba', role: 'player' },
  'Jayson Tatum': { sport: 'nba', role: 'player' },
  'Nikola Jokic': { sport: 'nba', role: 'player' },
  'Joel Embiid': { sport: 'nba', role: 'player' },
  'Anthony Edwards': { sport: 'nba', role: 'player' },
  'Shai Gilgeous-Alexander': { sport: 'nba', role: 'player' },
  'Victor Wembanyama': { sport: 'nba', role: 'player' },
  'Ja Morant': { sport: 'nba', role: 'player' },
  'Damian Lillard': { sport: 'nba', role: 'player' },
  'James Harden': { sport: 'nba', role: 'player' },
  'Anthony Davis': { sport: 'nba', role: 'player' },
  'Trae Young': { sport: 'nba', role: 'player' },
  'Devin Booker': { sport: 'nba', role: 'player' },
  'Kyrie Irving': { sport: 'nba', role: 'player' },
  'Paul George': { sport: 'nba', role: 'player' },
  'Kawhi Leonard': { sport: 'nba', role: 'player' },
  // MLB
  'Shohei Ohtani': { sport: 'mlb', role: 'player' },
  'Mike Trout': { sport: 'mlb', role: 'player' },
  'Aaron Judge': { sport: 'mlb', role: 'player' },
  'Mookie Betts': { sport: 'mlb', role: 'player' },
  'Ronald Acuna Jr': { sport: 'mlb', role: 'player' },
  'Freddie Freeman': { sport: 'mlb', role: 'player' },
  'Bryce Harper': { sport: 'mlb', role: 'player' },
  'Juan Soto': { sport: 'mlb', role: 'player' },
  'Trea Turner': { sport: 'mlb', role: 'player' },
  'Corbin Burnes': { sport: 'mlb', role: 'player' },
  'Gerrit Cole': { sport: 'mlb', role: 'player' },
  'Corey Seager': { sport: 'mlb', role: 'player' },
  'Yoshinobu Yamamoto': { sport: 'mlb', role: 'player' },
  'Bobby Witt Jr': { sport: 'mlb', role: 'player' },
  // NHL
  'Connor McDavid': { sport: 'nhl', role: 'player' },
  'Nathan MacKinnon': { sport: 'nhl', role: 'player' },
  'Auston Matthews': { sport: 'nhl', role: 'player' },
  'Leon Draisaitl': { sport: 'nhl', role: 'player' },
  'Cale Makar': { sport: 'nhl', role: 'player' },
  'Nikita Kucherov': { sport: 'nhl', role: 'player' },
  'David Pastrnak': { sport: 'nhl', role: 'player' },
  'Sidney Crosby': { sport: 'nhl', role: 'player' },
  'Alex Ovechkin': { sport: 'nhl', role: 'player' },
  'Igor Shesterkin': { sport: 'nhl', role: 'player' },
  'Connor Bedard': { sport: 'nhl', role: 'player' },
  // Soccer
  'Lionel Messi': { sport: 'soccer', role: 'player' },
  'Cristiano Ronaldo': { sport: 'soccer', role: 'player' },
  'Kylian Mbappe': { sport: 'soccer', role: 'player' },
  'Erling Haaland': { sport: 'soccer', role: 'player' },
  'Jude Bellingham': { sport: 'soccer', role: 'player' },
  'Vinicius Jr': { sport: 'soccer', role: 'player' },
  'Mohamed Salah': { sport: 'soccer', role: 'player' },
  'Bukayo Saka': { sport: 'soccer', role: 'player' },
  'Harry Kane': { sport: 'soccer', role: 'player' },
  'Cole Palmer': { sport: 'soccer', role: 'player' },
  // MMA
  'Jon Jones': { sport: 'mma', role: 'fighter' },
  'Alex Pereira': { sport: 'mma', role: 'fighter' },
  'Islam Makhachev': { sport: 'mma', role: 'fighter' },
  'Conor McGregor': { sport: 'mma', role: 'fighter' },
  'Sean O\'Malley': { sport: 'mma', role: 'fighter' },
  'Ilia Topuria': { sport: 'mma', role: 'fighter' },
  'Dana White': { sport: 'mma', role: 'executive' },
  // Celebrities (courtside regulars)
  'Drake': { sport: 'nba', role: 'celebrity' },
  'Jay-Z': { sport: 'nba', role: 'celebrity' },
  'Beyonce': { sport: 'nfl', role: 'celebrity' },
  'Taylor Swift': { sport: 'nfl', role: 'celebrity' },
  'Jack Nicholson': { sport: 'nba', role: 'celebrity' },
  'Spike Lee': { sport: 'nba', role: 'celebrity' },
  'Bad Bunny': { sport: 'mma', role: 'celebrity' },
  'Rihanna': { sport: 'nfl', role: 'celebrity' },
  'Kim Kardashian': { sport: 'nba', role: 'celebrity' },
  'Travis Scott': { sport: 'nba', role: 'celebrity' },
  // Coaches / Executives
  'Andy Reid': { sport: 'nfl', role: 'coach' },
  'Bill Belichick': { sport: 'nfl', role: 'coach' },
  'Nick Saban': { sport: 'ncaaf', role: 'coach' },
  'Adam Silver': { sport: 'nba', role: 'executive' },
  'Roger Goodell': { sport: 'nfl', role: 'executive' },
  'Rob Manfred': { sport: 'mlb', role: 'executive' },
};

// Source credibility multipliers — applied to engagement score
const SOURCE_CREDIBILITY: Record<string, number> = {
  // Tier 1: Major wire services and sports networks
  espn: 1.5,
  apnews: 1.5,
  cbssports: 1.4,
  nbcsports: 1.4,
  // Tier 2: Established outlets
  bbc: 1.3,
  guardian: 1.3,
  yahoo: 1.2,
  foxsports: 1.2,
  skysports: 1.2,
  usatoday: 1.2,
  // Tier 3: Sports-specific outlets
  bleacherreport: 1.1,
  sbnation: 1.1,
  theringer: 1.0,
  sportingnews: 1.0,
  // Social / aggregator
  twitter: 1.1,
  reddit: 1.0,
};

// Default credibility for Google News (meta-aggregator) and unknown sources
const GNEWS_CREDIBILITY = 0.8;
const DEFAULT_CREDIBILITY = 1.0;

// Cross-source confirmation boost per additional source
const CROSS_SOURCE_BOOST = 300;

/**
 * Normalize a title for cross-source matching.
 * Lowercase, strip punctuation, take first 60 chars.
 */
function normalizeTitle(title: string): string {
  return title
    .toLowerCase()
    .replace(/[^a-z0-9\s]/g, '')
    .trim()
    .slice(0, 60);
}

/**
 * Apply cross-source confirmation boosts.
 * Groups candidates by normalized title and boosts stories appearing in 2+ unique sources.
 */
function applyCrossSourceBoosts(candidates: ScoutCandidate[]): number {
  const titleGroups = new Map<string, ScoutCandidate[]>();

  for (const c of candidates) {
    const normalized = normalizeTitle(c.title);
    if (normalized.length < 15) continue; // skip very short titles
    const existing = titleGroups.get(normalized);
    if (existing) {
      existing.push(c);
    } else {
      titleGroups.set(normalized, [c]);
    }
  }

  let boostedCount = 0;
  for (const [, group] of titleGroups) {
    // Count unique sources in this group
    const uniqueSources = new Set(group.map(c => c.source));
    if (uniqueSources.size < 2) continue;

    const boost = (uniqueSources.size - 1) * CROSS_SOURCE_BOOST;
    for (const c of group) {
      c.engagementScore += boost;
    }
    boostedCount += group.length;
  }

  return boostedCount;
}

function getCredibility(candidate: ScoutCandidate): number {
  if (candidate.sourceType === 'gnews') return GNEWS_CREDIBILITY;
  return SOURCE_CREDIBILITY[candidate.source] ?? DEFAULT_CREDIBILITY;
}

function extractCelebrities(text: string): string[] {
  const found: string[] = [];
  const textLower = text.toLowerCase();

  for (const name of Object.keys(CELEBRITY_DICTIONARY)) {
    if (textLower.includes(name.toLowerCase())) {
      found.push(name);
    }
  }

  return [...new Set(found)];
}

export async function runTrendingScorer(candidates: ScoutCandidate[]): Promise<ScoutCandidate[]> {
  const now = Date.now();

  // Score each candidate with credibility weight
  for (const c of candidates) {
    const hoursOld = Math.max((now - c.publishedAt.getTime()) / 3600000, 0.5);
    const recencyBoost = 500 / hoursOld;
    const credibility = getCredibility(c);
    c.engagementScore = (c.engagementScore + recencyBoost) * credibility;

    // Celebrity extraction
    const celebs = extractCelebrities(`${c.title} ${c.description}`);
    if (celebs.length > 0) {
      c.celebrityNames = celebs;
      // Bonus for celebrity mentions
      c.engagementScore += celebs.length * 200;
    }
  }

  // Cross-source confirmation boost
  const crossSourceBoosted = applyCrossSourceBoosts(candidates);
  if (crossSourceBoosted > 0) {
    console.log(`  [trending-scorer] Cross-source boost applied to ${crossSourceBoosted} items`);
  }

  // Sort by engagement score descending
  candidates.sort((a, b) => b.engagementScore - a.engagementScore);

  // Auto-flag: top 3 → is_featured, score > 5000 → is_breaking
  for (let i = 0; i < candidates.length; i++) {
    if (i < 3) candidates[i].isFeatured = true;
    if (candidates[i].engagementScore > 5000) candidates[i].isBreaking = true;
  }

  // Upsert celebrities into rm_celebrity_tracker
  const allCelebs = new Map<string, { sport: string; role: string; engagement: number }>();
  for (const c of candidates) {
    if (!c.celebrityNames) continue;
    for (const name of c.celebrityNames) {
      const info = CELEBRITY_DICTIONARY[name];
      if (!info) continue;
      const existing = allCelebs.get(name);
      if (existing) {
        existing.engagement = Math.max(existing.engagement, c.engagementScore);
      } else {
        allCelebs.set(name, { sport: info.sport, role: info.role, engagement: c.engagementScore });
      }
    }
  }

  for (const [name, info] of allCelebs) {
    try {
      await pool.query(
        `INSERT INTO rm_celebrity_tracker (name, sport, role, mention_count, last_engagement, last_seen_at)
         VALUES ($1, $2, $3, 1, $4, NOW())
         ON CONFLICT (name, sport) DO UPDATE SET
           mention_count = rm_celebrity_tracker.mention_count + 1,
           last_engagement = GREATEST(rm_celebrity_tracker.last_engagement, $4),
           last_seen_at = NOW()`,
        [name, info.sport, info.role, info.engagement]
      );
    } catch (err: any) {
      // Non-fatal — skip celebrity upsert errors
    }
  }

  console.log(`[trending-scorer] Scored ${candidates.length} candidates, ${allCelebs.size} celebrities tracked`);
  return candidates;
}
