import { poissonPmf, type OutcomeProbs } from './poisson';

// In-play win probability. Given each side's pre-match goal expectation, the
// current score, and the minute, the remaining goals are modelled as independent
// Poisson processes scaled to the time left — convolved with the current score to
// give live win/draw/loss. Cheap enough to recompute on every tick.

const REG_MINUTES = 90;
const MAX_GOALS = 12;

export function inPlayProbs(
  lambdaHome: number,
  lambdaAway: number,
  minute: number,
  scoreHome: number,
  scoreAway: number,
): OutcomeProbs {
  const remaining = Math.max(0, Math.min(1, (REG_MINUTES - minute) / REG_MINUTES));

  if (remaining <= 0) {
    if (scoreHome > scoreAway) return { home: 1, draw: 0, away: 0 };
    if (scoreHome < scoreAway) return { home: 0, draw: 0, away: 1 };
    return { home: 0, draw: 1, away: 0 };
  }

  const lh = lambdaHome * remaining;
  const la = lambdaAway * remaining;
  const ph = Array.from({ length: MAX_GOALS + 1 }, (_, k) => poissonPmf(lh, k));
  const pa = Array.from({ length: MAX_GOALS + 1 }, (_, k) => poissonPmf(la, k));

  let home = 0, draw = 0, away = 0;
  for (let i = 0; i <= MAX_GOALS; i++) {
    for (let j = 0; j <= MAX_GOALS; j++) {
      const p = ph[i]! * pa[j]!;
      const fh = scoreHome + i;
      const fa = scoreAway + j;
      if (fh > fa) home += p;
      else if (fh < fa) away += p;
      else draw += p;
    }
  }
  const total = home + draw + away;
  return { home: home / total, draw: draw / total, away: away / total };
}
