/**
 * RIE — Base Strategy
 *
 * Abstract base class for sport-specific strategies.
 * Each strategy defines signal weights, RAG queries, and composite adjustments.
 */

import { SignalResult, StrategyProfile, RagInsight } from '../types';

function clamp(val: number, min: number, max: number): number {
  return Math.max(min, Math.min(max, val));
}

export abstract class BaseStrategy {
  abstract league: string;
  abstract getProfile(): StrategyProfile;

  /**
   * Compute composite confidence as a weighted sum of available signals.
   * Redistributes weight from unavailable signals proportionally to available ones.
   */
  computeComposite(signals: SignalResult[]): number {
    const available = signals.filter(s => s.available && s.weight > 0);
    if (available.length === 0) return 0.5;

    const totalWeight = available.reduce((s, sig) => s + sig.weight, 0);
    if (totalWeight === 0) return 0.5;

    // Normalize weights to sum to 1.0
    const composite = available.reduce((s, sig) => s + sig.score * (sig.weight / totalWeight), 0);
    return clamp(composite, 0, 1);
  }

  /**
   * Override point for sport-specific adjustments after base composite.
   * Default: no adjustment.
   */
  adjustComposite(base: number, signals: SignalResult[], ragInsights: RagInsight[]): number {
    return base;
  }

  /**
   * Assign weights from the strategy profile to collected signals.
   */
  assignWeights(signals: SignalResult[]): SignalResult[] {
    const profile = this.getProfile();
    return signals.map(s => ({
      ...s,
      weight: profile.signalWeights[s.signalId] ?? 0,
    }));
  }
}
