const { getSupabaseServiceClient } = require('../utils/supabase');
const { calculatePayout } = require('./payoutCalculator');
const { recalculatePerformance } = require('./performanceService');

async function createBet(userId, { legs, amount, book, bet_type, scan_session_id, placed_at }) {
  const supabase = getSupabaseServiceClient();

  // Validate scan_session_id if provided
  if (scan_session_id) {
    const { data: session } = await supabase
      .from('scan_sessions')
      .select('id')
      .eq('id', scan_session_id)
      .eq('user_id', userId)
      .single();

    if (!session) {
      const err = new Error('Scan session not found or does not belong to user');
      err.statusCode = 404;
      throw err;
    }
  }

  const legsOdds = legs.map((l) => l.odds).filter((o) => o != null);
  const potentialPayout = calculatePayout(amount, bet_type, legsOdds);

  // Compute total odds for slip_data
  let totalOdds = null;
  if (legsOdds.length === 1) {
    totalOdds = legsOdds[0];
  } else if (legsOdds.length > 1) {
    // Convert to decimal, multiply, convert back to American
    let decimalProduct = 1;
    for (const odds of legsOdds) {
      decimalProduct *= odds < 0 ? 1 + (100 / Math.abs(odds)) : 1 + (odds / 100);
    }
    totalOdds = decimalProduct >= 2
      ? Math.round((decimalProduct - 1) * 100)
      : Math.round(-100 / (decimalProduct - 1));
  }

  const slipData = {
    legs,
    total_odds: totalOdds,
    scan_session_id: scan_session_id || null,
  };

  const { data: bet, error } = await supabase
    .from('bets')
    .insert({
      user_id: userId,
      amount,
      potential_payout: potentialPayout,
      slip_data: slipData,
      book,
      bet_type,
      submission_method: 'quickslip',
      status: 'pending',
      placed_at: placed_at || new Date().toISOString(),
    })
    .select('id, status, amount, potential_payout, bet_type, book, created_at')
    .single();

  if (error) throw error;

  return {
    bet_id: bet.id,
    status: bet.status,
    amount: parseFloat(bet.amount),
    potential_payout: parseFloat(bet.potential_payout),
    bet_type: bet.bet_type,
    book: bet.book,
    legs: legs.length,
    scan_session_id: scan_session_id || null,
    created_at: bet.created_at,
  };
}

async function createBetFromScreenshot(userId, { legs, amount, book, bet_type, scan_session_id }) {
  // Same as quickslip but with submission_method = 'screenshot'
  const supabase = getSupabaseServiceClient();

  if (scan_session_id) {
    const { data: session } = await supabase
      .from('scan_sessions')
      .select('id')
      .eq('id', scan_session_id)
      .eq('user_id', userId)
      .single();

    if (!session) {
      const err = new Error('Scan session not found or does not belong to user');
      err.statusCode = 404;
      throw err;
    }
  }

  const legsOdds = legs.map((l) => l.odds).filter((o) => o != null);
  const potentialPayout = calculatePayout(amount, bet_type, legsOdds);

  const slipData = {
    legs,
    scan_session_id: scan_session_id || null,
  };

  const { data: bet, error } = await supabase
    .from('bets')
    .insert({
      user_id: userId,
      amount,
      potential_payout: potentialPayout,
      slip_data: slipData,
      book,
      bet_type,
      submission_method: 'screenshot',
      status: 'pending',
      placed_at: new Date().toISOString(),
    })
    .select('id, status, amount, potential_payout, bet_type, book, created_at')
    .single();

  if (error) throw error;

  return {
    bet_id: bet.id,
    status: bet.status,
    amount: parseFloat(bet.amount),
    potential_payout: parseFloat(bet.potential_payout),
    bet_type: bet.bet_type,
    book: bet.book,
    legs: legs.length,
    scan_session_id: scan_session_id || null,
    created_at: bet.created_at,
  };
}

async function settleBet(userId, betId, { status, leg_outcomes }) {
  const supabase = getSupabaseServiceClient();

  // Fetch the bet
  const { data: bet, error: fetchError } = await supabase
    .from('bets')
    .select('*')
    .eq('id', betId)
    .eq('user_id', userId)
    .single();

  if (fetchError || !bet) {
    const err = new Error('Bet not found');
    err.statusCode = 404;
    throw err;
  }

  if (bet.status !== 'pending') {
    const err = new Error('Bet already settled');
    err.statusCode = 422;
    throw err;
  }

  // Update bet status
  const settledAt = new Date().toISOString();
  const { error: updateError } = await supabase
    .from('bets')
    .update({ status, settled_at: settledAt })
    .eq('id', betId);

  if (updateError) throw updateError;

  // Calculate profit
  const amount = parseFloat(bet.amount);
  const payout = parseFloat(bet.potential_payout || 0);
  let profit = 0;
  if (status === 'won') profit = payout - amount;
  else if (status === 'lost') profit = -amount;

  // Recalculate performance
  await recalculatePerformance(userId);

  return {
    bet_id: betId,
    status,
    settled_at: settledAt,
    amount,
    potential_payout: payout,
    profit: Math.round(profit * 100) / 100,
  };
}

async function listBets(userId, { status, book, limit = 20, offset = 0 }) {
  const supabase = getSupabaseServiceClient();

  let query = supabase
    .from('bets')
    .select('*', { count: 'exact' })
    .eq('user_id', userId)
    .order('placed_at', { ascending: false })
    .range(offset, offset + limit - 1);

  if (status) query = query.eq('status', status);
  if (book) query = query.eq('book', book);

  const { data: bets, count, error } = await query;
  if (error) throw error;

  return {
    bets: bets || [],
    total: count || 0,
    limit,
    offset,
  };
}

module.exports = { createBet, createBetFromScreenshot, settleBet, listBets };
