/**
 * Referee impact signal.
 *
 * Game-day ref assignments live in `game_ref_assignments` (migration 017).
 * Per-referee tendencies live in `ref_profiles`, populated by the
 * Sports-Reference scraper (scripts/scrape-sports-reference.js).
 *
 * Crew impact is computed by averaging the three refs' profiles. If any
 * profile is missing we still return a partial impact (averaging only the
 * available refs) — the feature cache decides whether to surface the
 * feature or omit it based on coverage.
 */

const { getSupabaseServiceClient } = require('../../utils/supabase');

const LOOPBACK_IPS = new Set(['127.0.0.1', '::1', '::ffff:127.0.0.1']);

async function getRefAssignment(gameId) {
  const supabase = getSupabaseServiceClient();
  const { data, error } = await supabase
    .from('game_ref_assignments')
    .select('ref1_name, ref2_name, ref3_name, ref_crew_avg_fouls, ref_crew_pace_impact')
    .eq('game_id', gameId)
    .maybeSingle();
  if (error) {
    console.warn('[refSignals] assignment lookup failed:', error.message);
    return null;
  }
  return data || null;
}

async function getRefProfiles(refNames) {
  const named = refNames.filter(Boolean);
  if (named.length === 0) return [];
  const supabase = getSupabaseServiceClient();
  const { data, error } = await supabase
    .from('ref_profiles')
    .select('ref_name, avg_fouls_per_game, avg_free_throws_per_game, pace_impact, home_whistle_bias')
    .in('ref_name', named);
  if (error) {
    console.warn('[refSignals] profile lookup failed:', error.message);
    return [];
  }
  return data || [];
}

function average(values) {
  const clean = values.filter((v) => Number.isFinite(v));
  if (clean.length === 0) return null;
  return clean.reduce((a, b) => a + b, 0) / clean.length;
}

async function getRefImpact(gameId) {
  const assignment = await getRefAssignment(gameId);
  if (!assignment) return null;
  const crew = [assignment.ref1_name, assignment.ref2_name, assignment.ref3_name].filter(Boolean);
  if (crew.length === 0) return null;

  // If precomputed crew values exist on the assignment row (scraper wrote
  // them), prefer those — they were derived from the same profiles but
  // baked at assignment time. Note: Number(null) === 0 is finite, so guard
  // explicitly against null/undefined before going through Number().
  const hasFouls = assignment.ref_crew_avg_fouls != null && Number.isFinite(Number(assignment.ref_crew_avg_fouls));
  const hasPace = assignment.ref_crew_pace_impact != null && Number.isFinite(Number(assignment.ref_crew_pace_impact));
  if (hasFouls || hasPace) {
    return {
      crew,
      avg_fouls: assignment.ref_crew_avg_fouls,
      pace_impact: assignment.ref_crew_pace_impact,
      foul_adjustment: assignment.ref_crew_avg_fouls,
      home_bias: null,
      profilesUsed: crew.length,
    };
  }

  const profiles = await getRefProfiles(crew);
  return {
    crew,
    avg_fouls: average(profiles.map((p) => p.avg_fouls_per_game)),
    pace_impact: average(profiles.map((p) => p.pace_impact)),
    foul_adjustment: average(profiles.map((p) => p.avg_free_throws_per_game)),
    home_bias: average(profiles.map((p) => p.home_whistle_bias)),
    profilesUsed: profiles.length,
  };
}

// Manual entry endpoint helper — the route module (not built here) calls
// this when ops POSTs an assignment.
async function setRefAssignment(gameId, sport, gameDate, refs) {
  const supabase = getSupabaseServiceClient();
  // Pull profiles synchronously to precompute crew impact at insert time so
  // downstream reads don't need a join.
  const profiles = await getRefProfiles(refs);
  const avgFouls = average(profiles.map((p) => p.avg_fouls_per_game));
  const paceImpact = average(profiles.map((p) => p.pace_impact));
  const { error } = await supabase
    .from('game_ref_assignments')
    .upsert({
      game_id: gameId,
      sport,
      game_date: gameDate,
      ref1_name: refs[0] || null,
      ref2_name: refs[1] || null,
      ref3_name: refs[2] || null,
      ref_crew_avg_fouls: avgFouls,
      ref_crew_pace_impact: paceImpact,
    }, { onConflict: 'game_id' });
  if (error) {
    console.warn('[refSignals] assignment upsert failed:', error.message);
    return { ok: false, error: error.message };
  }
  return { ok: true, avg_fouls: avgFouls, pace_impact: paceImpact };
}

module.exports = { getRefImpact, getRefAssignment, getRefProfiles, setRefAssignment, LOOPBACK_IPS };
