// ═══════════════════════════════════════════════════════════════════════════════
// LOOPUMAN ADMIN ALERTS SERVICE
// Created: February 11, 2026
// ═══════════════════════════════════════════════════════════════════════════════
// 1. Real-time push alerts (deposits, withdrawals, disputes, errors)
// 2. Daily digest (auto-sent every morning)
// 3. PM2 service health monitoring
// ═══════════════════════════════════════════════════════════════════════════════

require('dotenv').config();
const { createClient } = require('@supabase/supabase-js');
const { exec } = require('child_process');
const https = require('https');

const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_SERVICE_KEY);
const ADMIN_CHAT_ID = process.env.ADMIN_TELEGRAM_IDS || process.env.ADMIN_TELEGRAM_ID;
const BOT_TOKEN = process.env.ADMIN_BOT_TOKEN;

// ─── Send Telegram Message ──────────────────────────────────────────────────
function sendAlert(text) {
  if (!ADMIN_CHAT_ID || !BOT_TOKEN) return;
  const url = `https://api.telegram.org/bot${BOT_TOKEN}/sendMessage`;
  const body = JSON.stringify({
    chat_id: ADMIN_CHAT_ID,
    text,
    parse_mode: 'HTML',
    disable_notification: false,
  });
  const req = https.request(url, { method: 'POST', headers: { 'Content-Type': 'application/json' } });
  req.on('error', (e) => console.log('[Alerts] Send failed:', e.message));
  req.write(body);
  req.end();
}

// ─── Real-Time Monitors ─────────────────────────────────────────────────────

let lastChecked = {
  stripeDeposit: new Date().toISOString(),
  cryptoDeposit: new Date().toISOString(),
  withdrawal: new Date().toISOString(),
  dispute: new Date().toISOString(),
  ticket: new Date().toISOString(),
  report: new Date().toISOString(),
};

async function checkNewEvents() {
  try {
    const since = lastChecked.stripeDeposit;
    const now = new Date().toISOString();

    // New Stripe deposits
    const { data: newStripe } = await supabase.from('transactions')
      .select('amount, user_id, created_at')
      .eq('type', 'stripe_deposit')
      .gt('created_at', since)
      .order('created_at', { ascending: false });

    if (newStripe && newStripe.length > 0) {
      for (const d of newStripe) {
        const usd = (d.amount / 100).toFixed(2);
        sendAlert(`💳 <b>STRIPE DEPOSIT</b>\n\nⒶ${d.amount} VAE ($${usd})\nUser: <code>${d.user_id.slice(0, 8)}...</code>\nTime: ${new Date(d.created_at).toLocaleTimeString()}`);
      }
    }

    // New crypto deposits
    const { data: newCrypto } = await supabase.from('crypto_deposits')
      .select('amount_vae, amount_usd, stablecoin, user_id, created_at')
      .eq('status', 'completed')
      .gt('created_at', lastChecked.cryptoDeposit)
      .order('created_at', { ascending: false });

    if (newCrypto && newCrypto.length > 0) {
      for (const d of newCrypto) {
        sendAlert(`🔗 <b>CRYPTO DEPOSIT</b>\n\nⒶ${d.amount_vae} VAE ($${d.amount_usd?.toFixed(2)})\n${d.stablecoin}\nUser: <code>${d.user_id.slice(0, 8)}...</code>`);
      }
    }

    // New pending withdrawals
    const { data: newWd } = await supabase.from('withdrawals')
      .select('amount_vae, user_id, stablecoin, created_at')
      .eq('status', 'pending')
      .gt('created_at', lastChecked.withdrawal)
      .order('created_at', { ascending: false });

    if (newWd && newWd.length > 0) {
      for (const w of newWd) {
        sendAlert(`⚠️ <b>WITHDRAWAL REQUEST</b>\n\nⒶ${w.amount_vae} VAE ${w.stablecoin || ''}\nUser: <code>${w.user_id.slice(0, 8)}...</code>\n\n👉 Check Admin Bot to approve/reject`);
      }
    }

    // New disputes
    const { data: newDisp } = await supabase.from('disputes')
      .select('id, reason, created_at')
      .eq('status', 'open')
      .gt('created_at', lastChecked.dispute)
      .order('created_at', { ascending: false });

    if (newDisp && newDisp.length > 0) {
      for (const d of newDisp) {
        sendAlert(`🚨 <b>NEW DISPUTE</b>\n\nReason: ${(d.reason || 'No reason').slice(0, 100)}\n\n👉 Check Admin Bot to resolve`);
      }
    }

    // New support tickets
    const { data: newTix } = await supabase.from('support_tickets')
      .select('id, subject, created_at')
      .eq('status', 'open')
      .gt('created_at', lastChecked.ticket)
      .order('created_at', { ascending: false });

    if (newTix && newTix.length > 0) {
      for (const t of newTix) {
        sendAlert(`🎫 <b>NEW TICKET</b>\n\n${(t.subject || 'No subject').slice(0, 100)}\n\n👉 Check Admin Bot`);
      }
    }

    // Update timestamps
    lastChecked.stripeDeposit = now;
    lastChecked.cryptoDeposit = now;
    lastChecked.withdrawal = now;
    lastChecked.dispute = now;
    lastChecked.ticket = now;

  } catch (e) {
    console.error('[Alerts] Check error:', e.message);
  }
}

