'use strict';

/**
 * Value engine config (Model Train, steps 3-4).
 *
 * Product doctrine (Kev): VYNDR PROMOTES bets people actually take — roughly the
 * -160 to +200 band — that ALSO carry a genuine vig-free edge. Not
 * plus-money-only, not heavy chalk.
 *
 * The TAKEABLE gate applies to PROMOTED surfaces only (daily hero, featured /
 * top-of-board, future alerts). The full board still shows every graded read.
 * Parlay Lab is EXEMPT (juiced legs combine into takeable payouts).
 * JUICE_ODDS_FLOOR (-400, in rareEventMarkets) stays the absolute refusal
 * backstop UNDERNEATH this — those reads are never graded at all.
 *
 * All thresholds are env-tunable.
 */

// The promotable price band. Ceiling = most-juiced favorite we'll promote;
// max = longest dog we'll promote.
const TAKEABLE_ODDS_CEILING = Number(process.env.TAKEABLE_ODDS_CEILING || -160);
const TAKEABLE_ODDS_MAX = Number(process.env.TAKEABLE_ODDS_MAX || 200);

// A read is VALUE only when its EV clears this (a real edge, not rounding).
const VALUE_EV_THRESHOLD = Number(process.env.VALUE_EV_THRESHOLD || 2);

/** Is an American price inside the takeable band (default -160..+200)?
 *  Strict on input — null/''/undefined are NOT takeable (Number(null) === 0
 *  would otherwise land a missing price inside the band). */
function isTakeable(american) {
  if (american == null || american === '') return false;
  const a = Number(american);
  if (!Number.isFinite(a)) return false;
  return a >= TAKEABLE_ODDS_CEILING && a <= TAKEABLE_ODDS_MAX;
}

/** A read carries VALUE when it's takeable AND its EV clears the threshold —
 *  "the price pays you to take it", distinct from grade ("read quality"). */
function isValue(american, evPct) {
  return isTakeable(american) && Number.isFinite(evPct) && evPct >= VALUE_EV_THRESHOLD;
}

module.exports = {
  TAKEABLE_ODDS_CEILING,
  TAKEABLE_ODDS_MAX,
  VALUE_EV_THRESHOLD,
  isTakeable,
  isValue,
};
