/**
 * LOOPUMAN - SCHEDULER v3.1 FIXED
 * Automated tasks: auto-approve, expire tasks, process referrals
 * 
 * FIX: Made ai-agents import optional to prevent MODULE_NOT_FOUND
 */
'use strict';
require('dotenv').config();

const { createClient } = require('@supabase/supabase-js');

// Try to load ai-agents, but don't crash if it's missing
let aiAgents = null;
try {
  aiAgents = require('./ai-agents');
  console.log('✅ AI agents loaded');
} catch (e) {
  console.log('⚠️ AI agents not available:', e.message);
}

// Load blockchain services (deposit monitoring)
let blockchainService = null;
let depositListener = null;
let adminAlerts = null;
try {
  blockchainService = require('./services/blockchain-service');
  console.log('✅ Blockchain service loaded');
} catch (e) {
  console.log('⚠️ Blockchain service not available:', e.message);
}
try {
  depositListener = require('./services/deposit-listener');
  console.log('✅ Deposit listener loaded');

try {
  adminAlerts = require('./services/admin-alerts');
  adminAlerts.start();
  console.log('✅ Admin alerts service loaded');
} catch (e) {
  console.log('⚠️ Admin alerts not available:', e.message);
}
} catch (e) {
  console.log('⚠️ Deposit listener not available:', e.message);
}

const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_SERVICE_KEY);

const CONFIG = {
  AUTO_APPROVE_HOURS: 48,
  REFERRAL_DELAY_DAYS: 28,
  EXPIRE_CHECK_INTERVAL: 60 * 60 * 1000, // 1 hour
  AUTO_APPROVE_INTERVAL: 30 * 60 * 1000, // 30 min
  REFERRAL_INTERVAL: 6 * 60 * 60 * 1000, // 6 hours
};

// Auto-approve submissions after 48 hours
async function autoApproveSubmissions() {
  console.log('[Scheduler] Checking auto-approvals...');
  // Value-based: 24hr micro, 48hr standard, 72hr premium
  const now = Date.now();
  const cutoff = new Date(now - 24 * 60 * 60 * 1000).toISOString();
  const cutoff48 = new Date(now - 48 * 60 * 60 * 1000).toISOString();
  const cutoff72 = new Date(now - 72 * 60 * 60 * 1000).toISOString();

  const { data: subs, error } = await supabase.from('submissions')
    .select('*, task:tasks(budget, title), worker:app_users(id, telegram_id, tasks_completed, tasks_approved)')
    .eq('status', 'submitted')
    .lt('submitted_at', cutoff);

  if (error) {
    console.error('[Scheduler] Auto-approve query error:', error);
    return;
  }

  if (!subs?.length) { 
    console.log('[Scheduler] No auto-approvals needed'); 
    return; 
  }


  // Filter by value-based tier timing: 24hr micro, 48hr standard, 72hr premium
  const eligibleSubs = subs.filter(sub => {
    const budget = sub.task?.budget || 0;
    const submittedAt = sub.submitted_at;
    if (budget <= 100) return true;
    if (budget <= 500) return submittedAt < cutoff48;
    return submittedAt < cutoff72;
  });

  if (!eligibleSubs.length) {
    console.log('[Scheduler] No eligible auto-approvals (value tier)');
    return;
  }

  for (const sub of eligibleSubs) {
    try {
      // Approve
      await supabase.from('submissions').update({ 
        status: 'approved', 
        approved_at: new Date().toISOString() 
      }).eq('id', sub.id);

      // Pay worker (atomic)
      const payment = sub.worker_payment || Math.floor((sub.task?.budget || 0) * 0.8);
      if (payment > 0) {
        await supabase.rpc('increment_balance', {
          p_user_id: sub.worker.id,
          p_amount: payment,
          p_balance_type: 'earned',
        });
      }

      // Record transaction
      await supabase.from('transactions').insert({
        user_id: sub.worker.id,
        type: 'task_payment',
        amount: payment,
        task_id: sub.task_id,
        description: `Auto-approved: ${sub.task?.title}`,
      });

      // Update worker trust score (+5 per auto-approved task)
      await supabase.from('app_users').update({
        trust_score: Math.min(200, (sub.worker?.trust_score || 30) + 5),
      }).eq('id', sub.worker.id);

      // Update worker stats
      await supabase.from('app_users').update({
        tasks_completed: (sub.worker.tasks_completed || 0) + 1,
        tasks_approved: (sub.worker.tasks_approved || 0) + 1,
      }).eq('id', sub.worker.id);

      console.log(`[Scheduler] Auto-approved: ${sub.id.slice(0, 8)}`);
    } catch (err) {
      console.error(`[Scheduler] Auto-approve error for ${sub.id}:`, err);
    }
  }
}