// ─── PM2 Health Monitor ─────────────────────────────────────────────────────

const EXPECTED_SERVICES = ['telegram-bot', 'whatsapp-bot', 'ai-agents', 'admin-bot', 'scheduler', 'enterprise-api'];
let lastRestartCounts = {};

function checkPM2Health() {
  exec('pm2 jlist', (err, stdout) => {
    if (err) {
      sendAlert('🔴 <b>PM2 ERROR</b>\n\nCannot reach PM2. Server may be down!');
      return;
    }
    try {
      const procs = JSON.parse(stdout);
      const alerts = [];

      for (const name of EXPECTED_SERVICES) {
        const proc = procs.find(p => p.name === name);
        if (!proc) {
          alerts.push(`❌ ${name}: NOT FOUND`);
        } else if (proc.pm2_env.status !== 'online') {
          alerts.push(`🔴 ${name}: ${proc.pm2_env.status}`);
        } else {
          // Check for crash loops (rapid restarts)
          const restarts = proc.pm2_env.restart_time || 0;
          const lastCount = lastRestartCounts[name] || restarts;
          const newRestarts = restarts - lastCount;
          if (newRestarts > 5) {
            alerts.push(`⚠️ ${name}: ${newRestarts} restarts in last check!`);
          }
          lastRestartCounts[name] = restarts;
        }
      }

      if (alerts.length > 0) {
        sendAlert('🔴 <b>SERVICE ALERT</b>\n━━━━━━━━━━━━━━━━\n\n' + alerts.join('\n'));
      }
    } catch (e) {
      console.error('[Health] Parse error:', e.message);
    }
  });
}

// ─── Daily Digest ────────────────────────────────────────────────────────────

