const SHARP_BOOKS = ['pinnacle', 'circa', 'bookmaker'];
const SQUARE_BOOKS = ['draftkings', 'fanduel', 'betmgm', 'caesars', 'fanatics', 'bet365'];

/**
 * Detect discrepancy between sharp and square book consensus lines.
 * @param {Array<{book: string, line: number}>} propLines
 * @returns {object} { discrepancy, gap, sharp_consensus, square_consensus }
 */
function detectDiscrepancy(propLines) {
  if (!propLines || propLines.length === 0) {
    return { discrepancy: false, gap: 0, sharp_consensus: null, square_consensus: null };
  }

  const sharpLines = propLines.filter(p => SHARP_BOOKS.includes(p.book.toLowerCase()));
  const squareLines = propLines.filter(p => SQUARE_BOOKS.includes(p.book.toLowerCase()));

  if (sharpLines.length === 0 || squareLines.length === 0) {
    return { discrepancy: false, gap: 0, sharp_consensus: null, square_consensus: null };
  }

  const sharpConsensus = sharpLines.reduce((s, p) => s + p.line, 0) / sharpLines.length;
  const squareConsensus = squareLines.reduce((s, p) => s + p.line, 0) / squareLines.length;
  const gap = Math.abs(sharpConsensus - squareConsensus);

  return {
    discrepancy: gap > 0.5,
    gap: Math.round(gap * 100) / 100,
    sharp_consensus: Math.round(sharpConsensus * 100) / 100,
    square_consensus: Math.round(squareConsensus * 100) / 100,
    sharp_books_used: sharpLines.length,
    square_books_used: squareLines.length,
  };
}

/**
 * Detect steam move: 0.5+ movement at 3+ books within 10 minutes.
 * @param {Array<{book: string, line: number, timestamp: string}>} movements
 * @returns {object} { steam_move, books_moved, magnitude, window_minutes }
 */
function detectSteamMove(movements) {
  if (!movements || movements.length < 3) {
    return { steam_move: false, books_moved: 0, magnitude: 0, window_minutes: 0 };
  }

  const sorted = [...movements].sort((a, b) => new Date(a.timestamp) - new Date(b.timestamp));
  const windowMs = 10 * 60 * 1000; // 10 minutes

  for (let i = 0; i < sorted.length; i++) {
    const windowStart = new Date(sorted[i].timestamp).getTime();
    const windowEnd = windowStart + windowMs;

    const inWindow = sorted.filter(m => {
      const t = new Date(m.timestamp).getTime();
      return t >= windowStart && t <= windowEnd;
    });

    // Group by book, find those with 0.5+ movement
    const bookMovements = {};
    for (const m of inWindow) {
      if (!bookMovements[m.book]) bookMovements[m.book] = [];
      bookMovements[m.book].push(m.line);
    }

    const significantMoves = Object.entries(bookMovements).filter(([_, lines]) => {
      if (lines.length < 2) return false;
      const range = Math.max(...lines) - Math.min(...lines);
      return range >= 0.5;
    });

    // Also count books that appear with already-moved lines (single entry with magnitude info)
    const booksWithMovement = inWindow.filter(m => Math.abs(m.line) >= 0.5);
    const uniqueBooks = new Set(booksWithMovement.map(m => m.book));

    if (uniqueBooks.size >= 3 || significantMoves.length >= 3) {
      const allMagnitudes = booksWithMovement.map(m => Math.abs(m.line));
      return {
        steam_move: true,
        books_moved: Math.max(uniqueBooks.size, significantMoves.length),
        magnitude: Math.round((allMagnitudes.reduce((s, v) => s + v, 0) / allMagnitudes.length) * 100) / 100,
        window_minutes: 10,
      };
    }
  }

  return { steam_move: false, books_moved: 0, magnitude: 0, window_minutes: 0 };
}

/**
 * Get reliability score for a prop type in a sport from historical accuracy.
 * @param {string} propType
 * @param {string} sport
 * @returns {number} Reliability score 0-1
 */
function getReliabilityScore(propType, sport) {
  const reliabilityMap = {
    nba: {
      points: 0.72,
      rebounds: 0.65,
      assists: 0.68,
      threes: 0.60,
      steals: 0.45,
      blocks: 0.42,
      pts_rebs_asts: 0.70,
    },
    mlb: {
      hits: 0.55,
      home_runs: 0.40,
      rbis: 0.48,
      stolen_bases: 0.52,
      strikeouts_pitcher: 0.65,
      earned_runs: 0.58,
      total_bases: 0.53,
    },
  };

  const sportMap = reliabilityMap[sport.toLowerCase()];
  if (!sportMap) return 0.50; // default
  return sportMap[propType.toLowerCase()] || 0.50;
}

module.exports = {
  SHARP_BOOKS,
  SQUARE_BOOKS,
  detectDiscrepancy,
  detectSteamMove,
  getReliabilityScore,
};