// Expire old tasks
async function expireTasks() {
  console.log('[Scheduler] Checking expired tasks...');
  const now = new Date().toISOString();

  const { data: tasks, error } = await supabase.from('tasks')
    .select('id, title, budget, requester_id')
    .eq('status', 'active')
    .lt('expires_at', now);

  if (error) {
    console.error('[Scheduler] Expire query error:', error);
    return;
  }

  if (!tasks?.length) { 
    console.log('[Scheduler] No expired tasks'); 
    return; 
  }

  for (const task of tasks) {
    try {
      // Check for submissions
      const { data: subs } = await supabase.from('submissions')
        .select('id, status, worker_id, worker_payment, worker:app_users(id, telegram_id, tasks_completed, tasks_approved)')
        .eq('task_id', task.id);

      const hasActive = subs?.some(s => ['in_progress', 'submitted'].includes(s.status));

      if (hasActive) {
        // Auto-approve pending submissions on expiry
        for (const sub of subs.filter(s => s.status === 'submitted')) {
          await supabase.from('submissions').update({
            status: 'approved',
            approved_at: now,
          }).eq('id', sub.id);
          // Pay worker (atomic)
          if (sub.worker_payment && sub.worker_id) {
            await supabase.rpc('increment_balance', {
              p_user_id: sub.worker_id,
              p_amount: sub.worker_payment,
              p_balance_type: 'earned',
            });
            await supabase.from('transactions').insert({
              user_id: sub.worker_id,
              type: 'task_payment',
              amount: sub.worker_payment,
              task_id: task.id,
              description: 'Auto-approved (expired): ' + (task.title || ''),
            });
            if (sub.worker) {
              await supabase.from('app_users').update({
                tasks_completed: (sub.worker.tasks_completed || 0) + 1,
                tasks_approved: (sub.worker.tasks_approved || 0) + 1,
              }).eq('id', sub.worker_id);
            }
          }
          console.log('[Scheduler] Auto-approved expired: ' + sub.id.slice(0, 8) + ' — worker paid');
        }
        // Refund in_progress (not submitted) workers
        for (const sub of subs.filter(s => s.status === 'in_progress')) {
          await supabase.from('submissions').update({ status: 'cancelled' }).eq('id', sub.id);
          // Clear pending balance
          const { data: workerBal } = await supabase.from('vae_balances').select('pending').eq('user_id', sub.worker_id).single();
          const payment = Math.floor(task.budget * 0.8);
          await supabase.from('vae_balances').update({ pending: Math.max(0, (workerBal?.pending || 0) - payment) }).eq('user_id', sub.worker_id);
        }
      } else {
        // Refund requester (atomic — available_only, not earned)
        await supabase.rpc('increment_balance', {
          p_user_id: task.requester_id,
          p_amount: task.budget,
          p_balance_type: 'available_only',
        });

        await supabase.from('transactions').insert({
          user_id: task.requester_id,
          type: 'refund',
          amount: task.budget,
          task_id: task.id,
          description: `Expired: ${task.title}`,
        });
      }

      await supabase.from('tasks').update({ status: 'expired' }).eq('id', task.id);
      console.log(`[Scheduler] Expired: ${task.id.slice(0, 8)}`);
    } catch (err) {
      console.error(`[Scheduler] Expire error for ${task.id}:`, err);
    }
  }
}

// Process referral bonuses (after 28-day delay)
async function processReferralBonuses() {
  console.log('[Scheduler] Processing referral bonuses...');
  const cutoff = new Date(Date.now() - CONFIG.REFERRAL_DELAY_DAYS * 24 * 60 * 60 * 1000).toISOString();

  const { data: txs, error } = await supabase.from('transactions')
    .select('*, user:app_users(referred_by)')
    .eq('type', 'task_payment')
    .lt('created_at', cutoff)
    .is('metadata->referral_processed', null);

  if (error) {
    console.error('[Scheduler] Referral query error:', error);
    return;
  }

  if (!txs?.length) { 
    console.log('[Scheduler] No referral bonuses to process'); 
    return; 
  }

  for (const tx of txs) {
    if (!tx.user?.referred_by) continue;

    try {
      const bonus = Math.floor(tx.amount * 0.01); // 1%
      if (bonus <= 0) continue;

      // Credit referrer (atomic)
      await supabase.rpc('increment_balance', {
        p_user_id: tx.user.referred_by,
        p_amount: bonus,
        p_balance_type: 'earned',
      });

      await supabase.from('transactions').insert({
        user_id: tx.user.referred_by,
        type: 'referral_bonus',
        amount: bonus,
        description: 'Referral earning (1%)',
      });

      // Mark as processed
      await supabase.from('transactions').update({
        metadata: { ...(tx.metadata || {}), referral_processed: true }
      }).eq('id', tx.id);

      console.log(`[Scheduler] Referral bonus: ${bonus} VAE`);
    } catch (err) {
      console.error(`[Scheduler] Referral error for ${tx.id}:`, err);
    }
  }
}

// Send daily summary to admins
async function sendDailySummary() {
  try {
    const adminBot = require('./admin-bot');
    await adminBot.sendDailySummary();
    console.log('[Scheduler] Daily summary sent');
  } catch (e) {
    console.error('[Scheduler] Daily summary error:', e.message);
  }
}

// Clean up stale sessions
async function cleanupStaleSessions() {
  console.log('[Scheduler] Cleanup complete');
}

