/**
 * Material Change Detection — compares pre/post refresh state to detect
 * significant line movements or confidence shifts that warrant a "GAME CHANGER" banner.
 */

import { MATERIAL_THRESHOLDS } from '../lib/scheduler-config';

interface ChangeItem {
  type: string;
  market?: string;
  old: number;
  new: number;
  delta: number;
}

export interface MaterialChangeResult {
  isMaterial: boolean;
  changes: ChangeItem[];
  bannerText: string | null;
}

function extractSpreadLine(odds: any): number | null {
  if (!odds?.spread) return null;
  const home = odds.spread.home?.line ?? odds.spread.home;
  if (typeof home === 'number') return home;
  return null;
}

function extractTotalLine(odds: any): number | null {
  if (!odds?.total) return null;
  const over = odds.total.over?.line ?? odds.total.over;
  if (typeof over === 'number') return over;
  return null;
}

function extractMoneyline(odds: any, side: 'home' | 'away'): number | null {
  if (!odds?.moneyline) return null;
  const val = odds.moneyline[side];
  if (typeof val === 'number') return val;
  return null;
}

/**
 * Detect material changes between pre-refresh and post-refresh states.
 */
export function detectMaterialChange(params: {
  preOdds: any;
  postOdds: any;
  preConfidence: number;
  postConfidence: number;
}): MaterialChangeResult {
  const { preOdds, postOdds, preConfidence, postConfidence } = params;
  const changes: ChangeItem[] = [];

  // Spread movement
  const preSpread = extractSpreadLine(preOdds);
  const postSpread = extractSpreadLine(postOdds);
  if (preSpread != null && postSpread != null) {
    const delta = Math.abs(postSpread - preSpread);
    if (delta >= MATERIAL_THRESHOLDS.spread_movement) {
      changes.push({ type: 'line_movement', market: 'spread', old: preSpread, new: postSpread, delta });
    }
  }

  // Total movement
  const preTotal = extractTotalLine(preOdds);
  const postTotal = extractTotalLine(postOdds);
  if (preTotal != null && postTotal != null) {
    const delta = Math.abs(postTotal - preTotal);
    if (delta >= MATERIAL_THRESHOLDS.total_movement) {
      changes.push({ type: 'line_movement', market: 'total', old: preTotal, new: postTotal, delta });
    }
  }

  // Moneyline movement (check both sides, report the larger)
  for (const side of ['home', 'away'] as const) {
    const preMl = extractMoneyline(preOdds, side);
    const postMl = extractMoneyline(postOdds, side);
    if (preMl != null && postMl != null) {
      const delta = Math.abs(postMl - preMl);
      if (delta >= MATERIAL_THRESHOLDS.moneyline_movement) {
        changes.push({ type: 'line_movement', market: `moneyline_${side}`, old: preMl, new: postMl, delta });
      }
    }
  }

  // Confidence shift
  const confDelta = Math.abs(postConfidence - preConfidence);
  if (confDelta >= MATERIAL_THRESHOLDS.confidence_shift) {
    changes.push({
      type: 'confidence_shift',
      old: Math.round(preConfidence * 100),
      new: Math.round(postConfidence * 100),
      delta: Math.round(confDelta * 100),
    });
  }

  if (changes.length === 0) {
    return { isMaterial: false, changes: [], bannerText: null };
  }

  // Build human-readable banner text from most impactful change
  const bannerText = buildBannerText(changes);

  return { isMaterial: true, changes, bannerText };
}

function formatLine(val: number): string {
  return val > 0 ? `+${val}` : `${val}`;
}

function buildBannerText(changes: ChangeItem[]): string {
  const parts: string[] = [];

  for (const c of changes) {
    if (c.type === 'line_movement' && c.market === 'spread') {
      parts.push(`Spread moved ${c.delta} points (${formatLine(c.old)} → ${formatLine(c.new)})`);
    } else if (c.type === 'line_movement' && c.market === 'total') {
      parts.push(`Total moved ${c.delta} points (${c.old} → ${c.new})`);
    } else if (c.type === 'line_movement' && c.market?.startsWith('moneyline')) {
      const side = c.market === 'moneyline_home' ? 'Home' : 'Away';
      parts.push(`${side} ML shifted ${Math.round(c.delta)} (${formatLine(c.old)} → ${formatLine(c.new)})`);
    } else if (c.type === 'confidence_shift') {
      parts.push(`Forecast confidence shifted ${c.delta}% (${c.old}% → ${c.new}%)`);
    }
  }

  return parts.join(' | ');
}
