// ═══════════════════════════════════════════════════════════════════════════════
// LOOPUMAN — competition_module.js v2
// Changes from v1:
//   - Tiered setup fees ($10/$25/$50 based on prize size)
//   - Location/country support (worldwide or country-restricted)
//   - Social contest bonus = requester picks top 3 (NOT auto-engagement)
//   - Fixed approveChallengeEntry (userId passed directly, no db.getUser)
//   - Prize shown on list buttons
//   - Deep link sharing after competition created
//   - Pending review count on My Competitions
// ═══════════════════════════════════════════════════════════════════════════════

'use strict';

const COMP = {
  // Tiered setup fees based on prize size
  setupFee: (prize) => {
    if (prize < 10000) return 1000;   // under $100 → $10 setup
    if (prize < 50000) return 2500;   // $100-$500 → $25 setup
    return 5000;                       // over $500 → $50 setup
  },
  SETUP_FEE_SOCIAL:   4900,   // $49 flat for social contests
  PLATFORM_FEE_PCT:   25,
  MIN_PRIZE_OPEN:     5000,   // $50 minimum
  MIN_BASE_PAY:       300,    // $3 minimum per post
  MIN_ENTRIES_OPEN:   5,
  WINNER_GRACE_HRS:   72,
  ACCOUNT_NEW_DAYS:   7,
  BONUS_PLACES:       3,
};

const platformFee = (amount) => Math.round(amount * COMP.PLATFORM_FEE_PCT / 100);
const totalCostOpen = (prize) => prize + platformFee(prize) + COMP.setupFee(prize);
const vaeToUsd = (vae) => (vae / 100).toFixed(2);

function timeLeft(deadline) {
  const diff = new Date(deadline) - Date.now();
  if (diff <= 0) return 'Ended';
  const d = Math.floor(diff / 86400000);
  const h = Math.floor((diff % 86400000) / 3600000);
  const m = Math.floor((diff % 3600000) / 60000);
  if (d > 0) return `${d}d ${h}h left`;
  if (h > 0) return `${h}h ${m}m left`;
  return `${m}m left`;
}

function locationBadge(comp) {
  if (!comp.location_required || !comp.allowed_countries?.length) return '🌍 Worldwide';
  return `📍 ${comp.allowed_countries.join(', ')}`;
}

// ─── MENU ─────────────────────────────────────────────────────────────────────
async function showCompetitionsMenu(ctx, supabase, edit, Markup, fmt) {
  const [{ data: comps }, { data: chals }] = await Promise.all([
    supabase.from('competitions')
      .select('id,title,prize_pool,entry_count,deadline,location_required,allowed_countries')
      .eq('status', 'active').order('created_at', { ascending: false }).limit(6),
    supabase.from('social_challenges')
      .select('id,title,base_pay_per_post,prize_structure,entry_count,deadline,location_required,allowed_countries')
      .eq('status', 'active').order('created_at', { ascending: false }).limit(6),
  ]);

  const openList = comps || [];
  const socialList = chals || [];

  let msg = `🏆 <b>Competitions &amp; Contests</b>\n\n`;
  msg += `🏆 <b>Open Competition</b> — submit best work, 1 winner takes full prize\n`;
  msg += `📱 <b>Social Contest</b> — post on TikTok/Instagram, earn per approval + top 3 bonuses\n\n`;

  if (openList.length) {
    msg += `━━━━━━━━━━━━━━━━\n🏆 <b>Open Competitions</b>\n\n`;
    openList.forEach((c, i) => {
      msg += `${i + 1}. <b>${fmt.esc(c.title)}</b>\n`;
      msg += `   💰 $${vaeToUsd(c.prize_pool)} • 👥 ${c.entry_count || 0} entries • ${locationBadge(c)} • ⏰ ${timeLeft(c.deadline)}\n\n`;
    });
  }

  if (socialList.length) {
    msg += `━━━━━━━━━━━━━━━━\n📱 <b>Social Contests</b>\n\n`;
    socialList.forEach((c, i) => {
      const ps = c.prize_structure || {};
      msg += `${i + 1}. <b>${fmt.esc(c.title)}</b>\n`;
      msg += `   💵 $${vaeToUsd(c.base_pay_per_post)}/post • 🥇$${vaeToUsd(ps['1st'] || 0)} bonus • ${locationBadge(c)} • ⏰ ${timeLeft(c.deadline)}\n\n`;
    });
  }

  if (!openList.length && !socialList.length) {
    msg += `<i>No active competitions right now.\n\n`;
    msg += `🏆 Post a competition — get 20+ creative submissions, pick the best\n`;
    msg += `📱 Post a social contest — get TikToks/Reels about your brand, pay per post\n\n`;
    msg += `10x cheaper than agencies.</i>\n`;
  }

  const btns = [];
  // Show prize on button: "🏆 Logo Design — $50"
  openList.forEach(c => btns.push([Markup.button.callback(
    `🏆 ${c.title.substring(0, 28)} — $${vaeToUsd(c.prize_pool)}`,
    `comp_view_${c.id}`
  )]));
  socialList.forEach(c => btns.push([Markup.button.callback(
    `📱 ${c.title.substring(0, 25)} — $${vaeToUsd(c.base_pay_per_post)}/post`,
    `chal_view_${c.id}`
  )]));
  btns.push([
    Markup.button.callback('➕ Post Competition', 'comp_create'),
    Markup.button.callback('📱 Post Contest', 'chal_create'),
  ]);
  btns.push([Markup.button.callback('📊 My Competitions', 'my_competitions')]);
  btns.push([Markup.button.callback('🔙 Menu', 'menu')]);

  return edit(ctx, msg, Markup.inlineKeyboard(btns));
}

