const { getSupabaseServiceClient } = require('../utils/supabase');
const { getRedisClient } = require('../utils/redis');
const { gradeParlayFromLegs } = require('./parlayGrader');

function getToday() {
  return new Date().toISOString().split('T')[0];
}

async function detectScratches(sport, currentProps) {
  const redis = getRedisClient();
  const today = getToday();
  const playerSetKey = `odds:players:${sport}:${today}`;

  // Build current player set (players with props from 2+ books)
  const playerBooks = {};
  for (const prop of currentProps) {
    if (!playerBooks[prop.player]) playerBooks[prop.player] = new Set();
    playerBooks[prop.player].add(prop.book);
  }

  const currentPlayers = new Set();
  for (const [player, books] of Object.entries(playerBooks)) {
    if (books.size >= 2) currentPlayers.add(player);
  }

  // Get previous player set
  const prevPlayersRaw = await redis.get(playerSetKey);
  const prevPlayers = prevPlayersRaw ? new Set(JSON.parse(prevPlayersRaw)) : null;

  // Store current set for next comparison
  await redis.set(playerSetKey, JSON.stringify([...currentPlayers]), 'EX', 86400);

  if (!prevPlayers) {
    // First fetch — no comparison possible
    return { scratchedPlayers: [] };
  }

  // Find players who disappeared (were in prev but not in current)
  const scratched = [];
  for (const player of prevPlayers) {
    if (!currentPlayers.has(player)) {
      scratched.push(player);
    }
  }

  if (scratched.length > 0) {
    await processScratches(scratched);
  }

  return { scratchedPlayers: scratched };
}

async function processScratches(scratchedPlayers) {
  const supabase = getSupabaseServiceClient();
  const today = getToday();

  for (const player of scratchedPlayers) {
    // Find scan sessions from today that include this player
    const { data: picks } = await supabase
      .from('picks')
      .select('id, user_id, player, stat_type, grade, confidence')
      .eq('player', player)
      .gte('created_at', `${today}T00:00:00Z`);

    if (!picks || picks.length === 0) continue;

    // Find unique sessions containing these picks
    const affectedUserIds = [...new Set(picks.map((p) => p.user_id))];

    for (const userId of affectedUserIds) {
      // Find the user's scan sessions from today
      const { data: sessions } = await supabase
        .from('scan_sessions')
        .select('id, legs, final_grade')
        .eq('user_id', userId)
        .gte('created_at', `${today}T00:00:00Z`);

      if (!sessions) continue;

      for (const session of sessions) {
        // Check if any of the scratched player's picks are in this session
        const scratchedPickIds = picks
          .filter((p) => p.user_id === userId)
          .map((p) => p.id);

        const sessionLegs = session.legs || [];
        const affectedLegIds = sessionLegs.filter((legId) =>
          scratchedPickIds.includes(legId)
        );

        if (affectedLegIds.length === 0) continue;

        // Re-grade without the scratched legs
        const remainingLegIds = sessionLegs.filter((legId) =>
          !affectedLegIds.includes(legId)
        );

        let regradeDetail;
        if (remainingLegIds.length < 2) {
          regradeDetail = `${player} scratched. Your parlay has only ${remainingLegIds.length} leg(s) remaining — cannot be graded as a parlay.`;
        } else {
          // Fetch remaining picks for re-grading
          const { data: remainingPicks } = await supabase
            .from('picks')
            .select('grade, confidence')
            .in('id', remainingLegIds);

          if (remainingPicks && remainingPicks.length >= 2) {
            const mockLegs = remainingPicks.map((p) => ({
              grade: p.grade,
              confidence: p.confidence,
              _composite: p.grade === 'A' ? 3.5 : p.grade === 'B' ? 2.0 : p.grade === 'C' ? 0.8 : 0.1,
            }));
            const { grade: newGrade } = gradeParlayFromLegs(mockLegs, []);
            regradeDetail = `${player} scratched. Your ${sessionLegs.length}-leg parlay regraded from ${session.final_grade} to ${newGrade} without this leg.`;
          } else {
            regradeDetail = `${player} scratched. Your parlay may be affected — check with your sportsbook.`;
          }
        }

        // Create alert
        await supabase.from('cascade_alerts').insert({
          user_id: userId,
          alert_type: 'player_scratched',
          scan_session_id: session.id,
          player,
          detail: regradeDetail,
        });
      }
    }
  }
}

module.exports = { detectScratches, processScratches };