// Start scheduler
async function start() {
  console.log('');
  console.log('╔═══════════════════════════════════════════════════════════════╗');
  console.log('║     ⏰ LOOPUMAN SCHEDULER v3.1 FIXED                          ║');
  console.log('╠═══════════════════════════════════════════════════════════════╣');
  console.log('║  ✅ Auto-approve after 48 hours                               ║');
  console.log('║  ✅ Expire old tasks                                          ║');
  console.log('║  ✅ Process referral bonuses (28-day delay)                   ║');
  console.log('║  ✅ Daily admin summary                                       ║');
  console.log('╚═══════════════════════════════════════════════════════════════╝');
  console.log('');

  // Initial runs
  try {
    await autoApproveSubmissions();
    await expireTasks();
    await processReferralBonuses();
    // Deposit monitoring
    if (blockchainService?.retryFailedWithdrawals) {
      await blockchainService.retryFailedWithdrawals();
      console.log('[Scheduler] ✅ Retried failed withdrawals');
    }
    if (depositListener?.scanForDeposits) {
      await depositListener.scanForDeposits(120); // Last 120 minutes
      console.log('[Scheduler] ✅ Scanned for deposits');
    }
  } catch (err) {
    console.error('[Scheduler] Initial run error:', err);
  }

  // Schedule intervals
  setInterval(autoApproveSubmissions, CONFIG.AUTO_APPROVE_INTERVAL);
  setInterval(expireTasks, CONFIG.EXPIRE_CHECK_INTERVAL);
  setInterval(processReferralBonuses, CONFIG.REFERRAL_INTERVAL);
  setInterval(cleanupStaleSessions, 60 * 60 * 1000);
  
  // Deposit monitoring intervals
  if (blockchainService?.retryFailedWithdrawals) {
    setInterval(() => blockchainService.retryFailedWithdrawals().catch(e => console.error('[Scheduler] Withdrawal retry error:', e)), 30 * 60 * 1000); // Every 30 min
  }
  if (depositListener?.scanForDeposits) {
    setInterval(() => depositListener.scanForDeposits(5).catch(e => console.error('[Scheduler] Deposit scan error:', e)), 2 * 60 * 1000); // Every 2 min
  }

  // Daily summary at midnight
  const now = new Date();
  const midnight = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1, 0, 0, 0);
  const msUntilMidnight = midnight - now;
  
  setTimeout(() => {
    sendDailySummary();
    setInterval(sendDailySummary, 24 * 60 * 60 * 1000);
  }, msUntilMidnight);
  console.log('[Scheduler] Started! Next daily summary soon');
  const { runCompetitionScheduler } = require('./competition_module');
  const _compNotify = async (tid, msg) => {
    try {
      const axios = require('axios');
      await axios.post('https://api.telegram.org/bot' + process.env.TELEGRAM_BOT_TOKEN + '/sendMessage', { chat_id: String(tid), text: msg, parse_mode: 'HTML' });
    } catch(e) {}
  };
  setInterval(async () => {
    try { await runCompetitionScheduler(supabase, db, _compNotify, fmt); }
    catch(e) { console.error('[Scheduler] Competition error:', e.message); }
  }, 60 * 60 * 1000);
  console.log('[Scheduler] Competition scheduler registered (hourly)');
}

// Nudge/Bid: Mark stale tasks as biddable
async function markBiddableTasks() {
  console.log("[Scheduler] Checking for stale tasks to mark biddable...");
  const now = new Date();
  const in24hours = new Date(now.getTime() + 24 * 60 * 60 * 1000);
  const { data: tasks, error } = await supabase.from("tasks")
    .select("id, created_at, expires_at, is_biddable, budget_vae, title, current_workers")
    .in("status", ["open", "active"]).eq("is_biddable", false).lt("current_workers", 1);
  if (error) { console.error("[Scheduler] Biddable check error:", error.message); return; }
  if (!tasks?.length) { console.log("[Scheduler] No new biddable tasks"); return; }
  let marked = 0;
  for (const task of tasks) {
    const created = new Date(task.created_at);
    const expires = task.expires_at ? new Date(task.expires_at) : null;
    if (!expires) continue;
    const totalLifetime = expires.getTime() - created.getTime();
    const elapsed = now.getTime() - created.getTime();
    if (elapsed > totalLifetime * 0.5 || expires <= in24hours) {
      await supabase.from("tasks").update({ is_biddable: true, biddable_at: now.toISOString() }).eq("id", task.id);
      marked++;
    }
  }
  const cutoff48h = new Date(now.getTime() - 48 * 60 * 60 * 1000).toISOString();
  await supabase.from("task_bids").update({ status: "expired" }).eq("status", "pending").lt("created_at", cutoff48h);
  console.log("[Scheduler] Marked " + marked + " tasks as biddable");
}
setInterval(markBiddableTasks, 30 * 60 * 1000);
markBiddableTasks();

module.exports = { start, autoApproveSubmissions, expireTasks, processReferralBonuses };
if (require.main === module) start();
