// ═══════════════════════════════════════════════════════════════════════════════
// COMPETITION BOT v2 — REPLACE competition_bot_append.js on server
// Upload this file, then on server:
//   1. Remove old appended code from telegram-bot.js
//   2. Append this file instead
// OR: since old code is already appended, we replace competition_module.js
//     with v2 and this file replaces the appended section
// ═══════════════════════════════════════════════════════════════════════════════

const {
  COMP, platformFee, totalCostOpen, vaeToUsd, locationBadge,
  showCompetitionsMenu, viewCompetition, viewChallenge,
  judgeCompetition, awardWinner,
  reviewChallengeSubmissions, approveChallengeEntry,
  judgeSocialContest, awardSocialBonus,
  myCompetitions, runCompetitionScheduler,
} = require('./competition_module');

const _notifyComp = async (telegramId, message) => {
  if (!telegramId) return;
  try { await bot.telegram.sendMessage(String(telegramId), message, { parse_mode: 'HTML' }); }
  catch (e) { /* silent */ }
};

// ─── COUNTRY LIST for location picker ────────────────────────────────────────
const TOP_COUNTRIES = [
  'Kenya', 'Nigeria', 'Ghana', 'South Africa', 'Tanzania',
  'Uganda', 'Ethiopia', 'Philippines', 'India', 'Pakistan',
  'Bangladesh', 'Indonesia', 'Brazil', 'Mexico', 'USA',
  'UK', 'Canada', 'Australia', 'Worldwide'
];

// ─── MENU ─────────────────────────────────────────────────────────────────────
bot.action('competitions_menu', async (ctx) => {
  await cb(ctx);
  await showCompetitionsMenu(ctx, supabase, edit, Markup, fmt);
});

// ─── VIEW ─────────────────────────────────────────────────────────────────────
bot.action(/^comp_view_(.+)$/, async (ctx) => {
  await cb(ctx);
  const user = await db.getUser(ctx.from.id);
  await viewCompetition(ctx, ctx.match[1], supabase, edit, Markup, fmt, user.id);
});

bot.action(/^chal_view_(.+)$/, async (ctx) => {
  await cb(ctx);
  const user = await db.getUser(ctx.from.id);
  await viewChallenge(ctx, ctx.match[1], supabase, edit, Markup, fmt, user.id);
});

// ─── DEEP LINK: t.me/LoopumanBot?start=comp_XXXX ─────────────────────────────
// Handle in existing /start handler by checking payload
// Added here as a standalone action for direct deep links
bot.action(/^deeplink_comp_(.+)$/, async (ctx) => {
  await cb(ctx);
  const user = await db.getUser(ctx.from.id);
  await viewCompetition(ctx, ctx.match[1], supabase, edit, Markup, fmt, user.id);
});

// ─── CREATE OPEN COMPETITION ──────────────────────────────────────────────────
bot.action('comp_create', async (ctx) => {
  await cb(ctx);
  const user = await db.getUser(ctx.from.id);
  const minCost = totalCostOpen(COMP.MIN_PRIZE_OPEN);
  if ((user.balance?.available || 0) < minCost) {
    return edit(ctx,
      `❌ <b>Insufficient Balance</b>\n\nMinimum to post a competition:\n• Prize: $50\n• Platform fee (25%): $12.50\n• Setup fee: $10\n• <b>Total: $72.50</b>\n\nYour balance: $${vaeToUsd(user.balance?.available || 0)}`,
      Markup.inlineKeyboard([
        [Markup.button.callback('💳 Add Funds', 'buy_vae')],
        [Markup.button.callback('🔙 Back', 'competitions_menu')],
      ])
    );
  }
  setState(ctx.from.id, {
    action: 'create_competition',
    step: 'title',
    draft: { title: null, description: null, prize_pool: null, duration_days: null, location_required: false, allowed_countries: [] },
  });
  return edit(ctx,
    `🏆 <b>Create Open Competition</b>\n\nWorkers submit their best work. You pick 1 winner who gets 100% of the prize.\n\n💰 <b>Fee structure:</b>\n• Prize under $100 → $10 setup fee\n• Prize $100–$500 → $25 setup fee\n• Prize over $500 → $50 setup fee\n• Platform fee: 25% on prize\n\n<b>Step 1 of 5: What is your competition title?</b>\n<i>e.g. "Design our app logo" or "Write our tagline"</i>`,
    Markup.inlineKeyboard([[Markup.button.callback('❌ Cancel', 'competitions_menu')]])
  );
});

