/**
 * Middle detection across books.
 *
 * A middle exists when one book has Over X.5 and another has Under Y.5 with
 * X < Y — any actual result in [X+1, Y-1] wins both sides. We only flag
 * middles where VYNDR's projection puts the probability of landing in the
 * middle above 15%.
 */

const { americanToImplied } = require('./LineShoppingEngine');

function approxLandsBetween(projection, lo, hi, sigma = 5) {
  if (projection == null) return null;
  // Crude normal-ish band: pretend sigma is half the typical spread; a real
  // model would use the per-stat empirical distribution from grade_history.
  const cdf = (x) => 0.5 * (1 + Math.tanh((x - projection) / (sigma * 1.2533)));
  return cdf(hi) - cdf(lo);
}

function detect(shoppedProps, { minProbability = 0.15 } = {}) {
  const middles = [];
  for (const group of shoppedProps || []) {
    const rows = group.books || [];
    for (let i = 0; i < rows.length; i++) {
      for (let j = 0; j < rows.length; j++) {
        if (i === j) continue;
        const a = rows[i]; // candidate Over
        const b = rows[j]; // candidate Under
        if (typeof a.line !== 'number' || typeof b.line !== 'number') continue;
        if (a.line >= b.line) continue;
        if (a.odds_over == null || b.odds_under == null) continue;

        const middleLo = a.line + 0.5;
        const middleHi = b.line - 0.5;
        if (middleHi < middleLo) continue;

        const prob = approxLandsBetween(group.projection ?? group.vyndr_projection, middleLo, middleHi);
        if (prob == null) continue;
        if (prob < minProbability) continue;

        middles.push({
          key: group.key,
          over: { book: a.book, line: a.line, odds: a.odds_over, implied: americanToImplied(a.odds_over) },
          under: { book: b.book, line: b.line, odds: b.odds_under, implied: americanToImplied(b.odds_under) },
          window: [middleLo, middleHi],
          probability: prob,
        });
      }
    }
  }
  return middles;
}

module.exports = { detect };