async function sendDailyDigest() {
  try {
    const now = new Date();
    const yesterday = new Date(now);
    yesterday.setDate(yesterday.getDate() - 1);
    const yIso = yesterday.toISOString();

    // Yesterday's new users
    const { count: newUsers } = await supabase.from('app_users')
      .select('*', { count: 'exact', head: true })
      .gte('created_at', yIso)
      .not('telegram_id', 'like', 'ai_%');

    // Yesterday's Stripe deposits
    const { data: yStripe } = await supabase.from('transactions')
      .select('amount')
      .eq('type', 'stripe_deposit')
      .gte('created_at', yIso);
    const stripeVae = yStripe?.reduce((a, b) => a + (b.amount || 0), 0) || 0;

    // Yesterday's crypto deposits
    const { data: yCrypto } = await supabase.from('crypto_deposits')
      .select('amount_vae')
      .eq('status', 'completed')
      .gte('created_at', yIso);
    const cryptoVae = yCrypto?.reduce((a, b) => a + (b.amount_vae || 0), 0) || 0;

    // Yesterday's tasks
    const { count: newTasks } = await supabase.from('tasks')
      .select('*', { count: 'exact', head: true })
      .gte('created_at', yIso);

    const { count: completedTasks } = await supabase.from('tasks')
      .select('*', { count: 'exact', head: true })
      .eq('status', 'completed')
      .gte('updated_at', yIso);

    // Pending actions
    const { count: pendWd } = await supabase.from('withdrawals')
      .select('*', { count: 'exact', head: true })
      .eq('status', 'pending');

    const { count: openDisp } = await supabase.from('disputes')
      .select('*', { count: 'exact', head: true })
      .eq('status', 'open');

    const { count: openTix } = await supabase.from('support_tickets')
      .select('*', { count: 'exact', head: true })
      .eq('status', 'open');

    // Total balances across all users
    const { data: allBals } = await supabase.from('vae_balances')
      .select('available');
    const totalFloat = allBals?.reduce((a, b) => a + (b.available || 0), 0) || 0;

    const totalDepositsVae = stripeVae + cryptoVae;
    const totalDepositsUsd = (totalDepositsVae / 100).toFixed(2);

    let msg = '☀️ <b>DAILY DIGEST</b>\n━━━━━━━━━━━━━━━━━━━━\n';
    msg += `📅 ${now.toLocaleDateString('en-GB', { weekday: 'long', day: 'numeric', month: 'short' })}\n\n`;

    msg += '<b>💰 REVENUE (24h)</b>\n';
    msg += `   💳 Stripe: $${(stripeVae / 100).toFixed(2)} (Ⓥ${stripeVae.toLocaleString()})\n`;
    msg += `   🔗 Crypto: $${(cryptoVae / 100).toFixed(2)} (Ⓥ${cryptoVae.toLocaleString()})\n`;
    msg += `   📊 Total: $${totalDepositsUsd} (Ⓥ${totalDepositsVae.toLocaleString()})\n\n`;

    msg += '<b>👥 USERS</b>\n';
    msg += `   +${newUsers || 0} new signups\n\n`;

    msg += '<b>📋 TASKS</b>\n';
    msg += `   ${newTasks || 0} posted | ${completedTasks || 0} completed\n\n`;

    msg += '<b>🏦 PLATFORM FLOAT</b>\n';
    msg += `   Ⓥ${totalFloat.toLocaleString()} ($${(totalFloat / 100).toFixed(2)}) across all users\n\n`;

    if ((pendWd || 0) + (openDisp || 0) + (openTix || 0) > 0) {
      msg += '<b>⚠️ NEEDS ATTENTION</b>\n';
      if (pendWd > 0) msg += `   💰 ${pendWd} pending withdrawals\n`;
      if (openDisp > 0) msg += `   🚨 ${openDisp} open disputes\n`;
      if (openTix > 0) msg += `   🎫 ${openTix} open tickets\n`;
    } else {
      msg += '✅ <b>No pending actions</b>';
    }

    sendAlert(msg);
    console.log('[Digest] Daily digest sent');
  } catch (e) {
    console.error('[Digest] Error:', e.message);
  }
}

// ─── Schedule Everything ─────────────────────────────────────────────────────

function start() {
  console.log('[Alerts] Starting admin alerts service...');

  // Real-time event checks every 60 seconds
  setInterval(checkNewEvents, 60 * 1000);
  console.log('[Alerts] ✅ Real-time alerts: every 60s');

  // PM2 health check every 5 minutes
  checkPM2Health(); // Initial check
  setInterval(checkPM2Health, 5 * 60 * 1000);
  console.log('[Alerts] ✅ Health monitor: every 5min');

  // Daily digest at 8:00 AM UTC
  const scheduleDigest = () => {
    const now = new Date();
    const next8am = new Date(now);
    next8am.setUTCHours(8, 0, 0, 0);
    if (next8am <= now) next8am.setDate(next8am.getDate() + 1);
    const msUntil = next8am - now;
    console.log('[Alerts] ✅ Daily digest scheduled: ' + next8am.toISOString() + ' (' + Math.round(msUntil / 3600000) + 'h from now)');
    setTimeout(() => {
      sendDailyDigest();
      setInterval(sendDailyDigest, 24 * 60 * 60 * 1000);
    }, msUntil);
  };
  scheduleDigest();

  // Send startup alert
  sendAlert('🟢 <b>LOOPUMAN ALERTS ACTIVE</b>\n\n✅ Real-time monitoring\n✅ Health checks\n✅ Daily digest at 8:00 UTC');
}

module.exports = { start, sendAlert, sendDailyDigest, checkPM2Health };