// ─── CREATE SOCIAL CONTEST ────────────────────────────────────────────────────
bot.action('chal_create', async (ctx) => {
  await cb(ctx);
  setState(ctx.from.id, {
    action: 'create_challenge',
    step: 'title',
    draft: {
      title: null, description: null, platform: null, hashtag: null,
      base_pay_per_post: null, prize_1st: null, prize_2nd: null, prize_3rd: null,
      duration_days: null, requirements: null, location_required: false, allowed_countries: [],
    },
  });
  return edit(ctx,
    `📱 <b>Create Social Media Contest</b>\n\nPeople post about your brand on TikTok/Instagram/YouTube.\nEvery approved post = instant base pay.\nAfter deadline you pick top 3 = bonus prizes.\n\n💰 <b>Fees:</b>\n• Setup fee: $49 (charged now)\n• Base pay + 25% per approved post\n• Bonus prizes + 25% when you pick top 3\n• AI content, avatars, virtual characters ✅\n\n<b>Step 1 of 6: What is your contest title?</b>\n<i>e.g. "Show us how you use our product"</i>`,
    Markup.inlineKeyboard([[Markup.button.callback('❌ Cancel', 'competitions_menu')]])
  );
});

// ─── ENTER OPEN COMPETITION (worker) ─────────────────────────────────────────
bot.action(/^comp_enter_(.+)$/, async (ctx) => {
  await cb(ctx);
  const compId = ctx.match[1];
  const user = await db.getUser(ctx.from.id);
  const { data: comp } = await supabase.from('competitions').select('*').eq('id', compId).single();

  if (!comp || comp.status !== 'active') return edit(ctx, '❌ Competition no longer active.',
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', 'competitions_menu')]]));
  if (comp.requester_id === user.id) return edit(ctx, '❌ You cannot enter your own competition.',
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', `comp_view_${compId}`)]]));

  // Location check
  if (comp.location_required && comp.allowed_countries?.length) {
    const workerCountry = user.country || user.location_country || '';
    const allowed = comp.allowed_countries.map(c => c.toLowerCase());
    if (workerCountry && !allowed.includes(workerCountry.toLowerCase())) {
      return edit(ctx,
        `❌ <b>Location Restricted</b>\n\nThis competition is only open to workers in: ${comp.allowed_countries.join(', ')}\n\nYour location: ${workerCountry || 'Not set'}`,
        Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', `comp_view_${compId}`)]]));
    }
  }

  const { data: existing } = await supabase.from('competition_entries')
    .select('id').eq('competition_id', compId).eq('user_id', user.id).maybeSingle();
  if (existing) return edit(ctx, '❌ You already submitted an entry.',
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', `comp_view_${compId}`)]]));

  setState(ctx.from.id, { action: 'comp_entry', compId, files: [], userId: user.id });
  return edit(ctx,
    `✍️ <b>Submit Your Entry</b>\n\n<b>${fmt.esc(comp.title)}</b>\nPrize: <b>$${vaeToUsd(comp.prize_pool)}</b>\n\nSend your entry now — text, images, files, links all accepted.\nMake it your best work! One submission per person.\n\n<i>Send your content and it will be submitted automatically.</i>`,
    Markup.inlineKeyboard([[Markup.button.callback('❌ Cancel', `comp_view_${compId}`)]])
  );
});

// ─── ENTER SOCIAL CONTEST (worker) ───────────────────────────────────────────
bot.action(/^chal_enter_(.+)$/, async (ctx) => {
  await cb(ctx);
  const chalId = ctx.match[1];
  const user = await db.getUser(ctx.from.id);
  const { data: chal } = await supabase.from('social_challenges').select('*').eq('id', chalId).single();

  if (!chal || chal.status !== 'active') return edit(ctx, '❌ Contest no longer active.',
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', 'competitions_menu')]]));
  if (chal.requester_id === user.id) return edit(ctx, '❌ You cannot enter your own contest.',
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', `chal_view_${chalId}`)]]));

  // Location check
  if (chal.location_required && chal.allowed_countries?.length) {
    const workerCountry = user.country || user.location_country || '';
    const allowed = chal.allowed_countries.map(c => c.toLowerCase());
    if (workerCountry && !allowed.includes(workerCountry.toLowerCase())) {
      return edit(ctx,
        `❌ <b>Location Restricted</b>\n\nThis contest is only open to workers in: ${chal.allowed_countries.join(', ')}`,
        Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', `chal_view_${chalId}`)]]));
    }
  }

  setState(ctx.from.id, { action: 'chal_entry', chalId, userId: user.id });
  const hashMsg = chal.hashtag ? `\nRequired hashtag: <b>${fmt.esc(chal.hashtag)}</b>` : '';
  return edit(ctx,
    `📱 <b>Submit Your Post</b>\n\n<b>${fmt.esc(chal.title)}</b>\nBase pay on approval: <b>$${vaeToUsd(chal.base_pay_per_post)}</b>${hashMsg}\n\n1️⃣ Post your content on ${chal.platform || 'social media'}\n2️⃣ Send the URL of your live post here\n\n🤖 AI content &amp; avatars welcome!`,
    Markup.inlineKeyboard([[Markup.button.callback('❌ Cancel', `chal_view_${chalId}`)]])
  );
});

// ─── JUDGE & AWARD OPEN COMPETITION ──────────────────────────────────────────
bot.action(/^comp_judge_(.+)$/, async (ctx) => {
  await cb(ctx);
  const user = await db.getUser(ctx.from.id);
  await judgeCompetition(ctx, ctx.match[1], supabase, edit, Markup, fmt, user.id);
});

bot.action(/^comp_entries_(.+)$/, async (ctx) => {
  await cb(ctx);
  const user = await db.getUser(ctx.from.id);
  await judgeCompetition(ctx, ctx.match[1], supabase, edit, Markup, fmt, user.id);
});

bot.action(/^comp_award_([a-zA-Z0-9-]+)_([a-zA-Z0-9-]+)$/, async (ctx) => {
  await cb(ctx);
  const [, compId, entryId] = ctx.match;
  const user = await db.getUser(ctx.from.id);
  const { data: comp } = await supabase.from('competitions').select('requester_id').eq('id', compId).single();
  if (comp?.requester_id !== user.id) return edit(ctx, '❌ Only the requester can award the prize.',
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', 'competitions_menu')]]));
  await awardWinner(ctx, compId, entryId, supabase, edit, Markup, fmt, db, _notifyComp);
});

// ─── SOCIAL CONTEST: REVIEW & APPROVE ────────────────────────────────────────
bot.action(/^chal_review_(.+)$/, async (ctx) => {
  await cb(ctx);
  const user = await db.getUser(ctx.from.id);
  await reviewChallengeSubmissions(ctx, ctx.match[1], supabase, edit, Markup, fmt, user.id);
});

bot.action(/^chal_approve_([a-zA-Z0-9-]+)_([a-zA-Z0-9-]+)$/, async (ctx) => {
  await cb(ctx);
  const [, chalId, entryId] = ctx.match;
  const user = await db.getUser(ctx.from.id);
  const { data: chal } = await supabase.from('social_challenges').select('requester_id').eq('id', chalId).single();
  if (chal?.requester_id !== user.id) return edit(ctx, '❌ Only the requester can approve.',
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', 'competitions_menu')]]));
  // FIXED: pass user.id directly
  await approveChallengeEntry(ctx, chalId, entryId, supabase, edit, Markup, fmt, db, _notifyComp, user.id);
});

bot.action(/^chal_reject_([a-zA-Z0-9-]+)_([a-zA-Z0-9-]+)$/, async (ctx) => {
  await cb(ctx);
  const [, chalId, entryId] = ctx.match;
  const user = await db.getUser(ctx.from.id);
  const { data: chal } = await supabase.from('social_challenges').select('requester_id').eq('id', chalId).single();
  if (chal?.requester_id !== user.id) return edit(ctx, '❌ Only the requester can reject.',
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', 'competitions_menu')]]));
  setState(ctx.from.id, { action: 'chal_reject_reason', chalId, entryId });
  return edit(ctx,
    `❌ <b>Reject Submission</b>\n\nSend a brief reason so the worker can improve.\n<i>e.g. "Missing required hashtag"</i>`,
    Markup.inlineKeyboard([[Markup.button.callback('⏭️ Skip reason', `chal_reject_skip_${chalId}_${entryId}`)]])
  );
});

bot.action(/^chal_reject_skip_([a-zA-Z0-9-]+)_([a-zA-Z0-9-]+)$/, async (ctx) => {
  await cb(ctx);
  const [, chalId, entryId] = ctx.match;
  await supabase.from('challenge_entries').update({ status: 'rejected' }).eq('id', entryId);
  const { data: e } = await supabase.from('challenge_entries')
    .select('user_id,worker:app_users(telegram_id)').eq('id', entryId).single();
  const { data: chal } = await supabase.from('social_challenges').select('title').eq('id', chalId).single();
  if (e?.worker?.telegram_id) {
    await _notifyComp(e.worker.telegram_id,
      `❌ Your submission for "<b>${fmt.esc(chal?.title || '')}</b>" was not approved. Please review requirements and try again.`
    );
  }
  const user = await db.getUser(ctx.from.id);
  return reviewChallengeSubmissions(ctx, chalId, supabase, edit, Markup, fmt, user.id);
});

// ─── SOCIAL CONTEST: JUDGE TOP 3 ─────────────────────────────────────────────
bot.action(/^chal_judge_([a-zA-Z0-9-]+)_?(\d?)$/, async (ctx) => {
  await cb(ctx);
  const chalId = ctx.match[1];
  const place = parseInt(ctx.match[2]) || 1;
  const user = await db.getUser(ctx.from.id);
  await judgeSocialContest(ctx, chalId, supabase, edit, Markup, fmt, user.id, place);
});

bot.action(/^chal_bonus_([a-zA-Z0-9-]+)_([a-zA-Z0-9-]+)_(\d)$/, async (ctx) => {
  await cb(ctx);
  const [, chalId, entryId, placeStr] = ctx.match;
  const place = parseInt(placeStr);
  const user = await db.getUser(ctx.from.id);
  const { data: chal } = await supabase.from('social_challenges').select('requester_id').eq('id', chalId).single();
  if (chal?.requester_id !== user.id) return edit(ctx, '❌ Only the requester can award bonuses.',
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', 'competitions_menu')]]));
  await awardSocialBonus(ctx, chalId, entryId, place, supabase, edit, Markup, fmt, db, _notifyComp, user.id);
});

// ─── FLAG RESULT ──────────────────────────────────────────────────────────────
bot.action(/^comp_flag_(.+)$/, async (ctx) => {
  await cb(ctx);
  const compId = ctx.match[1];
  const user = await db.getUser(ctx.from.id);
  const { data: myEntry } = await supabase.from('competition_entries')
    .select('id').eq('competition_id', compId).eq('user_id', user.id).maybeSingle();
  if (!myEntry) return edit(ctx, '❌ You must have entered this competition to flag it.',
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', 'competitions_menu')]]));
  await supabase.from('competitions')
    .update({ metadata: { flagged: true, flagged_by: user.id, flagged_at: new Date().toISOString() } })
    .eq('id', compId);
  return edit(ctx,
    `🚩 <b>Flagged for Review</b>\n\nThank you. Our team will review within 24 hours. If fraud is confirmed, the prize will be redistributed.`,
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Menu', 'menu')]])
  );
});

// ─── MY COMPETITIONS ──────────────────────────────────────────────────────────
bot.action('my_competitions', async (ctx) => {
  await cb(ctx);
  const user = await db.getUser(ctx.from.id);
  await myCompetitions(ctx, supabase, edit, Markup, fmt, user.id);
});

// ─── CONFIRM POST OPEN COMPETITION ───────────────────────────────────────────
bot.action('comp_confirm_post', async (ctx) => {
  await cb(ctx);
  const user = await db.getUser(ctx.from.id);
  const state = getState(ctx.from.id);
  const draft = state?.draft;
  if (!draft?.prize_pool || !draft?.title) return edit(ctx, '❌ No draft found.',
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', 'competitions_menu')]]));

  const total = totalCostOpen(draft.prize_pool);
  const deducted = await db.deductBalance(user.id, total);
  if (!deducted) return edit(ctx, `❌ Insufficient balance. Need $${vaeToUsd(total)}.`,
    Markup.inlineKeyboard([[Markup.button.callback('💳 Add Funds', 'buy_vae')]]));

  await db.recordTransaction(user.id, 'competition_setup', -total, null, `Competition: ${draft.title}`);

  const { data: comp } = await supabase.from('competitions').insert({
    requester_id: user.id,
    title: draft.title,
    description: draft.description,
    prize_pool: draft.prize_pool,
    prize_structure: { '1st': draft.prize_pool },
    setup_fee: COMP.setupFee(draft.prize_pool),
    platform_fee_pct: COMP.PLATFORM_FEE_PCT,
    setup_fee_paid: true,
    min_entries: COMP.MIN_ENTRIES_OPEN,
    winner_deadline_hours: COMP.WINNER_GRACE_HRS,
    location_required: draft.location_required || false,
    allowed_countries: draft.allowed_countries || [],
    deadline: new Date(Date.now() + draft.duration_days * 86400000).toISOString(),
    status: 'active',
    entry_count: 0,
  }).select().single();

  clearState(ctx.from.id);

  const shareLink = `https://t.me/LoopumanBot?start=comp_${comp.id}`;
  return edit(ctx,
    `🏆 <b>Competition Live!</b>\n\n"<b>${fmt.esc(draft.title)}</b>"\n💰 Prize: $${vaeToUsd(draft.prize_pool)}\n💳 Charged: $${vaeToUsd(total)}\n⏰ Duration: ${draft.duration_days} days\n${locationBadge(draft)}\n\n<b>Share your competition to get submissions:</b>\n<code>${shareLink}</code>\n\n<i>Post this link on LinkedIn, Twitter, or anywhere your audience is.</i>`,
    Markup.inlineKeyboard([
      [Markup.button.callback('👀 View Competition', `comp_view_${comp.id}`)],
      [Markup.button.callback('📊 My Competitions', 'my_competitions')],
    ])
  );
});

// ─── CONFIRM POST SOCIAL CONTEST ─────────────────────────────────────────────
bot.action('chal_confirm_post', async (ctx) => {
  await cb(ctx);
  const user = await db.getUser(ctx.from.id);
  const state = getState(ctx.from.id);
  const draft = state?.draft;
  if (!draft?.base_pay_per_post || !draft?.title) return edit(ctx, '❌ No draft found.',
    Markup.inlineKeyboard([[Markup.button.callback('🔙 Back', 'competitions_menu')]]));

  const deducted = await db.deductBalance(user.id, COMP.SETUP_FEE_SOCIAL);
  if (!deducted) return edit(ctx, `❌ Insufficient balance. Setup fee: $${vaeToUsd(COMP.SETUP_FEE_SOCIAL)}.`,
    Markup.inlineKeyboard([[Markup.button.callback('💳 Add Funds', 'buy_vae')]]));

  await db.recordTransaction(user.id, 'social_contest_setup', -COMP.SETUP_FEE_SOCIAL, null, `Contest: ${draft.title}`);

  const { data: chal } = await supabase.from('social_challenges').insert({
    requester_id: user.id,
    title: draft.title,
    description: draft.description,
    platform: draft.platform || 'Any',
    hashtag: draft.hashtag || null,
    base_pay_per_post: draft.base_pay_per_post,
    prize_structure: { '1st': draft.prize_1st || 0, '2nd': draft.prize_2nd || 0, '3rd': draft.prize_3rd || 0 },
    prize_pool: (draft.prize_1st || 0) + (draft.prize_2nd || 0) + (draft.prize_3rd || 0),
    setup_fee: COMP.SETUP_FEE_SOCIAL,
    platform_fee_pct: COMP.PLATFORM_FEE_PCT,
    setup_fee_paid: true,
    ai_content_allowed: true,
    requirements: draft.requirements || null,
    location_required: draft.location_required || false,
    allowed_countries: draft.allowed_countries || [],
    deadline: new Date(Date.now() + draft.duration_days * 86400000).toISOString(),
    status: 'active',
    entry_count: 0,
    approved_count: 0,
  }).select().single();

  clearState(ctx.from.id);

  const shareLink = `https://t.me/LoopumanBot?start=chal_${chal.id}`;
  return edit(ctx,
    `📱 <b>Social Contest Live!</b>\n\n"<b>${fmt.esc(draft.title)}</b>"\n💵 Base pay: $${vaeToUsd(draft.base_pay_per_post)}/post\n🥇$${vaeToUsd(draft.prize_1st||0)} 🥈$${vaeToUsd(draft.prize_2nd||0)} 🥉$${vaeToUsd(draft.prize_3rd||0)}\n💳 Setup charged: $${vaeToUsd(COMP.SETUP_FEE_SOCIAL)}\n⏰ Duration: ${draft.duration_days} days\n${locationBadge(draft)}\n\n<b>Share to attract content creators:</b>\n<code>${shareLink}</code>`,
    Markup.inlineKeyboard([
      [Markup.button.callback('👀 View Contest', `chal_view_${chal.id}`)],
      [Markup.button.callback('📊 My Competitions', 'my_competitions')],
    ])
  );
});

// ─── LOCATION PICKER ─────────────────────────────────────────────────────────
bot.action(/^comp_location_(.+)$/, async (ctx) => {
  await cb(ctx);
  const country = ctx.match[1];
  const state = getState(ctx.from.id);
  if (!state) return;
  const draft = state.draft;
  if (country === 'worldwide') {
    draft.location_required = false;
    draft.allowed_countries = [];
  } else {
    draft.location_required = true;
    if (!draft.allowed_countries.includes(country)) draft.allowed_countries.push(country);
  }
  updateState(ctx.from.id, { draft });
  // Continue to confirmation
  const action = state.action === 'create_competition' ? 'show_comp_review' : 'show_chal_review';
  ctx.match[1] = action;
  // Trigger review
  await _showReview(ctx, state.action, draft);
});

async function _showReview(ctx, action, draft) {
  if (action === 'create_competition') {
    const total = totalCostOpen(draft.prize_pool);
    return send(ctx,
      `🏆 <b>Review Your Competition</b>\n\n📋 <b>${fmt.esc(draft.title)}</b>\n📝 ${fmt.esc((draft.description||'').substring(0,100))}\n💰 Prize: $${vaeToUsd(draft.prize_pool)}\n⏰ Duration: ${draft.duration_days} days\n${locationBadge(draft)}\n💳 <b>Total charged: $${vaeToUsd(total)}</b>\n\n<i>Winner gets $${vaeToUsd(draft.prize_pool)} (100%)</i>`,
      Markup.inlineKeyboard([
        [Markup.button.callback('✅ Post Competition', 'comp_confirm_post')],
        [Markup.button.callback('❌ Cancel', 'competitions_menu')],
      ])
    );
  } else {
    const bonusTotal = (draft.prize_1st||0)+(draft.prize_2nd||0)+(draft.prize_3rd||0);
    return send(ctx,
      `📱 <b>Review Your Contest</b>\n\n📋 <b>${fmt.esc(draft.title)}</b>\n💵 Base pay: $${vaeToUsd(draft.base_pay_per_post)}/post\n🥇$${vaeToUsd(draft.prize_1st||0)} 🥈$${vaeToUsd(draft.prize_2nd||0)} 🥉$${vaeToUsd(draft.prize_3rd||0)}\n⏰ ${draft.duration_days} days\n${locationBadge(draft)}\n💳 Setup now: $${vaeToUsd(COMP.SETUP_FEE_SOCIAL)}\n\n<i>Each approval costs $${vaeToUsd(draft.base_pay_per_post + platformFee(draft.base_pay_per_post))} incl. fee</i>`,
      Markup.inlineKeyboard([
        [Markup.button.callback('🚀 Launch Contest', 'chal_confirm_post')],
        [Markup.button.callback('❌ Cancel', 'competitions_menu')],
      ])
    );
  }
}

// ─── TEXT HANDLER — competition states ───────────────────────────────────────
// This secondary handler fires AFTER the main bot.on('text')
// The main handler's switch() falls through for unknown actions
// These cases handle competition-specific actions
bot.on('text', async (ctx, next) => {
  const state = getState(ctx.from.id);
  if (!state) return next();

  const action = state.action;
  const text = ctx.message.text.trim();

  try {
    // ── Worker: submit open competition entry ─────────────────────────────
    if (action === 'comp_entry') {
      const user = await db.getUser(ctx.from.id);
      const { data: comp } = await supabase.from('competitions')
        .select('title,prize_pool,entry_count').eq('id', state.compId).single();
      await supabase.from('competition_entries').upsert({
        competition_id: state.compId, user_id: user.id,
        content: text, files: state.files || [], status: 'submitted',
        worker_wallet: user.crypto_address || null,
      }, { onConflict: 'competition_id,user_id' });
      await supabase.from('competitions').update({ entry_count: (comp?.entry_count || 0) + 1 }).eq('id', state.compId);
      clearState(ctx.from.id);
      return send(ctx,
        `✅ <b>Entry Submitted!</b>\n\n<b>${fmt.esc(comp?.title||'')}</b>\nPrize: $${vaeToUsd(comp?.prize_pool||0)}\n\nGood luck! 🍀 You'll be notified when a winner is picked.`,
        Markup.inlineKeyboard([
          [Markup.button.callback('🏆 Browse More', 'competitions_menu')],
          [Markup.button.callback('🔙 Menu', 'menu')],
        ])
      );
    }

    // ── Worker: submit social contest post URL ────────────────────────────
    if (action === 'chal_entry') {
      const user = await db.getUser(ctx.from.id);
      const { data: chal } = await supabase.from('social_challenges')
        .select('title,base_pay_per_post,platform,entry_count').eq('id', state.chalId).single();
      const platform = text.includes('tiktok') ? 'TikTok'
        : text.includes('instagram') ? 'Instagram'
        : text.includes('youtube')||text.includes('youtu.be') ? 'YouTube'
        : text.includes('twitter')||text.includes('x.com') ? 'X/Twitter'
        : chal?.platform || 'Other';
      await supabase.from('challenge_entries').insert({
        challenge_id: state.chalId, user_id: user.id,
        post_url: text, post_link: text, platform, status: 'pending',
        worker_wallet: user.crypto_address || null,
      });
      await supabase.from('social_challenges').update({ entry_count: (chal?.entry_count||0)+1 }).eq('id', state.chalId);
      clearState(ctx.from.id);
      return send(ctx,
        `📤 <b>Submitted for Review!</b>\n\n<b>${fmt.esc(chal?.title||'')}</b>\nPlatform: ${platform}\n\nOnce approved: <b>$${vaeToUsd(chal?.base_pay_per_post||0)} instantly!</b>\n🏆 Keep getting engagement — requester picks top 3 for bonus prizes!`,
        Markup.inlineKeyboard([
          [Markup.button.callback('📱 More Contests', 'competitions_menu')],
          [Markup.button.callback('🔙 Menu', 'menu')],
        ])
      );
    }

    // ── Requester: reject reason for social contest ───────────────────────
    if (action === 'chal_reject_reason') {
      await supabase.from('challenge_entries').update({ status: 'rejected' }).eq('id', state.entryId);
      const { data: e } = await supabase.from('challenge_entries')
        .select('user_id,worker:app_users(telegram_id)').eq('id', state.entryId).single();
      const { data: chal } = await supabase.from('social_challenges').select('title').eq('id', state.chalId).single();
      if (e?.worker?.telegram_id) {
        await _notifyComp(e.worker.telegram_id,
          `❌ Your submission for "<b>${fmt.esc(chal?.title||'')}</b>" was not approved.\n\nReason: ${fmt.esc(text)}\n\nAdjust and resubmit if the contest is still open.`
        );
      }
      clearState(ctx.from.id);
      const user = await db.getUser(ctx.from.id);
      return reviewChallengeSubmissions(ctx, state.chalId, supabase, edit, Markup, fmt, user.id);
    }

    // ── Requester: create open competition steps ──────────────────────────
    if (action === 'create_competition') {
      const draft = state.draft;
      const step = state.step;

      if (step === 'title') {
        draft.title = text;
        setState(ctx.from.id, { ...state, step: 'description', draft });
        return send(ctx,
          `✅ Title: "<b>${fmt.esc(text)}</b>"\n\n<b>Step 2 of 5: Describe your competition</b>\n<i>What should workers create or submit? Be specific about requirements.</i>`,
          Markup.inlineKeyboard([[Markup.button.callback('❌ Cancel', 'competitions_menu')]])
        );
      }
      if (step === 'description') {
        draft.description = text;
        setState(ctx.from.id, { ...state, step: 'prize', draft });
        return send(ctx,
          `✅ Description set!\n\n<b>Step 3 of 5: Set your prize amount (USD)</b>\n• Minimum: $50\n• Workers keep 100% of prize\n<i>Just send the dollar amount, e.g. "200"</i>`,
          Markup.inlineKeyboard([[Markup.button.callback('❌ Cancel', 'competitions_menu')]])
        );
      }
      if (step === 'prize') {
        const amt = Math.round(parseFloat(text.replace(/[^0-9.]/g,'')) * 100);
        if (!amt || amt < COMP.MIN_PRIZE_OPEN) return send(ctx, `❌ Minimum prize is $${vaeToUsd(COMP.MIN_PRIZE_OPEN)}.`);
        draft.prize_pool = amt;
        const setup = COMP.setupFee(amt);
        const total = totalCostOpen(amt);
        setState(ctx.from.id, { ...state, step: 'duration', draft });
        return send(ctx,
          `✅ Prize: <b>$${vaeToUsd(amt)}</b>\n\n💰 Cost breakdown:\n• Prize: $${vaeToUsd(amt)}\n• Platform fee (25%): $${vaeToUsd(platformFee(amt))}\n• Setup fee: $${vaeToUsd(setup)}\n• <b>Total: $${vaeToUsd(total)}</b>\n\n<b>Step 4 of 5: How many days? (1–90)</b>`,
          Markup.inlineKeyboard([[Markup.button.callback('❌ Cancel', 'competitions_menu')]])
        );
      }
      if (step === 'duration') {
        const days = parseInt(text);
        if (!days || days < 1 || days > 90) return send(ctx, '❌ Please enter 1–90.');
        draft.duration_days = days;
        setState(ctx.from.id, { ...state, step: 'location', draft });
        // Location picker
        const btns = TOP_COUNTRIES.map(c => [Markup.button.callback(
          c === 'Worldwide' ? '🌍 Worldwide (open to all)' : `📍 ${c}`,
          `comp_location_${c === 'Worldwide' ? 'worldwide' : c}`
        )]);
        return send(ctx,
          `<b>Step 5 of 5: Location restriction</b>\n\nWho can enter this competition?`,
          Markup.inlineKeyboard(btns)
        );
      }
      return next();
    }

    // ── Requester: create social contest steps ────────────────────────────
    if (action === 'create_challenge') {
      const draft = state.draft;
      const step = state.step;

      if (step === 'title') {
        draft.title = text;
        setState(ctx.from.id, { ...state, step: 'description', draft });
        return send(ctx,
          `✅ Title: "<b>${fmt.esc(text)}</b>"\n\n<b>Step 2 of 6: Describe your challenge</b>\n<i>What should participants post? What message/style/format?</i>`,
          Markup.inlineKeyboard([[Markup.button.callback('❌ Cancel', 'competitions_menu')]])
        );
      }
      if (step === 'description') {
        draft.description = text;
        setState(ctx.from.id, { ...state, step: 'platform', draft });
        return send(ctx,
          `✅ Description set!\n\n<b>Step 3 of 6: Which platform?</b>`,
          Markup.inlineKeyboard([
            [Markup.button.callback('TikTok', 'chal_platform_TikTok'), Markup.button.callback('Instagram', 'chal_platform_Instagram')],
            [Markup.button.callback('YouTube', 'chal_platform_YouTube'), Markup.button.callback('X/Twitter', 'chal_platform_X/Twitter')],
            [Markup.button.callback('🌍 Any Platform', 'chal_platform_Any')],
          ])
        );
      }
      if (step === 'base_pay') {
        const amt = Math.round(parseFloat(text.replace(/[^0-9.]/g,'')) * 100);
        if (!amt || amt < COMP.MIN_BASE_PAY) return send(ctx, `❌ Minimum base pay is $${vaeToUsd(COMP.MIN_BASE_PAY)}.`);
        draft.base_pay_per_post = amt;
        setState(ctx.from.id, { ...state, step: 'bonuses', draft });
        return send(ctx,
          `✅ Base pay: <b>$${vaeToUsd(amt)}/post</b>\n\n<b>Step 5 of 6: Set bonus prizes for top 3</b>\nSend 3 amounts separated by commas:\n<i>e.g. "50,25,10" → 🥇$50 🥈$25 🥉$10</i>\n\nOr send "0,0,0" for no bonuses.`,
          Markup.inlineKeyboard([[Markup.button.callback('❌ Cancel', 'competitions_menu')]])
        );
      }
      if (step === 'bonuses') {
        const parts = text.split(',').map(x => Math.round(parseFloat(x.trim()) * 100));
        if (parts.length < 3 || parts.some(isNaN) || parts.some(n => n < 0)) {
          return send(ctx, '❌ Send 3 amounts separated by commas, e.g. "50,25,10"');
        }
        draft.prize_1st = parts[0]; draft.prize_2nd = parts[1]; draft.prize_3rd = parts[2];
        setState(ctx.from.id, { ...state, step: 'duration', draft });
        return send(ctx,
          `✅ Bonuses: 🥇$${vaeToUsd(parts[0])} 🥈$${vaeToUsd(parts[1])} 🥉$${vaeToUsd(parts[2])}\n\n<b>Step 6 of 6: How many days? (3–90)</b>`,
          Markup.inlineKeyboard([[Markup.button.callback('❌ Cancel', 'competitions_menu')]])
        );
      }
      if (step === 'duration') {
        const days = parseInt(text);
        if (!days || days < 3 || days > 90) return send(ctx, '❌ Please enter 3–90.');
        draft.duration_days = days;
        setState(ctx.from.id, { ...state, step: 'location', draft });
        const btns = TOP_COUNTRIES.map(c => [Markup.button.callback(
          c === 'Worldwide' ? '🌍 Worldwide (open to all)' : `📍 ${c}`,
          `comp_location_${c === 'Worldwide' ? 'worldwide' : c}`
        )]);
        return send(ctx,
          `<b>Step 6 of 6: Location restriction</b>\n\nWho can enter this contest?`,
          Markup.inlineKeyboard(btns)
        );
      }
      return next();
    }

  } catch (e) {
    console.error(`[Competition Text] ${action}:`, e.message);
    await send(ctx, '❌ Something went wrong. Please try again.',
      Markup.inlineKeyboard([[Markup.button.callback('🔙 Menu', 'menu')]]));
  }

  return next();
});

// ─── PLATFORM PICKER for social contest ──────────────────────────────────────
bot.action(/^chal_platform_(.+)$/, async (ctx) => {
  await cb(ctx);
  const platform = ctx.match[1];
  const state = getState(ctx.from.id);
  if (!state) return;
  const draft = state.draft;
  draft.platform = platform;
  setState(ctx.from.id, { ...state, step: 'base_pay', draft });
  return edit(ctx,
    `✅ Platform: <b>${platform}</b>\n\n<b>Step 4 of 6: Set base pay per approved post (USD)</b>\n• Minimum: $3\n• Every approved post earns this instantly\n<i>Send the amount, e.g. "5"</i>`,
    Markup.inlineKeyboard([[Markup.button.callback('❌ Cancel', 'competitions_menu')]])
  );
});

// ─── PHOTO/DOCUMENT for competition entries ───────────────────────────────────
bot.on(['photo', 'document'], async (ctx, next) => {
  const state = getState(ctx.from.id);
  if (state?.action !== 'comp_entry') return next();
  const fileId = ctx.message?.photo?.slice(-1)[0]?.file_id || ctx.message?.document?.file_id;
  if (fileId) {
    const files = state.files || [];
    files.push(fileId);
    updateState(ctx.from.id, { files });
    await ctx.reply('📎 File received! Send more files or send text to complete your submission.');
  }
});

// ═══════════════════════════════════════════════════════════════════════════════
// END COMPETITION BOT v2
// ═══════════════════════════════════════════════════════════════════════════════