// ─── VIEW OPEN COMPETITION ────────────────────────────────────────────────────
async function viewCompetition(ctx, compId, supabase, edit, Markup, fmt, userId) {
  const { data: comp } = await supabase.from('competitions')
    .select('*, requester:app_users!competitions_requester_id_fkey(id,username,first_name)')
    .eq('id', compId).single();

  if (!comp) return edit(ctx, '❌ Competition not found.',
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', 'competitions_menu')]]));

  const isOwner = comp.requester_id === userId;
  const hasEnded = new Date(comp.deadline) < new Date();
  const canJudge = isOwner && (hasEnded || comp.status === 'judging') && comp.status !== 'completed';
  const req = comp.requester;
  const reqName = req?.username ? '@' + req.username : req?.first_name || 'Anonymous';
  const setupFee = COMP.setupFee(comp.prize_pool);

  let msg = `🏆 <b>${fmt.esc(comp.title)}</b>\n\n`;
  msg += `📝 ${fmt.esc(comp.description || '')}\n\n`;
  msg += `━━━━━━━━━━━━━━━━\n`;
  msg += `💰 <b>Prize:</b> $${vaeToUsd(comp.prize_pool)} — winner keeps 100%\n`;
  msg += `👥 <b>Entries:</b> ${comp.entry_count || 0} (need ${comp.min_entries || COMP.MIN_ENTRIES_OPEN} min to pick winner)\n`;
  msg += `${locationBadge(comp)}\n`;
  msg += `⏰ <b>Deadline:</b> ${timeLeft(comp.deadline)}\n`;
  msg += `📊 <b>Status:</b> ${comp.status}\n\n`;
  msg += `<i>Submit your best work. Requester picks 1 winner.\nIf no pick within 72hrs of deadline, top-rated entry wins automatically.</i>\n\n`;
  msg += `👤 Posted by: ${reqName}\n`;

  const btns = [];
  if (!isOwner && !hasEnded && comp.status === 'active') {
    // Location check
    btns.push([Markup.button.callback('✍️ Submit My Entry', `comp_enter_${comp.id}`)]);
  }
  if (canJudge) btns.push([Markup.button.callback('👑 Pick Winner', `comp_judge_${comp.id}`)]);
  if (isOwner) btns.push([Markup.button.callback('👀 View All Entries', `comp_entries_${comp.id}`)]);
  if (!isOwner && comp.status === 'completed') btns.push([Markup.button.callback('🚩 Flag Result', `comp_flag_${comp.id}`)]);
  btns.push([Markup.button.callback('🔙 Back', 'competitions_menu')]);

  return edit(ctx, msg, Markup.inlineKeyboard(btns));
}

// ─── VIEW SOCIAL CONTEST ──────────────────────────────────────────────────────
async function viewChallenge(ctx, chalId, supabase, edit, Markup, fmt, userId) {
  const { data: chal } = await supabase.from('social_challenges')
    .select('*, requester:app_users!social_challenges_requester_id_fkey(id,username,first_name)')
    .eq('id', chalId).single();

  if (!chal) return edit(ctx, '❌ Contest not found.',
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', 'competitions_menu')]]));

  const isOwner = chal.requester_id === userId;
  const hasEnded = new Date(chal.deadline) < new Date();
  const ps = chal.prize_structure || { '1st': 5000, '2nd': 2500, '3rd': 1000 };
  const req = chal.requester;
  const reqName = req?.username ? '@' + req.username : req?.first_name || 'Anonymous';

  let msg = `📱 <b>${fmt.esc(chal.title)}</b>\n\n`;
  msg += `📝 ${fmt.esc(chal.description || '')}\n\n`;
  if (chal.requirements) msg += `📋 <b>Requirements:</b> ${fmt.esc(chal.requirements)}\n\n`;
  msg += `━━━━━━━━━━━━━━━━\n`;
  msg += `💵 <b>Base pay per approved post:</b> $${vaeToUsd(chal.base_pay_per_post)}\n`;
  msg += `🥇 <b>1st place bonus:</b> $${vaeToUsd(ps['1st'] || 0)}\n`;
  msg += `🥈 <b>2nd place bonus:</b> $${vaeToUsd(ps['2nd'] || 0)}\n`;
  msg += `🥉 <b>3rd place bonus:</b> $${vaeToUsd(ps['3rd'] || 0)}\n\n`;
  msg += `📢 <b>Platform:</b> ${chal.platform || 'Any'}\n`;
  if (chal.hashtag) msg += `#️⃣ <b>Hashtag:</b> ${fmt.esc(chal.hashtag)}\n`;
  msg += `👥 <b>Submitted:</b> ${chal.entry_count || 0} • ✅ <b>Approved:</b> ${chal.approved_count || 0}\n`;
  msg += `${locationBadge(chal)}\n`;
  msg += `⏰ <b>Deadline:</b> ${timeLeft(chal.deadline)}\n`;
  msg += `🤖 <b>AI content:</b> ${chal.ai_content_allowed ? 'Allowed ✅' : 'Human only'}\n\n`;
  msg += `<i>Post on ${chal.platform || 'social media'} and submit your URL.\n`;
  msg += `Every approved post earns base pay instantly.\n`;
  msg += `After deadline, requester picks top 3 — bonuses paid immediately.</i>\n\n`;
  msg += `👤 Posted by: ${reqName}\n`;

  const btns = [];
  if (!isOwner && !hasEnded && chal.status === 'active') {
    btns.push([Markup.button.callback('📤 Submit My Post', `chal_enter_${chal.id}`)]);
  }
  if (isOwner && chal.status === 'active') {
    // Show pending count
    const { count } = await supabase.from('challenge_entries')
      .select('id', { count: 'exact', head: true })
      .eq('challenge_id', chalId).eq('status', 'pending');
    const pendingLabel = count > 0 ? `✅ Review Submissions (${count} pending)` : '✅ Review Submissions';
    btns.push([Markup.button.callback(pendingLabel, `chal_review_${chal.id}`)]);
  }
  if (isOwner && hasEnded && chal.status === 'active') {
    btns.push([Markup.button.callback('🏆 Pick Top 3 Winners', `chal_judge_${chal.id}`)]);
  }
  btns.push([Markup.button.callback('🔙 Back', 'competitions_menu')]);

  return edit(ctx, msg, Markup.inlineKeyboard(btns));
}

// ─── JUDGE OPEN COMPETITION ───────────────────────────────────────────────────
async function judgeCompetition(ctx, compId, supabase, edit, Markup, fmt, userId) {
  const { data: comp } = await supabase.from('competitions').select('*').eq('id', compId).single();
  if (!comp || comp.requester_id !== userId) return edit(ctx, '❌ Not authorised.',
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', 'competitions_menu')]]));

  const { data: entries } = await supabase.from('competition_entries')
    .select('*, worker:app_users(id,username,first_name,tasks_completed,trust_score)')
    .eq('competition_id', compId).eq('status', 'submitted')
    .order('created_at', { ascending: true });

  const list = entries || [];

  if (!list.length) return edit(ctx,
    `📭 <b>No entries yet</b>\n\n<b>${fmt.esc(comp.title)}</b>\n\nShare your competition link to attract submissions:\n<code>https://t.me/LoopumanBot?start=comp_${compId}</code>`,
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', `comp_view_${compId}`)]]));

  if (list.length < (comp.min_entries || COMP.MIN_ENTRIES_OPEN)) return edit(ctx,
    `⚠️ <b>Not enough entries yet</b>\n\nNeed ${comp.min_entries || COMP.MIN_ENTRIES_OPEN} minimum. Current: ${list.length}\n\nShare: <code>https://t.me/LoopumanBot?start=comp_${compId}</code>`,
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', `comp_view_${compId}`)]]));

  let msg = `👑 <b>Pick Your Winner</b>\n\n`;
  msg += `<b>${fmt.esc(comp.title)}</b>\n`;
  msg += `Prize: <b>$${vaeToUsd(comp.prize_pool)}</b> — winner gets 100%\n\n`;

  const btns = [];
  list.forEach((e, i) => {
    const w = e.worker;
    const name = w?.username ? '@' + w.username : w?.first_name || 'Worker';
    const preview = e.content ? e.content.substring(0, 80) : 'Media submission';
    msg += `${i + 1}. <b>${name}</b> (${w?.tasks_completed || 0} tasks)\n   <i>${fmt.esc(preview)}</i>\n\n`;
    btns.push([Markup.button.callback(`👑 Award to ${name}`, `comp_award_${compId}_${e.id}`)]);
  });

  btns.push([Markup.button.callback('🔙 Back', `comp_view_${compId}`)]);
  return edit(ctx, msg, Markup.inlineKeyboard(btns));
}

// ─── AWARD OPEN COMPETITION WINNER ───────────────────────────────────────────
async function awardWinner(ctx, compId, entryId, supabase, edit, Markup, fmt, db, notifyUser) {
  const { data: comp } = await supabase.from('competitions').select('*').eq('id', compId).single();
  const { data: entry } = await supabase.from('competition_entries')
    .select('*, worker:app_users(id,telegram_id,username,first_name,tasks_completed,created_at)')
    .eq('id', entryId).single();

  if (!comp || !entry) return edit(ctx, '❌ Not found.',
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', 'competitions_menu')]]));

  if (comp.requester_id === entry.user_id) return edit(ctx, '❌ Cannot award prize to yourself.',
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', `comp_judge_${compId}`)]]));

  const now = new Date().toISOString();
  const prize = comp.prize_pool;
  const w = entry.worker;
  const accountAgeDays = (Date.now() - new Date(w?.created_at || Date.now())) / 86400000;
  const holdPayment = accountAgeDays < COMP.ACCOUNT_NEW_DAYS && (w?.tasks_completed || 0) === 0;

  if (!holdPayment) {
    await db.addToBalance(entry.user_id, prize);
    await db.recordTransaction(entry.user_id, 'competition_win', prize, compId, `Won: ${comp.title}`);
  }

  await supabase.from('competition_entries').update({
    is_winner: true, rank: 1, prize_won: prize, status: 'won', paid_at: holdPayment ? null : now
  }).eq('id', entryId);

  await supabase.from('competition_entries').update({ status: 'not_selected' })
    .eq('competition_id', compId).neq('id', entryId);

  await supabase.from('competitions').update({
    status: 'completed', winner_selected_at: now, closed_at: now
  }).eq('id', compId);

  const winnerName = w?.username ? '@' + w.username : w?.first_name || 'Worker';
  if (w?.telegram_id) {
    await notifyUser(w.telegram_id,
      `🏆 <b>YOU WON!</b>\n\n<b>${fmt.esc(comp.title)}</b>\n💰 $${vaeToUsd(prize)}${holdPayment ? ' (held 48hrs — new account review)' : ' added to your balance!'}`
    );
  }

  // Notify losers + XP
  const { data: allEntries } = await supabase.from('competition_entries')
    .select('user_id,worker:app_users(telegram_id,trust_score)')
    .eq('competition_id', compId);

  for (const e of (allEntries || [])) {
    if (e.user_id === entry.user_id) continue;
    if (e.worker?.telegram_id) {
      await notifyUser(e.worker.telegram_id,
        `📋 Competition "<b>${fmt.esc(comp.title)}</b>" ended. You were not selected this time. +2 XP earned for participating!`
      ).catch(() => {});
    }
    await supabase.from('app_users').update({ trust_score: (e.worker?.trust_score || 0) + 2 })
      .eq('id', e.user_id).catch(() => {});
  }

  const holdNote = holdPayment ? `\n\n⚠️ Winner is a new account — payment held 48hrs for review.` : '';
  return edit(ctx,
    `🏆 <b>Winner Selected!</b>\n\n<b>${fmt.esc(comp.title)}</b>\n👑 Winner: <b>${winnerName}</b>\n💰 $${vaeToUsd(prize)} paid${holdNote}`,
    Markup.inlineKeyboard([
      [Markup.button.callback('📊 My Competitions', 'my_competitions')],
      [Markup.button.callback('🔙 Menu', 'menu')],
    ])
  );
}

// ─── REVIEW SOCIAL SUBMISSIONS ────────────────────────────────────────────────
async function reviewChallengeSubmissions(ctx, chalId, supabase, edit, Markup, fmt, userId) {
  const { data: chal } = await supabase.from('social_challenges').select('*').eq('id', chalId).single();
  if (!chal || chal.requester_id !== userId) return edit(ctx, '❌ Not authorised.',
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', 'competitions_menu')]]));

  const { data: pending } = await supabase.from('challenge_entries')
    .select('*, worker:app_users(id,telegram_id,username,first_name,tasks_completed)')
    .eq('challenge_id', chalId).eq('status', 'pending')
    .order('created_at', { ascending: true }).limit(1);

  if (!pending?.length) return edit(ctx,
    `✅ <b>All caught up!</b>\n\n<b>${fmt.esc(chal.title)}</b>\nApproved: ${chal.approved_count || 0} posts\n\n<i>Check back when new submissions arrive.</i>`,
    Markup.inlineKeyboard([
      [Markup.button.callback('🔄 Refresh', `chal_review_${chalId}`)],
      [Markup.button.callback('🔙 Back', `chal_view_${chalId}`)],
    ])
  );

  const entry = pending[0];
  const w = entry.worker;
  const name = w?.username ? '@' + w.username : w?.first_name || 'Worker';
  const url = entry.post_url || entry.post_link || 'No URL provided';

  return edit(ctx,
    `📋 <b>Review Submission</b>\n\n<b>${fmt.esc(chal.title)}</b>\nFrom: <b>${name}</b> (${w?.tasks_completed || 0} tasks)\n\n🔗 <b>Post URL:</b> ${url}\n\n💵 Pay on approval: <b>$${vaeToUsd(chal.base_pay_per_post)}</b>\n\nDoes this meet your requirements?`,
    Markup.inlineKeyboard([
      [
        Markup.button.callback('✅ Approve & Pay', `chal_approve_${chalId}_${entry.id}`),
        Markup.button.callback('❌ Reject', `chal_reject_${chalId}_${entry.id}`),
      ],
      [Markup.button.callback('🔙 Back', `chal_view_${chalId}`)],
    ])
  );
}

// ─── APPROVE CHALLENGE ENTRY ──────────────────────────────────────────────────
// FIXED: userId passed directly, no db.getUser call
async function approveChallengeEntry(ctx, chalId, entryId, supabase, edit, Markup, fmt, db, notifyUser, userId) {
  const { data: entry } = await supabase.from('challenge_entries')
    .select('*, worker:app_users(id,telegram_id,username,first_name)')
    .eq('id', entryId).single();
  const { data: chal } = await supabase.from('social_challenges').select('*').eq('id', chalId).single();

  if (!entry || !chal) return edit(ctx, '❌ Not found.',
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', 'competitions_menu')]]));

  const basePay = chal.base_pay_per_post;

  await db.addToBalance(entry.user_id, basePay);
  await db.recordTransaction(entry.user_id, 'social_contest_pay', basePay, chalId, `Approved post: ${chal.title}`);

  await supabase.from('challenge_entries').update({
    status: 'approved', approved_by_requester: true, base_pay_paid: true
  }).eq('id', entryId);

  await supabase.from('social_challenges').update({
    approved_count: (chal.approved_count || 0) + 1
  }).eq('id', chalId);

  const w = entry.worker;
  if (w?.telegram_id) {
    await notifyUser(w.telegram_id,
      `✅ <b>Post Approved &amp; Paid!</b>\n\n<b>${fmt.esc(chal.title)}</b>\n💰 <b>$${vaeToUsd(basePay)} added to your balance!</b>\n\n🏆 Keep getting engagement — requester picks top 3 at contest end for bonus prizes!`
    ).catch(() => {});
  }

  // Continue with next pending — userId passed directly
  return reviewChallengeSubmissions(ctx, chalId, supabase, edit, Markup, fmt, userId);
}

// ─── JUDGE SOCIAL CONTEST — requester picks top 3 ────────────────────────────
async function judgeSocialContest(ctx, chalId, supabase, edit, Markup, fmt, userId, place) {
  const { data: chal } = await supabase.from('social_challenges').select('*').eq('id', chalId).single();
  if (!chal || chal.requester_id !== userId) return edit(ctx, '❌ Not authorised.',
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', 'competitions_menu')]]));

  const ps = chal.prize_structure || { '1st': 5000, '2nd': 2500, '3rd': 1000 };
  const placeNum = place || 1;
  const placeKey = placeNum === 1 ? '1st' : placeNum === 2 ? '2nd' : '3rd';
  const medals = { 1: '🥇', 2: '🥈', 3: '🥉' };

  const { data: approved } = await supabase.from('challenge_entries')
    .select('*, worker:app_users(id,username,first_name)')
    .eq('challenge_id', chalId).eq('status', 'approved').eq('bonus_paid', false)
    .order('created_at', { ascending: true });

  const list = approved || [];
  if (!list.length) return edit(ctx,
    `✅ All bonuses awarded for <b>${fmt.esc(chal.title)}</b>`,
    Markup.inlineKeyboard([[Markup.button.callback('🔙 My Competitions', 'my_competitions')]]));

  let msg = `${medals[placeNum]} <b>Pick ${placeKey} Place</b>\n\n`;
  msg += `<b>${fmt.esc(chal.title)}</b>\n`;
  msg += `${placeKey} bonus: <b>$${vaeToUsd(ps[placeKey] || 0)}</b>\n\n`;
  msg += `Select the post with the most engagement:\n\n`;

  const btns = [];
  list.forEach((e, i) => {
    const w = e.worker;
    const name = w?.username ? '@' + w.username : w?.first_name || 'Worker';
    const url = e.post_url || e.post_link || '';
    msg += `${i + 1}. <b>${name}</b>\n   ${url.substring(0, 50)}\n\n`;
    btns.push([Markup.button.callback(`${medals[placeNum]} ${name}`, `chal_bonus_${chalId}_${e.id}_${placeNum}`)]);
  });

  btns.push([Markup.button.callback('🔙 Back', `chal_view_${chalId}`)]);
  return edit(ctx, msg, Markup.inlineKeyboard(btns));
}

// ─── AWARD SOCIAL BONUS ───────────────────────────────────────────────────────
async function awardSocialBonus(ctx, chalId, entryId, placeNum, supabase, edit, Markup, fmt, db, notifyUser, userId) {
  const { data: entry } = await supabase.from('challenge_entries')
    .select('*, worker:app_users(id,telegram_id,username,first_name)')
    .eq('id', entryId).single();
  const { data: chal } = await supabase.from('social_challenges').select('*').eq('id', chalId).single();

  if (!entry || !chal) return edit(ctx, '❌ Not found.',
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', 'competitions_menu')]]));

  const ps = chal.prize_structure || { '1st': 5000, '2nd': 2500, '3rd': 1000 };
  const placeKey = placeNum === 1 ? '1st' : placeNum === 2 ? '2nd' : '3rd';
  const medals = { 1: '🥇', 2: '🥈', 3: '🥉' };
  const bonus = ps[placeKey] || 0;

  if (bonus > 0) {
    await db.addToBalance(entry.user_id, bonus);
    await db.recordTransaction(entry.user_id, 'social_contest_bonus', bonus, chalId, `${placeKey} place: ${chal.title}`);
  }

  await supabase.from('challenge_entries').update({
    rank: placeNum, place: placeKey, prize_won: (entry.prize_won || 0) + bonus, bonus_paid: true
  }).eq('id', entryId);

  const w = entry.worker;
  const winnerName = w?.username ? '@' + w.username : w?.first_name || 'Worker';
  if (w?.telegram_id) {
    await notifyUser(w.telegram_id,
      `${medals[placeNum]} <b>${placeKey.toUpperCase()} PLACE!</b>\n\n<b>${fmt.esc(chal.title)}</b>\n💰 $${vaeToUsd(bonus)} bonus added to your balance!`
    ).catch(() => {});
  }

  // If more places to award, continue
  if (placeNum < COMP.BONUS_PLACES) {
    return edit(ctx,
      `${medals[placeNum]} ${placeKey} place awarded to <b>${winnerName}</b>!\n\nNow pick ${placeNum === 1 ? '🥈 2nd' : '🥉 3rd'} place:`,
      Markup.inlineKeyboard([[Markup.button.callback(`Pick ${placeNum === 1 ? '2nd' : '3rd'} Place`, `chal_judge_${chalId}_${placeNum + 1}`)]])
    );
  }

  // All done
  await supabase.from('social_challenges').update({ status: 'completed', closed_at: new Date().toISOString() }).eq('id', chalId);
  return edit(ctx,
    `🎉 <b>All bonuses awarded!</b>\n\n<b>${fmt.esc(chal.title)}</b> is now complete.\nAll winners have been notified and paid.`,
    Markup.inlineKeyboard([
      [Markup.button.callback('📊 My Competitions', 'my_competitions')],
      [Markup.button.callback('🔙 Menu', 'menu')],
    ])
  );
}

// ─── MY COMPETITIONS ──────────────────────────────────────────────────────────
async function myCompetitions(ctx, supabase, edit, Markup, fmt, userId) {
  const [{ data: comps }, { data: chals }] = await Promise.all([
    supabase.from('competitions').select('id,title,prize_pool,entry_count,status,deadline')
      .eq('requester_id', userId).order('created_at', { ascending: false }).limit(10),
    supabase.from('social_challenges').select('id,title,base_pay_per_post,entry_count,approved_count,status,deadline')
      .eq('requester_id', userId).order('created_at', { ascending: false }).limit(10),
  ]);

  // Get pending counts for social contests
  const chalIds = (chals || []).filter(c => c.status === 'active').map(c => c.id);
  let pendingCounts = {};
  if (chalIds.length) {
    const { data: pending } = await supabase.from('challenge_entries')
      .select('challenge_id').eq('status', 'pending').in('challenge_id', chalIds);
    (pending || []).forEach(p => {
      pendingCounts[p.challenge_id] = (pendingCounts[p.challenge_id] || 0) + 1;
    });
  }

  let msg = `📊 <b>My Competitions &amp; Contests</b>\n\n`;
  const btns = [];
  const si = (s) => s === 'active' ? '🟢' : s === 'completed' ? '✅' : '🔴';

  if ((comps || []).length) {
    msg += `🏆 <b>Open Competitions</b>\n`;
    comps.forEach(c => {
      msg += `${si(c.status)} ${fmt.esc(c.title.substring(0, 30))} — $${vaeToUsd(c.prize_pool)} — ${c.entry_count || 0} entries\n`;
      btns.push([Markup.button.callback(`🏆 ${c.title.substring(0, 38)}`, `comp_view_${c.id}`)]);
    });
    msg += '\n';
  }

  if ((chals || []).length) {
    msg += `📱 <b>Social Contests</b>\n`;
    chals.forEach(c => {
      const pending = pendingCounts[c.id] || 0;
      const pendingBadge = pending > 0 ? ` ⚠️ ${pending} pending` : '';
      msg += `${si(c.status)} ${fmt.esc(c.title.substring(0, 30))} — ${c.approved_count || 0} approved${pendingBadge}\n`;
      btns.push([Markup.button.callback(
        `📱 ${c.title.substring(0, 30)}${pending > 0 ? ` (${pending} pending)` : ''}`,
        `chal_view_${c.id}`
      )]);
    });
  }

  if (!comps?.length && !chals?.length) msg += `<i>Nothing posted yet.</i>\n`;

  btns.push([
    Markup.button.callback('➕ Post Competition', 'comp_create'),
    Markup.button.callback('📱 Post Contest', 'chal_create'),
  ]);
  btns.push([Markup.button.callback('🔙 Menu', 'menu')]);
  return edit(ctx, msg, Markup.inlineKeyboard(btns));
}

// ─── SCHEDULER: AUTO WINNER for open competitions ────────────────────────────
async function runCompetitionScheduler(supabase, db, notifyUser, fmt) {
  const now = new Date().toISOString();
  const graceCutoff = new Date(Date.now() - COMP.WINNER_GRACE_HRS * 3600000).toISOString();
  const reminderCutoff = new Date(Date.now() + 48 * 3600000).toISOString();

  // 48hr reminder to requesters
  const { data: expiringSoon } = await supabase.from('competitions')
    .select('*, requester:app_users(telegram_id)')
    .eq('status', 'active')
    .lt('deadline', reminderCutoff)
    .gt('deadline', now);

  for (const comp of (expiringSoon || [])) {
    if (comp.requester?.telegram_id) {
      await notifyUser(comp.requester.telegram_id,
        `⏰ <b>Competition ending soon!</b>\n\n"<b>${fmt.esc(comp.title)}</b>" ends in less than 48 hours.\nYou have ${comp.entry_count || 0} entries to review.\n\nOpen your bot to pick a winner before the deadline!`
      ).catch(() => {});
    }
  }

  // Auto-select winners for overdue competitions
  const { data: overdue } = await supabase.from('competitions')
    .select('*, requester:app_users(telegram_id)')
    .eq('status', 'active')
    .lt('deadline', graceCutoff);

  for (const comp of (overdue || [])) {
    const { data: entries } = await supabase.from('competition_entries')
      .select('*, worker:app_users(id,telegram_id,trust_score,tasks_completed)')
      .eq('competition_id', comp.id).eq('status', 'submitted');

    if (!entries?.length) {
      const refund = comp.prize_pool + Math.round(comp.prize_pool * COMP.PLATFORM_FEE_PCT / 100);
      await db.addToBalance(comp.requester_id, refund);
      await db.recordTransaction(comp.requester_id, 'competition_refund', refund, comp.id, `No entries: ${comp.title}`);
      await supabase.from('competitions').update({ status: 'cancelled', closed_at: now }).eq('id', comp.id);
      await notifyUser(comp.requester?.telegram_id,
        `🔄 Competition "<b>${fmt.esc(comp.title)}</b>" had no entries. Prize refunded. Setup fee kept.`
      ).catch(() => {});
      continue;
    }

    const winner = [...entries].sort((a, b) => (b.worker?.trust_score || 0) - (a.worker?.trust_score || 0))[0];
    await db.addToBalance(winner.user_id, comp.prize_pool);
    await db.recordTransaction(winner.user_id, 'competition_win', comp.prize_pool, comp.id, `Auto-won: ${comp.title}`);

    await supabase.from('competition_entries').update({
      is_winner: true, rank: 1, prize_won: comp.prize_pool, status: 'won', paid_at: now
    }).eq('id', winner.id);

    await supabase.from('competition_entries').update({ status: 'not_selected' })
      .eq('competition_id', comp.id).neq('id', winner.id);

    await supabase.from('competitions').update({
      status: 'completed', auto_winner: true, winner_selected_at: now, closed_at: now
    }).eq('id', comp.id);

    if (winner.worker?.telegram_id) {
      await notifyUser(winner.worker.telegram_id,
        `🏆 <b>YOU AUTO-WON!</b>\n\n"<b>${fmt.esc(comp.title)}</b>"\n💰 $${vaeToUsd(comp.prize_pool)} added to your balance!`
      ).catch(() => {});
    }

    await notifyUser(comp.requester?.telegram_id,
      `⏰ "<b>${fmt.esc(comp.title)}</b>" auto-closed. Winner selected automatically as you didn't pick within 72 hours.`
    ).catch(() => {});

    console.log(`[Competition Scheduler] Auto-winner for: ${comp.title}`);
  }

  // Remind requesters whose social contests have ended to pick top 3
  const { data: endedChals } = await supabase.from('social_challenges')
    .select('*, requester:app_users(telegram_id)')
    .eq('status', 'active')
    .lt('deadline', now);

  for (const chal of (endedChals || [])) {
    if (chal.requester?.telegram_id) {
      await notifyUser(chal.requester.telegram_id,
        `🏆 <b>Your social contest has ended!</b>\n\n"<b>${fmt.esc(chal.title)}</b>"\n${chal.approved_count || 0} posts approved.\n\nOpen your bot to pick your top 3 and award bonus prizes!`
      ).catch(() => {});
    }
    // Mark as judging so we don't spam them
    await supabase.from('social_challenges').update({ status: 'judging' }).eq('id', chal.id);
  }
}

module.exports = {
  COMP, platformFee, totalCostOpen, vaeToUsd, timeLeft, locationBadge,
  showCompetitionsMenu, viewCompetition, viewChallenge,
  judgeCompetition, awardWinner,
  reviewChallengeSubmissions, approveChallengeEntry,
  judgeSocialContest, awardSocialBonus,
  myCompetitions, runCompetitionScheduler,
};
