/**
 * Scoring primitives (ARCHITECTURE §2.3). All times are server timestamps; the client clock is
 * never an input.
 */
import { POINTS, type Difficulty, type QuestionInput, type Timings } from './types';

export interface SpeedBonusInput {
  /** Server time the question opened (t_open). */
  openedAt: number;
  /** Server receive time of the answer (t_answer). */
  receivedAt: number;
  windowMs: number;
  graceMs: number;
}

const clamp01 = (x: number): number => (x < 0 ? 0 : x > 1 ? 1 : x);

/** round(50 × clamp01(1 − (t_answer − t_open − grace) / (window − grace))). */
export function speedBonus({ openedAt, receivedAt, windowMs, graceMs }: SpeedBonusInput): number {
  const elapsed = receivedAt - openedAt;
  const span = windowMs - graceMs;
  // Degenerate config (grace ≥ window): everything inside the window counts as "inside grace".
  if (span <= 0) return elapsed <= windowMs ? POINTS.SPEED_BONUS_MAX : 0;
  return Math.round(POINTS.SPEED_BONUS_MAX * clamp01(1 - (elapsed - graceMs) / span));
}

export function basePoints(difficulty: Difficulty): number {
  return difficulty === 'DIFFICULT' ? POINTS.CORRECT_DIFFICULT : POINTS.CORRECT_STANDARD;
}

/** Answer window: DIFFICULT questions and the board wildcard get the longer window. */
export function windowFor(question: Pick<QuestionInput, 'difficulty'>, isWildcard: boolean, timings: Timings): number {
  return question.difficulty === 'DIFFICULT' || isWildcard ? timings.difficultWindowMs : timings.windowMs;
}
