const {
  Client,
  GatewayIntentBits,
  REST,
  Routes,
  Collection,
  EmbedBuilder,
  ChannelType,
  PermissionFlagsBits,
} = require("discord.js");
const { createClient } = require("@supabase/supabase-js");
const http = require("http");
const fs = require("fs");
const path = require("path");
const WebSocket = require("ws");
const { createWebServer } = require("./server/webServer");

require("dotenv").config();

// =============================================================================
// ENVIRONMENT VALIDATION (Modified: Supabase now optional)
// =============================================================================

const token = process.env.DISCORD_BOT_TOKEN;
const clientId = process.env.DISCORD_CLIENT_ID;

if (!token) {
  console.error("Missing DISCORD_BOT_TOKEN environment variable");
  process.exit(1);
}

if (!clientId) {
  console.error("Missing DISCORD_CLIENT_ID environment variable");
  process.exit(1);
}

console.log("[Token] Bot token loaded (length: " + token.length + " chars)");

// =============================================================================
// DISCORD CLIENT SETUP (Modified: Added intents for Sentinel)
// =============================================================================

const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildMembers,
    GatewayIntentBits.GuildModeration,
    GatewayIntentBits.GuildMessages,
    GatewayIntentBits.MessageContent,
    GatewayIntentBits.DirectMessages,
    GatewayIntentBits.GuildMessageReactions,
    GatewayIntentBits.GuildVoiceStates,
  ],
});

// =============================================================================
// SUPABASE SETUP (Modified: Now optional)
// =============================================================================

let supabase = null;
if (process.env.SUPABASE_URL && process.env.SUPABASE_SERVICE_ROLE) {
  supabase = createClient(
    process.env.SUPABASE_URL,
    process.env.SUPABASE_SERVICE_ROLE
  );
  console.log("Supabase connected");
} else {
  console.log("Supabase not configured - community features will be limited");
}

// Achievement tracking for command usage
async function trackCommandForAchievements(discordUserId, guildId, member, supabaseClient, discordClient) {
  try {
    const { data: link } = await supabaseClient
      .from('discord_links')
      .select('user_id')
      .eq('discord_id', discordUserId)
      .maybeSingle();
    
    if (!link) return;

    const { updateUserStats, getUserStats, calculateLevel, updateQuestProgress } = require('./listeners/xpTracker');
    const { checkAchievements } = require('./commands/achievements');

    await updateUserStats(supabaseClient, link.user_id, guildId, { commandsUsed: 1 });

    // Track quest progress for command usage
    await updateQuestProgress(supabaseClient, link.user_id, guildId, 'commands', 1);

    const { data: profile } = await supabaseClient
      .from('user_profiles')
      .select('xp, prestige_level, total_xp_earned, daily_streak')
      .eq('id', link.user_id)
      .maybeSingle();

    if (profile) {
      const stats = await getUserStats(supabaseClient, link.user_id, guildId);
      stats.level = calculateLevel(profile.xp || 0, 'normal');
      stats.prestige = profile.prestige_level || 0;
      stats.totalXp = profile.total_xp_earned || profile.xp || 0;
      stats.dailyStreak = profile.daily_streak || 0;

      await checkAchievements(link.user_id, member, stats, supabaseClient, guildId, discordClient);
    }
  } catch (e) {
    // Silent fail for achievement tracking
  }
}

// =============================================================================
// COMMAND LOGGING SYSTEM (Supabase-based)
// =============================================================================

async function logCommand(data) {
  if (!supabase) return;
  try {
    await supabase.from('command_logs').insert({
      command_name: data.commandName,
      user_id: data.userId,
      user_tag: data.userTag,
      guild_id: data.guildId,
      guild_name: data.guildName,
      channel_id: data.channelId,
      success: data.success,
      error_message: data.errorMessage || null,
      execution_time_ms: data.executionTime || null
    });
  } catch (err) {
    console.error('Failed to log command:', err.message);
  }
}

async function getCommandAnalytics(days = 7) {
  if (!supabase) return { commands: [], hourly: [], daily: [], topUsers: [] };
  try {
    const cutoffDate = new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString();
    
    const { data: logs } = await supabase
      .from('command_logs')
      .select('*')
      .gte('created_at', cutoffDate);
    
    if (!logs) return { commands: [], hourly: [], daily: [], topUsers: [] };
    
    // Calculate command usage
    const commandCounts = {};
    const userCounts = {};
    const hourlyActivity = Array(24).fill(0);
    const dailyActivity = {};
    
    for (const log of logs) {
      // Command counts
      commandCounts[log.command_name] = (commandCounts[log.command_name] || 0) + 1;
      
      // User counts
      const userKey = `${log.user_id}|${log.user_tag}`;
      userCounts[userKey] = (userCounts[userKey] || 0) + 1;
      
      // Hourly
      const hour = new Date(log.created_at).getHours();
      hourlyActivity[hour]++;
      
      // Daily
      const dateKey = new Date(log.created_at).toISOString().split('T')[0];
      dailyActivity[dateKey] = (dailyActivity[dateKey] || 0) + 1;
    }
    
    const commands = Object.entries(commandCounts)
      .map(([name, count]) => ({ command_name: name, count }))
      .sort((a, b) => b.count - a.count)
      .slice(0, 20);
    
    const topUsers = Object.entries(userCounts)
      .map(([key, count]) => {
        const [user_id, user_tag] = key.split('|');
        return { user_id, user_tag, command_count: count };
      })
      .sort((a, b) => b.command_count - a.command_count)
      .slice(0, 10);
    
    const hourly = hourlyActivity.map((count, hour) => ({ hour, count }));
    const daily = Object.entries(dailyActivity).map(([date, count]) => ({ date, count }));
    
    return { commands, hourly, daily, topUsers };
  } catch (err) {
    console.error('Failed to get command analytics:', err.message);
    return { commands: [], hourly: [], daily: [], topUsers: [] };
  }
}

async function getTotalCommandCount() {
  if (!supabase) return 0;
  try {
    const { count } = await supabase.from('command_logs').select('*', { count: 'exact', head: true });
    return count || 0;
  } catch (err) {
    return 0;
  }
}

// Supabase-based server config functions
async function saveServerConfigToDB(guildId, config) {
  if (!supabase) return false;
  try {
    await supabase.from('server_config').upsert({
      guild_id: guildId,
      welcome_channel: config.welcome_channel,
      goodbye_channel: config.goodbye_channel,
      modlog_channel: config.modlog_channel,
      level_up_channel: config.level_up_channel,
      auto_role: config.auto_role,
      verified_role: config.verified_role,
      updated_at: new Date().toISOString()
    });
    return true;
  } catch (err) {
    console.error('Failed to save server config:', err.message);
    return false;
  }
}

async function getServerConfigFromDB(guildId) {
  if (!supabase) return null;
  try {
    const { data } = await supabase
      .from('server_config')
      .select('*')
      .eq('guild_id', guildId)
      .single();
    return data || null;
  } catch (err) {
    console.error('Failed to get server config:', err.message);
    return null;
  }
}

// Federation mappings with Supabase
async function saveFederationMappingToDB(guildId, roleId, roleName) {
  if (!supabase) return false;
  try {
    await supabase.from('federation_mappings').upsert({
      guild_id: guildId,
      role_id: roleId,
      role_name: roleName,
      linked_at: new Date().toISOString()
    });
    return true;
  } catch (err) {
    console.error('Failed to save federation mapping:', err.message);
    return false;
  }
}

async function getFederationMappingsFromDB() {
  if (!supabase) return [];
  try {
    const { data } = await supabase
      .from('federation_mappings')
      .select('*')
      .order('linked_at', { ascending: false });
    return data || [];
  } catch (err) {
    console.error('Failed to get federation mappings:', err.message);
    return [];
  }
}

// =============================================================================
// SENTINEL: HEAT TRACKING SYSTEM (New)
// =============================================================================

const heatMap = new Map();
const HEAT_THRESHOLD = 3;
const HEAT_WINDOW_MS = 10000;
const whitelistedUsers = (process.env.WHITELISTED_USERS || '').split(',').filter(Boolean);

function addHeat(userId, action) {
  if (whitelistedUsers.includes(userId)) return 0;
  
  const now = Date.now();
  if (!heatMap.has(userId)) {
    heatMap.set(userId, []);
  }
  
  const userEvents = heatMap.get(userId);
  userEvents.push({ action, timestamp: now });
  
  const recentEvents = userEvents.filter(e => now - e.timestamp < HEAT_WINDOW_MS);
  heatMap.set(userId, recentEvents);
  
  return recentEvents.length;
}

function getHeat(userId) {
  const now = Date.now();
  const userEvents = heatMap.get(userId) || [];
  return userEvents.filter(e => now - e.timestamp < HEAT_WINDOW_MS).length;
}

client.heatMap = heatMap;
client.addHeat = addHeat;
client.getHeat = getHeat;
client.HEAT_THRESHOLD = HEAT_THRESHOLD;

// =============================================================================
// SENTINEL: FEDERATION MAPPINGS (New)
// =============================================================================

const federationMappings = new Map();
client.federationMappings = federationMappings;

async function loadFederationMappings() {
  if (!supabase) return;
  try {
    const { data, error } = await supabase
      .from('federation_mappings')
      .select('*');
    if (error) throw error;
    for (const mapping of data || []) {
      federationMappings.set(mapping.role_id, {
        name: mapping.role_name,
        guildId: mapping.guild_id,
        guildName: mapping.guild_name,
        linkedAt: new Date(mapping.linked_at).getTime(),
      });
    }
    console.log(`[Federation] Loaded ${federationMappings.size} mappings from database`);
  } catch (e) {
    console.warn('[Federation] Could not load mappings:', e.message);
  }
}

async function saveFederationMapping(roleId, data) {
  if (!supabase) return;
  try {
    await supabase.from('federation_mappings').upsert({
      role_id: roleId,
      role_name: data.name,
      guild_id: data.guildId,
      guild_name: data.guildName,
      linked_at: new Date(data.linkedAt).toISOString(),
    });
  } catch (e) {
    console.warn('[Federation] Could not save mapping:', e.message);
  }
}

async function deleteFederationMapping(roleId) {
  if (!supabase) return;
  try {
    await supabase.from('federation_mappings').delete().eq('role_id', roleId);
  } catch (e) {
    console.warn('[Federation] Could not delete mapping:', e.message);
  }
}

client.saveFederationMapping = saveFederationMapping;
client.deleteFederationMapping = deleteFederationMapping;

const REALM_GUILDS = {
  hub: process.env.HUB_GUILD_ID,
  labs: process.env.LABS_GUILD_ID,
  gameforge: process.env.GAMEFORGE_GUILD_ID,
  corp: process.env.CORP_GUILD_ID,
  foundation: process.env.FOUNDATION_GUILD_ID,
};
client.REALM_GUILDS = REALM_GUILDS;

// =============================================================================
// GUILD WHITELIST SYSTEM
// =============================================================================

const WHITELISTED_GUILDS = [
  '373713073594302464',  // AeThex | Corporation
  '515711457946632232',  // AeThex (Main)
  '525971009313046529',  // AeThex | Nexus
  '1245619208805416970', // AeThex | GameForge
  '1275962459596783686', // AeThex | LABS
  '1284290638564687925', // AeThex | DevOps
  '1338564560277344287', // AeThex | Foundation
  '352519501201539072', // AeThex | Lone Star Studio
  
  ...(process.env.EXTRA_WHITELISTED_GUILDS || '').split(',').filter(Boolean),
];
client.WHITELISTED_GUILDS = WHITELISTED_GUILDS;

client.on('error', (error) => {
  console.error('[Discord] Client error:', error.message);
  addErrorLog('discord', 'Discord client error', { error: error.message });
});

client.on('warn', (warning) => {
  console.warn('[Discord] Warning:', warning);
  addErrorLog('warning', 'Discord warning', { warning });
});

client.on('guildCreate', async (guild) => {
  if (!WHITELISTED_GUILDS.includes(guild.id)) {
    console.log(`[Whitelist] Unauthorized server detected: ${guild.name} (${guild.id}) - Leaving...`);
    try {
      const owner = await guild.fetchOwner();
      await owner.send(`Your server "${guild.name}" is not authorized to use AeThex Bot. The bot has automatically left. Contact the AeThex team if you believe this is an error.`).catch(() => {});
    } catch (e) {}
    await guild.leave();
    console.log(`[Whitelist] Left unauthorized server: ${guild.name}`);
    return;
  }
  console.log(`[Whitelist] Joined authorized server: ${guild.name} (${guild.id})`);
});

// =============================================================================
// SENTINEL: TICKET TRACKING (New)
// =============================================================================

const activeTickets = new Map();
client.activeTickets = activeTickets;

async function loadActiveTickets() {
  if (!supabase) return;
  try {
    const { data, error } = await supabase
      .from('tickets')
      .select('*')
      .eq('status', 'open');
    if (error) throw error;
    for (const ticket of data || []) {
      activeTickets.set(ticket.channel_id, {
        odId: ticket.id,
        userId: ticket.user_id,
        guildId: ticket.guild_id,
        reason: ticket.reason,
        createdAt: new Date(ticket.created_at).getTime(),
      });
    }
    console.log(`[Tickets] Loaded ${activeTickets.size} active tickets from database`);
  } catch (e) {
    console.warn('[Tickets] Could not load tickets:', e.message);
  }
}

async function saveTicket(channelId, data) {
  if (!supabase) return;
  try {
    await supabase.from('tickets').insert({
      channel_id: channelId,
      user_id: data.userId,
      guild_id: data.guildId,
      reason: data.reason,
      status: 'open',
    });
  } catch (e) {
    console.warn('[Tickets] Could not save ticket:', e.message);
  }
}

async function closeTicket(channelId) {
  if (!supabase) return;
  try {
    await supabase
      .from('tickets')
      .update({ status: 'closed', closed_at: new Date().toISOString() })
      .eq('channel_id', channelId);
  } catch (e) {
    console.warn('[Tickets] Could not close ticket:', e.message);
  }
}

client.saveTicket = saveTicket;
client.closeTicket = closeTicket;

// =============================================================================
// SENTINEL: ALERT SYSTEM (New)
// =============================================================================

let alertChannelId = process.env.ALERT_CHANNEL_ID;
client.alertChannelId = alertChannelId;

async function sendAlert(message, embed = null) {
  if (!alertChannelId) return;
  try {
    const channel = await client.channels.fetch(alertChannelId);
    if (channel) {
      if (embed) {
        await channel.send({ content: message, embeds: [embed] });
      } else {
        await channel.send(message);
      }
    }
  } catch (err) {
    console.error("Failed to send alert:", err.message);
  }
}
client.sendAlert = sendAlert;

// =============================================================================
// ACTIVITY FEED SYSTEM (New - Dashboard Real-time)
// =============================================================================

const activityFeed = [];
const MAX_ACTIVITY_EVENTS = 100;
const threatAlerts = [];
const MAX_THREAT_ALERTS = 50;

const errorLogs = [];
const MAX_ERROR_LOGS = 50;
const commandQueue = [];
const MAX_COMMAND_QUEUE = 100;
let lastCpuUsage = process.cpuUsage();
let lastCpuTime = Date.now();

function addErrorLog(type, message, details = {}) {
  const log = {
    id: Date.now() + Math.random().toString(36).substr(2, 9),
    type,
    message,
    details,
    timestamp: new Date().toISOString(),
  };
  errorLogs.unshift(log);
  if (errorLogs.length > MAX_ERROR_LOGS) {
    errorLogs.pop();
  }
  return log;
}

function addToCommandQueue(command, status = 'pending') {
  const entry = {
    id: Date.now() + Math.random().toString(36).substr(2, 9),
    command,
    status,
    timestamp: new Date().toISOString(),
  };
  commandQueue.unshift(entry);
  if (commandQueue.length > MAX_COMMAND_QUEUE) {
    commandQueue.pop();
  }
  return entry;
}

function updateCommandQueue(id, status) {
  const entry = commandQueue.find(e => e.id === id);
  if (entry) {
    entry.status = status;
    entry.completedAt = new Date().toISOString();
  }
}

let currentCpuUsage = 0;

function updateCpuUsage() {
  const now = Date.now();
  const cpuUsage = process.cpuUsage(lastCpuUsage);
  const elapsed = (now - lastCpuTime) * 1000;
  
  if (elapsed > 0) {
    const userPercent = (cpuUsage.user / elapsed) * 100;
    const systemPercent = (cpuUsage.system / elapsed) * 100;
    currentCpuUsage = Math.min(100, Math.round(userPercent + systemPercent));
  }
  
  lastCpuUsage = process.cpuUsage();
  lastCpuTime = now;
}

setInterval(updateCpuUsage, 5000);

function getCpuUsage() {
  return currentCpuUsage;
}

client.addErrorLog = addErrorLog;
client.errorLogs = errorLogs;
client.commandQueue = commandQueue;
client.addToCommandQueue = addToCommandQueue;
client.updateCommandQueue = updateCommandQueue;

// Analytics tracking
const analyticsData = {
  commandUsage: {},
  xpDistributed: 0,
  newMembers: 0,
  modActions: { warnings: 0, kicks: 0, bans: 0, timeouts: 0 },
  hourlyActivity: Array(24).fill(0),
  dailyActivity: Array(7).fill(0),
  lastReset: Date.now(),
};

function trackCommand(commandName) {
  analyticsData.commandUsage[commandName] = (analyticsData.commandUsage[commandName] || 0) + 1;
  const hour = new Date().getHours();
  const day = new Date().getDay();
  analyticsData.hourlyActivity[hour]++;
  analyticsData.dailyActivity[day]++;
}

function trackXP(amount) {
  analyticsData.xpDistributed += amount;
}

function trackNewMember() {
  analyticsData.newMembers++;
}

function trackModAction(type) {
  if (analyticsData.modActions[type] !== undefined) {
    analyticsData.modActions[type]++;
  }
}

function resetDailyAnalytics() {
  const now = Date.now();
  const lastReset = analyticsData.lastReset;
  const dayMs = 24 * 60 * 60 * 1000;
  
  if (now - lastReset > dayMs) {
    analyticsData.commandUsage = {};
    analyticsData.xpDistributed = 0;
    analyticsData.newMembers = 0;
    analyticsData.modActions = { warnings: 0, kicks: 0, bans: 0, timeouts: 0 };
    analyticsData.lastReset = now;
  }
}

client.trackCommand = trackCommand;
client.trackXP = trackXP;
client.trackNewMember = trackNewMember;
client.trackModAction = trackModAction;
client.analyticsData = analyticsData;

function addActivity(type, data) {
  const event = {
    id: Date.now() + Math.random().toString(36).substr(2, 9),
    type,
    data,
    timestamp: new Date().toISOString(),
  };
  activityFeed.unshift(event);
  if (activityFeed.length > MAX_ACTIVITY_EVENTS) {
    activityFeed.pop();
  }
  return event;
}

function addThreatAlert(level, message, details = {}) {
  const alert = {
    id: Date.now() + Math.random().toString(36).substr(2, 9),
    level,
    message,
    details,
    timestamp: new Date().toISOString(),
    resolved: false,
  };
  threatAlerts.unshift(alert);
  if (threatAlerts.length > MAX_THREAT_ALERTS) {
    threatAlerts.pop();
  }
  return alert;
}

client.addActivity = addActivity;
client.activityFeed = activityFeed;
client.addThreatAlert = addThreatAlert;
client.threatAlerts = threatAlerts;

// =============================================================================
// COMMAND LOADING
// =============================================================================

client.commands = new Collection();

const commandsPath = path.join(__dirname, "commands");
if (fs.existsSync(commandsPath)) {
  const commandFiles = fs.readdirSync(commandsPath).filter((file) => file.endsWith(".js"));
  for (const file of commandFiles) {
    const filePath = path.join(commandsPath, file);
    const command = require(filePath);
    if ("data" in command && "execute" in command) {
      client.commands.set(command.data.name, command);
      console.log(`Loaded command: ${command.data.name}`);
    }
  }
}

// =============================================================================
// EVENT LOADING
// =============================================================================

const eventsPath = path.join(__dirname, "events");
if (fs.existsSync(eventsPath)) {
  const eventFiles = fs.readdirSync(eventsPath).filter((file) => file.endsWith(".js"));
  for (const file of eventFiles) {
    const filePath = path.join(eventsPath, file);
    const event = require(filePath);
    if ("name" in event && "execute" in event) {
      client.on(event.name, (...args) => event.execute(...args, client, supabase));
      console.log(`Loaded event: ${event.name}`);
    }
  }
}

// =============================================================================
// SENTINEL LISTENER LOADING (New)
// =============================================================================

const sentinelPath = path.join(__dirname, "listeners", "sentinel");
if (fs.existsSync(sentinelPath)) {
  const sentinelFiles = fs.readdirSync(sentinelPath).filter((file) => file.endsWith(".js"));
  for (const file of sentinelFiles) {
    const filePath = path.join(sentinelPath, file);
    const listener = require(filePath);
    if ("name" in listener && "execute" in listener) {
      client.on(listener.name, (...args) => listener.execute(...args, client));
      console.log(`Loaded sentinel listener: ${listener.name}`);
    }
  }
}

// =============================================================================
// GENERAL LISTENER LOADING (Welcome, Goodbye, XP Tracker)
// =============================================================================

const listenersPath = path.join(__dirname, "listeners");
const generalListenerFiles = ['welcome.js', 'goodbye.js', 'xpTracker.js', 'reactionXp.js', 'voiceXp.js', 'starboard.js', 'federationProtection.js'];
for (const file of generalListenerFiles) {
  const filePath = path.join(listenersPath, file);
  if (fs.existsSync(filePath)) {
    const listener = require(filePath);
    if ("name" in listener && "execute" in listener) {
      client.on(listener.name, (...args) => listener.execute(...args, client, supabase));
      console.log(`Loaded listener: ${file}`);
    }
  }
}

// =============================================================================
// SERVER CONFIGS MAP
// =============================================================================

const serverConfigs = new Map();
client.serverConfigs = serverConfigs;

async function loadServerConfigs() {
  if (!supabase) return;
  try {
    const { data, error } = await supabase
      .from('server_config')
      .select('*');
    if (error) throw error;
    for (const config of data || []) {
      serverConfigs.set(config.guild_id, config);
    }
    console.log(`[Config] Loaded ${serverConfigs.size} server configurations`);
  } catch (e) {
    console.warn('[Config] Could not load server configs:', e.message);
  }
}

// =============================================================================
// FEED SYNC SETUP (Modified: Guard for missing Supabase)
// =============================================================================

let feedSyncModule = null;
let setupFeedListener = null;
let sendPostToDiscord = null;
let getFeedChannelId = () => null;

try {
  feedSyncModule = require("./listeners/feedSync");
  setupFeedListener = feedSyncModule.setupFeedListener;
  sendPostToDiscord = feedSyncModule.sendPostToDiscord;
  getFeedChannelId = feedSyncModule.getFeedChannelId;
} catch (e) {
  console.log("Feed sync module not available");
}

// =============================================================================
// INTERACTION HANDLER (Modified: Added button handling for tickets)
// =============================================================================

client.on("interactionCreate", async (interaction) => {
  console.log(`[Interaction] Received: type=${interaction.type}, commandName=${interaction.commandName || 'N/A'}, user=${interaction.user?.tag}, guild=${interaction.guildId}`);
  
  if (interaction.isChatInputCommand()) {
    console.log(`[Command] Processing: ${interaction.commandName}`);
    const command = client.commands.get(interaction.commandName);
    if (!command) {
      console.warn(`No command matching ${interaction.commandName} was found.`);
      return;
    }
    
    const queueEntry = addToCommandQueue(`/${interaction.commandName} by ${interaction.user.tag}`, 'pending');
    const startTime = Date.now();
    
    try {
      console.log(`[Command] Executing: ${interaction.commandName}`);
      await command.execute(interaction, supabase, client);
      const executionTime = Date.now() - startTime;
      console.log(`[Command] Completed: ${interaction.commandName} (${executionTime}ms)`);
      
      updateCommandQueue(queueEntry.id, 'completed');
      trackCommand(interaction.commandName);
      resetDailyAnalytics();
      
      // Track command usage for achievements
      if (supabase && interaction.guildId) {
        trackCommandForAchievements(interaction.user.id, interaction.guildId, interaction.member, supabase, client).catch(() => {});
      }
      
      const activityData = {
        command: interaction.commandName,
        user: interaction.user.tag,
        userId: interaction.user.id,
        guild: interaction.guild?.name || 'DM',
        guildId: interaction.guildId,
        executionTime,
      };
      
      addActivity('command', activityData);
      
      // Log to database
      logCommand({
        commandName: interaction.commandName,
        userId: interaction.user.id,
        userTag: interaction.user.tag,
        guildId: interaction.guildId,
        guildName: interaction.guild?.name || 'DM',
        channelId: interaction.channelId,
        success: true,
        executionTime,
      });
      
      // Broadcast via WebSocket
      if (typeof wsBroadcast === 'function') {
        wsBroadcast('command', activityData);
      }
    } catch (error) {
      const executionTime = Date.now() - startTime;
      console.error(`Error executing ${interaction.commandName}:`, error);
      
      updateCommandQueue(queueEntry.id, 'failed');
      addErrorLog('command', `Error in /${interaction.commandName}`, {
        command: interaction.commandName,
        user: interaction.user.tag,
        userId: interaction.user.id,
        guild: interaction.guild?.name || 'DM',
        error: error.message,
      });
      
      // Log failed command to database
      logCommand({
        commandName: interaction.commandName,
        userId: interaction.user.id,
        userTag: interaction.user.tag,
        guildId: interaction.guildId,
        guildName: interaction.guild?.name || 'DM',
        channelId: interaction.channelId,
        success: false,
        errorMessage: error.message,
        executionTime,
      });
      
      try {
        const errorEmbed = new EmbedBuilder()
          .setColor(0xff0000)
          .setTitle("Command Error")
          .setDescription("There was an error while executing this command.")
          .setFooter({ text: "Contact support if this persists" });
        
        if (interaction.replied || interaction.deferred) {
          await interaction.followUp({ embeds: [errorEmbed], ephemeral: true }).catch(() => {});
        } else {
          await interaction.reply({ embeds: [errorEmbed], ephemeral: true }).catch(() => {});
        }
      } catch (replyError) {
        console.error("Failed to send error response:", replyError.message);
      }
    }
  }
  
  if (interaction.isButton()) {
    const [action, ...params] = interaction.customId.split('_');
    
    if (action === 'ticket') {
      const ticketAction = params[0];
      if (ticketAction === 'close') {
        try {
          const channel = interaction.channel;
          if (channel && channel.type === ChannelType.GuildText) {
            await interaction.reply({ content: 'Closing ticket...', ephemeral: true });
            activeTickets.delete(channel.id);
            await closeTicket(channel.id);
            setTimeout(() => channel.delete().catch(console.error), 3000);
          }
        } catch (err) {
          console.error('Ticket close error:', err);
        }
      }
    }
    
    if (action === 'role') {
      const roleId = params.join('_');
      try {
        const role = interaction.guild.roles.cache.get(roleId);
        if (!role) {
          return interaction.reply({ content: 'This role no longer exists.', ephemeral: true });
        }
        
        const member = interaction.member;
        if (member.roles.cache.has(roleId)) {
          await member.roles.remove(roleId);
          await interaction.reply({ content: `Removed ${role} from you!`, ephemeral: true });
        } else {
          await member.roles.add(roleId);
          await interaction.reply({ content: `Added ${role} to you!`, ephemeral: true });
        }
      } catch (err) {
        console.error('Role button error:', err);
        await interaction.reply({ content: 'Failed to toggle role. Check bot permissions.', ephemeral: true }).catch(() => {});
      }
    }
    
    if (action === 'giveaway') {
      const giveawayAction = params[0];
      if (giveawayAction === 'enter') {
        try {
          const messageId = interaction.message.id;
          
          let giveawayData = client.giveaways?.get(messageId);
          let entries = giveawayData?.entries || [];
          
          if (supabase) {
            const { data } = await supabase
              .from('giveaways')
              .select('*')
              .eq('message_id', messageId)
              .single();
            
            if (data) {
              entries = data.entries || [];
              giveawayData = data;
            }
          }
          
          if (!giveawayData) {
            return interaction.reply({ content: 'This giveaway is no longer active.', ephemeral: true });
          }
          
          if (giveawayData.required_role) {
            const hasRole = interaction.member.roles.cache.has(giveawayData.required_role);
            if (!hasRole) {
              return interaction.reply({ content: `You need the <@&${giveawayData.required_role}> role to enter!`, ephemeral: true });
            }
          }
          
          if (entries.includes(interaction.user.id)) {
            return interaction.reply({ content: 'You have already entered this giveaway!', ephemeral: true });
          }
          
          entries.push(interaction.user.id);
          
          if (client.giveaways?.has(messageId)) {
            client.giveaways.get(messageId).entries = entries;
          }
          
          if (supabase) {
            await supabase
              .from('giveaways')
              .update({ entries: entries })
              .eq('message_id', messageId);
          }
          
          const embed = EmbedBuilder.from(interaction.message.embeds[0]);
          const entriesField = embed.data.fields?.find(f => f.name.includes('Entries'));
          if (entriesField) {
            entriesField.value = `${entries.length}`;
          }
          await interaction.message.edit({ embeds: [embed] });
          
          await interaction.reply({ content: `You have entered the giveaway! Total entries: ${entries.length}`, ephemeral: true });
          
        } catch (err) {
          console.error('Giveaway entry error:', err);
          await interaction.reply({ content: 'Failed to enter giveaway.', ephemeral: true }).catch(() => {});
        }
      }
    }
  }
  
  if (interaction.isModalSubmit()) {
    if (interaction.customId.startsWith('embed_modal_')) {
      try {
        const parts = interaction.customId.split('_');
        const channelId = parts[2];
        const color = parseInt(parts[3], 16);
        
        const title = interaction.fields.getTextInputValue('embed_title');
        const description = interaction.fields.getTextInputValue('embed_description');
        const imageUrl = interaction.fields.getTextInputValue('embed_image') || null;
        const thumbnailUrl = interaction.fields.getTextInputValue('embed_thumbnail') || null;
        const footerText = interaction.fields.getTextInputValue('embed_footer') || null;
        
        const embed = new EmbedBuilder()
          .setColor(color)
          .setTitle(title)
          .setDescription(description)
          .setTimestamp();
        
        if (imageUrl) embed.setImage(imageUrl);
        if (thumbnailUrl) embed.setThumbnail(thumbnailUrl);
        if (footerText) embed.setFooter({ text: footerText });
        
        const channel = await client.channels.fetch(channelId);
        await channel.send({ embeds: [embed] });
        
        await interaction.reply({ content: `Embed sent to <#${channelId}>!`, ephemeral: true });
        
      } catch (err) {
        console.error('Embed modal error:', err);
        await interaction.reply({ content: 'Failed to send embed. Check permissions and URLs.', ephemeral: true }).catch(() => {});
      }
    }
  }
  
  if (interaction.isStringSelectMenu()) {
    if (interaction.customId === 'help_category') {
      try {
        const category = interaction.values[0];
        const { getCategoryEmbed } = require('./commands/help');
        const embed = getCategoryEmbed(category);
        await interaction.update({ embeds: [embed] });
      } catch (err) {
        console.error('Help select error:', err);
      }
    }
  }
});

// =============================================================================
// COMMANDS FOR REGISTRATION (Uses actual command file definitions)
// =============================================================================

function getCommandsToRegister() {
  return Array.from(client.commands.values()).map(cmd => cmd.data.toJSON());
}

// =============================================================================
// COMMAND REGISTRATION FUNCTION
// =============================================================================

async function registerDiscordCommands() {
  try {
    const rest = new REST({ version: "10" }).setToken(
      process.env.DISCORD_BOT_TOKEN,
    );

    const commandsToRegister = getCommandsToRegister();
    console.log(
      `Registering ${commandsToRegister.length} slash commands...`,
    );

    try {
      const data = await rest.put(
        Routes.applicationCommands(process.env.DISCORD_CLIENT_ID),
        { body: commandsToRegister },
      );

      console.log(`Successfully registered ${data.length} slash commands`);
      return { success: true, count: data.length, results: null };
    } catch (bulkError) {
      if (bulkError.code === 50240) {
        console.warn(
          "Error 50240: Entry Point detected. Registering individually...",
        );

        const results = [];
        let successCount = 0;
        let skipCount = 0;

        for (const command of commandsToRegister) {
          try {
            const posted = await rest.post(
              Routes.applicationCommands(process.env.DISCORD_CLIENT_ID),
              { body: command },
            );
            results.push({
              name: command.name,
              status: "registered",
              id: posted.id,
            });
            successCount++;
          } catch (postError) {
            if (postError.code === 50045) {
              results.push({
                name: command.name,
                status: "already_exists",
              });
              skipCount++;
            } else {
              results.push({
                name: command.name,
                status: "error",
                error: postError.message,
              });
            }
          }
        }

        console.log(
          `Registration complete: ${successCount} new, ${skipCount} already existed`,
        );
        return {
          success: true,
          count: successCount,
          skipped: skipCount,
          results,
        };
      }

      throw bulkError;
    }
  } catch (error) {
    console.error("Failed to register commands:", error);
    return { success: false, error: error.message };
  }
}

// =============================================================================
// HTTP SERVER (Modified: Added Sentinel stats to health endpoint)
// =============================================================================

const healthPort = process.env.HEALTH_PORT || 8080;
const ADMIN_TOKEN = process.env.DISCORD_ADMIN_TOKEN || "aethex-bot-admin";

const checkAdminAuth = (req) => {
  const authHeader = req.headers.authorization;
  return authHeader === `Bearer ${ADMIN_TOKEN}`;
};

const httpServer = http.createServer((req, res) => {
    res.setHeader("Access-Control-Allow-Origin", "*");
    res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
    res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
    res.setHeader("Content-Type", "application/json");

    if (req.method === "OPTIONS") {
      res.writeHead(200);
      res.end();
      return;
    }

    if (req.url === "/" || req.url === "/dashboard") {
      res.setHeader("Content-Type", "text/html");
      try {
        const html = fs.readFileSync(dashboardPath, "utf8");
        res.writeHead(200);
        res.end(html);
      } catch (e) {
        res.writeHead(404);
        res.end("<h1>Dashboard not found</h1>");
      }
      return;
    }

    if (req.url === "/health") {
      res.writeHead(200);
      res.end(
        JSON.stringify({
          status: "online",
          guilds: client.guilds.cache.size,
          commands: client.commands.size,
          uptime: Math.floor(process.uptime()),
          heatMapSize: heatMap.size,
          supabaseConnected: !!supabase,
          timestamp: new Date().toISOString(),
        }),
      );
      return;
    }

    if (req.url === "/stats") {
      const guildStats = client.guilds.cache.map(g => ({
        id: g.id,
        name: g.name,
        memberCount: g.memberCount,
      }));
      res.writeHead(200);
      res.end(JSON.stringify({
        guilds: guildStats,
        totalMembers: guildStats.reduce((sum, g) => sum + g.memberCount, 0),
        uptime: Math.floor(process.uptime()),
        activeTickets: activeTickets.size,
        heatEvents: heatMap.size,
        federationLinks: federationMappings.size,
      }));
      return;
    }

    if (req.url === "/activity" || req.url.startsWith("/activity?")) {
      const url = new URL(req.url, `http://localhost:${healthPort}`);
      const limit = parseInt(url.searchParams.get('limit') || '50');
      const since = url.searchParams.get('since');
      
      let events = activityFeed.slice(0, Math.min(limit, 100));
      if (since) {
        events = events.filter(e => new Date(e.timestamp) > new Date(since));
      }
      
      res.writeHead(200);
      res.end(JSON.stringify({
        events,
        total: activityFeed.length,
        timestamp: new Date().toISOString(),
      }));
      return;
    }

    if (req.url === "/tickets") {
      const ticketList = Array.from(activeTickets.entries()).map(([channelId, data]) => ({
        channelId,
        userId: data.userId,
        guildId: data.guildId,
        reason: data.reason,
        createdAt: new Date(data.createdAt).toISOString(),
        age: Math.floor((Date.now() - data.createdAt) / 60000),
      }));
      
      res.writeHead(200);
      res.end(JSON.stringify({
        tickets: ticketList,
        count: ticketList.length,
        timestamp: new Date().toISOString(),
      }));
      return;
    }

    if (req.url === "/threats") {
      const unresolvedThreats = threatAlerts.filter(t => !t.resolved);
      const threatLevel = unresolvedThreats.length > 5 ? 'Critical' : 
                          unresolvedThreats.length > 2 ? 'High' :
                          unresolvedThreats.length > 0 ? 'Medium' : 'Low';
      
      res.writeHead(200);
      res.end(JSON.stringify({
        alerts: threatAlerts.slice(0, 50),
        unresolvedCount: unresolvedThreats.length,
        threatLevel,
        heatMapSize: heatMap.size,
        timestamp: new Date().toISOString(),
      }));
      return;
    }

    if (req.url === "/server-health") {
      const guilds = client.guilds.cache.map(g => {
        const botMember = g.members.cache.get(client.user.id);
        return {
          id: g.id,
          name: g.name,
          memberCount: g.memberCount,
          online: true,
          permissions: botMember?.permissions.has('Administrator') ? 'Admin' : 'Limited',
          joinedAt: g.joinedAt?.toISOString(),
        };
      });
      
      res.writeHead(200);
      res.end(JSON.stringify({
        guilds,
        botStatus: client.isReady() ? 'online' : 'offline',
        ping: client.ws.ping,
        timestamp: new Date().toISOString(),
      }));
      return;
    }

    if (req.url === "/system-info") {
      const memUsage = process.memoryUsage();
      const cpu = getCpuUsage();
      const pendingCommands = commandQueue.filter(c => c.status === 'pending').length;
      const completedCommands = commandQueue.filter(c => c.status === 'completed').length;
      const failedCommands = commandQueue.filter(c => c.status === 'failed').length;
      
      res.writeHead(200);
      res.end(JSON.stringify({
        uptime: Math.floor(process.uptime()),
        memory: {
          heapUsed: Math.round(memUsage.heapUsed / 1024 / 1024),
          heapTotal: Math.round(memUsage.heapTotal / 1024 / 1024),
          rss: Math.round(memUsage.rss / 1024 / 1024),
        },
        cpu: cpu,
        nodeVersion: process.version,
        platform: process.platform,
        ping: client.ws.ping,
        guilds: client.guilds.cache.size,
        commands: client.commands.size,
        activityEvents: activityFeed.length,
        whitelistedUsers: whitelistedUsers.length,
        errorLogs: errorLogs.slice(0, 20),
        errorCount: errorLogs.length,
        commandQueue: {
          pending: pendingCommands,
          completed: completedCommands,
          failed: failedCommands,
          total: commandQueue.length,
          recent: commandQueue.slice(0, 10),
        },
        timestamp: new Date().toISOString(),
      }));
      return;
    }

    if (req.url === "/analytics") {
      resetDailyAnalytics();
      
      const commandsArray = Object.entries(analyticsData.commandUsage)
        .map(([name, count]) => ({ name, count }))
        .sort((a, b) => b.count - a.count);
      
      const totalCommands = commandsArray.reduce((sum, c) => sum + c.count, 0);
      const totalModActions = Object.values(analyticsData.modActions).reduce((sum, c) => sum + c, 0);
      
      res.writeHead(200);
      res.end(JSON.stringify({
        commandsToday: totalCommands,
        xpDistributed: analyticsData.xpDistributed,
        newMembers: analyticsData.newMembers,
        modActionsTotal: totalModActions,
        modActions: analyticsData.modActions,
        commandUsage: commandsArray.slice(0, 15),
        hourlyActivity: analyticsData.hourlyActivity,
        dailyActivity: analyticsData.dailyActivity,
        lastReset: new Date(analyticsData.lastReset).toISOString(),
        timestamp: new Date().toISOString(),
      }));
      return;
    }

    if (req.url === "/leaderboard") {
      if (!supabase) {
        res.writeHead(200);
        res.end(JSON.stringify({ 
          success: false, 
          message: "Supabase not configured",
          xpLeaders: [],
          topChatters: [],
          topMods: [],
        }));
        return;
      }
      
      (async () => {
        try {
          const { data: xpLeaders } = await supabase
            .from('user_profiles')
            .select('id, username, avatar_url, xp')
            .order('xp', { ascending: false })
            .limit(10);
          
          const { data: modActors } = await supabase
            .from('mod_actions')
            .select('moderator_id, moderator_tag')
            .limit(100);
          
          const modCounts = {};
          (modActors || []).forEach(m => {
            modCounts[m.moderator_id] = modCounts[m.moderator_id] || { count: 0, tag: m.moderator_tag };
            modCounts[m.moderator_id].count++;
          });
          
          const topMods = Object.entries(modCounts)
            .map(([id, data]) => ({ id, tag: data.tag, count: data.count }))
            .sort((a, b) => b.count - a.count)
            .slice(0, 10);
          
          res.writeHead(200);
          res.end(JSON.stringify({
            success: true,
            xpLeaders: (xpLeaders || []).map((u, i) => ({
              rank: i + 1,
              username: u.username || 'Unknown',
              avatarUrl: u.avatar_url,
              xp: u.xp || 0,
              level: Math.floor(Math.sqrt((u.xp || 0) / 100)),
            })),
            topMods,
          }));
        } catch (error) {
          res.writeHead(500);
          res.end(JSON.stringify({ success: false, error: error.message }));
        }
      })();
      return;
    }

    if (req.url === "/bot-status") {
      if (!checkAdminAuth(req)) {
        res.writeHead(401);
        res.end(JSON.stringify({ error: "Unauthorized - Admin token required" }));
        return;
      }

      const channelId = getFeedChannelId();
      const guilds = client.guilds.cache.map((guild) => ({
        id: guild.id,
        name: guild.name,
        memberCount: guild.memberCount,
        icon: guild.iconURL(),
      }));

      res.writeHead(200);
      res.end(
        JSON.stringify({
          status: client.isReady() ? "online" : "offline",
          bot: {
            tag: client.user?.tag || "Not logged in",
            id: client.user?.id,
            avatar: client.user?.displayAvatarURL(),
          },
          guilds: guilds,
          guildCount: client.guilds.cache.size,
          commands: Array.from(client.commands.keys()),
          commandCount: client.commands.size,
          uptime: Math.floor(process.uptime()),
          feedBridge: {
            enabled: !!channelId,
            channelId: channelId,
          },
          sentinel: {
            heatMapSize: heatMap.size,
            activeTickets: activeTickets.size,
            federationMappings: federationMappings.size,
          },
          supabaseConnected: !!supabase,
          timestamp: new Date().toISOString(),
        }),
      );
      return;
    }

    if (req.url === "/linked-users") {
      if (!checkAdminAuth(req)) {
        res.writeHead(401);
        res.end(JSON.stringify({ error: "Unauthorized - Admin token required" }));
        return;
      }

      if (!supabase) {
        res.writeHead(200);
        res.end(JSON.stringify({ success: true, links: [], count: 0, message: "Supabase not configured" }));
        return;
      }

      (async () => {
        try {
          const { data: links, error } = await supabase
            .from("discord_links")
            .select("discord_id, user_id, primary_arm, created_at")
            .order("created_at", { ascending: false })
            .limit(50);

          if (error) throw error;

          const enrichedLinks = await Promise.all(
            (links || []).map(async (link) => {
              const { data: profile } = await supabase
                .from("user_profiles")
                .select("username, avatar_url")
                .eq("id", link.user_id)
                .single();

              return {
                discord_id: link.discord_id.slice(0, 6) + "***",
                user_id: link.user_id.slice(0, 8) + "...",
                primary_arm: link.primary_arm,
                created_at: link.created_at,
                profile: profile ? {
                  username: profile.username,
                  avatar_url: profile.avatar_url,
                } : null,
              };
            })
          );

          res.writeHead(200);
          res.end(JSON.stringify({ success: true, links: enrichedLinks, count: enrichedLinks.length }));
        } catch (error) {
          res.writeHead(500);
          res.end(JSON.stringify({ success: false, error: error.message }));
        }
      })();
      return;
    }

    if (req.url === "/command-stats") {
      if (!checkAdminAuth(req)) {
        res.writeHead(401);
        res.end(JSON.stringify({ error: "Unauthorized - Admin token required" }));
        return;
      }

      const cmds = getCommandsToRegister();
      const stats = {
        commands: cmds.map((cmd) => ({
          name: cmd.name,
          description: cmd.description,
          options: cmd.options?.length || 0,
        })),
        totalCommands: cmds.length,
      };

      res.writeHead(200);
      res.end(JSON.stringify({ success: true, stats }));
      return;
    }

    if (req.url === "/feed-stats") {
      if (!checkAdminAuth(req)) {
        res.writeHead(401);
        res.end(JSON.stringify({ error: "Unauthorized - Admin token required" }));
        return;
      }

      if (!supabase) {
        res.writeHead(200);
        res.end(JSON.stringify({ success: true, stats: { totalPosts: 0, discordPosts: 0, websitePosts: 0, recentPosts: [] }, message: "Supabase not configured" }));
        return;
      }

      (async () => {
        try {
          const { count: totalPosts } = await supabase
            .from("community_posts")
            .select("*", { count: "exact", head: true });

          const { count: discordPosts } = await supabase
            .from("community_posts")
            .select("*", { count: "exact", head: true })
            .eq("source", "discord");

          const { count: websitePosts } = await supabase
            .from("community_posts")
            .select("*", { count: "exact", head: true })
            .or("source.is.null,source.neq.discord");

          const { data: recentPosts } = await supabase
            .from("community_posts")
            .select("id, content, source, created_at")
            .order("created_at", { ascending: false })
            .limit(10);

          res.writeHead(200);
          res.end(
            JSON.stringify({
              success: true,
              stats: {
                totalPosts: totalPosts || 0,
                discordPosts: discordPosts || 0,
                websitePosts: websitePosts || 0,
                recentPosts: (recentPosts || []).map(p => ({
                  id: p.id,
                  content: p.content?.slice(0, 100) + (p.content?.length > 100 ? "..." : ""),
                  source: p.source,
                  created_at: p.created_at,
                })),
              },
            })
          );
        } catch (error) {
          res.writeHead(500);
          res.end(JSON.stringify({ success: false, error: error.message }));
        }
      })();
      return;
    }

    if (req.url === "/send-to-discord" && req.method === "POST") {
      let body = "";
      req.on("data", (chunk) => {
        body += chunk.toString();
      });
      req.on("end", async () => {
        try {
          const authHeader = req.headers.authorization;
          const expectedToken = process.env.DISCORD_BRIDGE_TOKEN || "aethex-bridge";
          if (authHeader !== `Bearer ${expectedToken}`) {
            res.writeHead(401);
            res.end(JSON.stringify({ error: "Unauthorized" }));
            return;
          }

          const post = JSON.parse(body);
          console.log("[API] Received post to send to Discord:", post.id);

          if (sendPostToDiscord) {
            const result = await sendPostToDiscord(post, post.author);
            res.writeHead(result.success ? 200 : 500);
            res.end(JSON.stringify(result));
          } else {
            res.writeHead(500);
            res.end(JSON.stringify({ error: "Feed sync not available" }));
          }
        } catch (error) {
          console.error("[API] Error processing send-to-discord:", error);
          res.writeHead(500);
          res.end(JSON.stringify({ error: error.message }));
        }
      });
      return;
    }

    if (req.url === "/bridge-status") {
      const channelId = getFeedChannelId();
      res.writeHead(200);
      res.end(
        JSON.stringify({
          enabled: !!channelId,
          channelId: channelId,
          botReady: client.isReady(),
        }),
      );
      return;
    }

    if (req.url.startsWith("/leave-guild/") && req.method === "POST") {
      if (!checkAdminAuth(req)) {
        res.writeHead(401);
        res.end(JSON.stringify({ error: "Unauthorized - Admin token required" }));
        return;
      }

      const guildId = req.url.split("/leave-guild/")[1];
      (async () => {
        try {
          const guild = client.guilds.cache.get(guildId);
          if (!guild) {
            res.writeHead(404);
            res.end(JSON.stringify({ error: "Guild not found" }));
            return;
          }

          const guildName = guild.name;
          await guild.leave();
          console.log(`[Admin] Left guild: ${guildName} (${guildId})`);
          res.writeHead(200);
          res.end(JSON.stringify({ success: true, message: `Left guild: ${guildName}` }));
        } catch (error) {
          res.writeHead(500);
          res.end(JSON.stringify({ error: error.message }));
        }
      })();
      return;
    }

    if (req.url.startsWith("/create-invite/") && req.method === "GET") {
      if (!checkAdminAuth(req)) {
        res.writeHead(401);
        res.end(JSON.stringify({ error: "Unauthorized - Admin token required" }));
        return;
      }

      const guildId = req.url.split("/create-invite/")[1];
      (async () => {
        try {
          const guild = client.guilds.cache.get(guildId);
          if (!guild) {
            res.writeHead(404);
            res.end(JSON.stringify({ error: "Guild not found" }));
            return;
          }

          const channel = guild.channels.cache.find(ch => ch.type === ChannelType.GuildText && ch.permissionsFor(guild.members.me).has('CreateInstantInvite'));
          if (!channel) {
            res.writeHead(403);
            res.end(JSON.stringify({ error: "No channel available to create invite" }));
            return;
          }

          const invite = await channel.createInvite({ maxAge: 86400, maxUses: 1 });
          res.writeHead(200);
          res.end(JSON.stringify({ success: true, invite: invite.url, guild: guild.name, expiresIn: "24 hours" }));
        } catch (error) {
          res.writeHead(500);
          res.end(JSON.stringify({ error: error.message }));
        }
      })();
      return;
    }

    if (req.url === "/register-commands") {
      if (req.method === "GET") {
        if (!checkAdminAuth(req)) {
          res.writeHead(401);
          res.end(JSON.stringify({ error: "Unauthorized - Admin token required" }));
          return;
        }
        res.writeHead(200, { "Content-Type": "text/html" });
        res.end(`
          <!DOCTYPE html>
          <html>
          <head>
            <title>Register Discord Commands</title>
            <style>
              body {
                font-family: Arial, sans-serif;
                display: flex;
                justify-content: center;
                align-items: center;
                min-height: 100vh;
                margin: 0;
                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
              }
              .container {
                background: white;
                padding: 40px;
                border-radius: 10px;
                box-shadow: 0 10px 30px rgba(0,0,0,0.3);
                text-align: center;
                max-width: 500px;
              }
              h1 { color: #333; margin-bottom: 20px; }
              p { color: #666; margin-bottom: 30px; }
              button {
                background: #667eea;
                color: white;
                border: none;
                padding: 12px 30px;
                border-radius: 5px;
                cursor: pointer;
                font-size: 16px;
                font-weight: bold;
                transition: background 0.3s;
              }
              button:hover { background: #764ba2; }
              button:disabled { background: #ccc; cursor: not-allowed; }
              #result { margin-top: 30px; padding: 20px; border-radius: 5px; display: none; }
              #result.success { background: #d4edda; color: #155724; display: block; }
              #result.error { background: #f8d7da; color: #721c24; display: block; }
              #loading { display: none; color: #667eea; font-weight: bold; }
            </style>
          </head>
          <body>
            <div class="container">
              <h1>Discord Commands Registration</h1>
              <p>Click to register all ${client.commands.size} slash commands</p>
              <button id="registerBtn" onclick="registerCommands()">Register Commands</button>
              <div id="loading">Registering... please wait...</div>
              <div id="result"></div>
            </div>
            <script>
              async function registerCommands() {
                const btn = document.getElementById('registerBtn');
                const loading = document.getElementById('loading');
                const result = document.getElementById('result');
                btn.disabled = true;
                loading.style.display = 'block';
                result.style.display = 'none';
                try {
                  const response = await fetch('/register-commands', {
                    method: 'POST',
                    headers: { 'Authorization': 'Bearer ${ADMIN_TOKEN}', 'Content-Type': 'application/json' }
                  });
                  const data = await response.json();
                  loading.style.display = 'none';
                  if (response.ok && data.success) {
                    result.className = 'success';
                    result.innerHTML = '<h3>Success!</h3><p>Registered ' + data.count + ' commands</p>';
                  } else {
                    result.className = 'error';
                    result.innerHTML = '<h3>Error</h3><p>' + (data.error || 'Failed') + '</p>';
                  }
                } catch (error) {
                  loading.style.display = 'none';
                  result.className = 'error';
                  result.innerHTML = '<h3>Error</h3><p>' + error.message + '</p>';
                } finally {
                  btn.disabled = false;
                }
              }
            </script>
          </body>
          </html>
        `);
        return;
      }

      if (req.method === "POST") {
        if (!checkAdminAuth(req)) {
          res.writeHead(401);
          res.end(JSON.stringify({ error: "Unauthorized - Admin token required" }));
          return;
        }

        registerDiscordCommands().then((result) => {
          if (result.success) {
            res.writeHead(200);
            res.end(JSON.stringify(result));
          } else {
            res.writeHead(500);
            res.end(JSON.stringify(result));
          }
        });
        return;
      }
    }

    // =============================================================================
    // MANAGEMENT API ENDPOINTS (Server Config, Whitelist, Roles, Announcements)
    // =============================================================================

    // GET /server-config/:guildId - Get server configuration
    if (req.url.startsWith("/server-config/") && req.method === "GET") {
      const guildId = req.url.split("/server-config/")[1].split("?")[0];
      
      if (!guildId) {
        res.writeHead(400);
        res.end(JSON.stringify({ error: "Guild ID required" }));
        return;
      }
      
      const config = serverConfigs.get(guildId) || {
        guild_id: guildId,
        welcome_channel: null,
        goodbye_channel: null,
        modlog_channel: null,
        level_up_channel: null,
        auto_role: null,
      };
      
      const guild = client.guilds.cache.get(guildId);
      const channels = guild ? guild.channels.cache
        .filter(c => c.type === 0) // Text channels
        .map(c => ({ id: c.id, name: c.name })) : [];
      const roles = guild ? guild.roles.cache
        .filter(r => r.name !== '@everyone')
        .map(r => ({ id: r.id, name: r.name, color: r.hexColor })) : [];
      
      res.writeHead(200);
      res.end(JSON.stringify({
        config,
        channels,
        roles,
        guildName: guild?.name || 'Unknown',
      }));
      return;
    }

    // POST /server-config - Save server configuration
    if (req.url === "/server-config" && req.method === "POST") {
      if (!checkAdminAuth(req)) {
        res.writeHead(401);
        res.end(JSON.stringify({ error: "Unauthorized" }));
        return;
      }
      
      let body = "";
      req.on("data", chunk => body += chunk);
      req.on("end", async () => {
        try {
          const data = JSON.parse(body);
          const guildId = data.guild_id;
          
          if (!guildId) {
            res.writeHead(400);
            res.end(JSON.stringify({ error: "Guild ID required" }));
            return;
          }
          
          const configData = {
            guild_id: guildId,
            welcome_channel: data.welcome_channel || null,
            goodbye_channel: data.goodbye_channel || null,
            modlog_channel: data.modlog_channel || null,
            level_up_channel: data.level_up_channel || null,
            auto_role: data.auto_role || null,
            updated_at: new Date().toISOString(),
          };
          
          serverConfigs.set(guildId, configData);
          
          if (supabase) {
            const { error: dbError } = await supabase.from('server_config').upsert(configData);
            if (dbError) {
              console.error('[Config] Failed to save to database:', dbError.message);
              res.writeHead(500);
              res.end(JSON.stringify({ error: 'Failed to persist config to database', details: dbError.message }));
              return;
            }
          }
          
          res.writeHead(200);
          res.end(JSON.stringify({ success: true, config: configData, persisted: !!supabase }));
        } catch (error) {
          res.writeHead(500);
          res.end(JSON.stringify({ error: error.message }));
        }
      });
      return;
    }

    // GET /whitelist - Get whitelisted servers and users
    if (req.url === "/whitelist" && req.method === "GET") {
      const whitelistedServers = WHITELISTED_GUILDS.map(guildId => {
        const guild = client.guilds.cache.get(guildId);
        return {
          id: guildId,
          name: guild?.name || 'Not Connected',
          memberCount: guild?.memberCount || 0,
          connected: !!guild,
        };
      });
      
      res.writeHead(200);
      res.end(JSON.stringify({
        servers: whitelistedServers,
        users: whitelistedUsers.map(id => ({ id, note: 'Whitelisted User' })),
        timestamp: new Date().toISOString(),
      }));
      return;
    }

    // GET /roles - Get level roles and federation roles
    if (req.url === "/roles" && req.method === "GET") {
      (async () => {
        const levelRoles = [];
        const fedRoles = Array.from(federationMappings.entries()).map(([roleId, data]) => ({
          roleId,
          name: data.name,
          guildId: data.guildId,
          guildName: data.guildName,
          linkedAt: new Date(data.linkedAt).toISOString(),
        }));
        
        // Try to get level roles from Supabase
        if (supabase) {
          try {
            const { data } = await supabase.from('level_roles').select('*');
            if (data) {
              for (const lr of data) {
                const guild = client.guilds.cache.get(lr.guild_id);
                const role = guild?.roles.cache.get(lr.role_id);
                levelRoles.push({
                  guildId: lr.guild_id,
                  guildName: guild?.name || 'Unknown',
                  roleId: lr.role_id,
                  roleName: role?.name || 'Unknown',
                  levelRequired: lr.level_required,
                });
              }
            }
          } catch (e) {
            console.warn('Could not fetch level roles:', e.message);
          }
        }
        
        res.writeHead(200);
        res.end(JSON.stringify({
          levelRoles,
          federationRoles: fedRoles,
          timestamp: new Date().toISOString(),
        }));
      })();
      return;
    }

    // POST /announce - Send announcement to servers
    if (req.url === "/announce" && req.method === "POST") {
      if (!checkAdminAuth(req)) {
        res.writeHead(401);
        res.end(JSON.stringify({ error: "Unauthorized" }));
        return;
      }
      
      let body = "";
      req.on("data", chunk => body += chunk);
      req.on("end", async () => {
        try {
          const { title, message, targets, color } = JSON.parse(body);
          
          if (!title || !message) {
            res.writeHead(400);
            res.end(JSON.stringify({ error: "Title and message required" }));
            return;
          }
          
          const embed = new EmbedBuilder()
            .setTitle(title)
            .setDescription(message)
            .setColor(color ? parseInt(color.replace('#', ''), 16) : 0x5865F2)
            .setTimestamp()
            .setFooter({ text: 'AeThex Network Announcement' });
          
          const results = [];
          const targetGuilds = targets && targets.length > 0 
            ? targets 
            : Array.from(client.guilds.cache.keys());
          
          for (const guildId of targetGuilds) {
            const guild = client.guilds.cache.get(guildId);
            if (!guild) {
              results.push({ guildId, success: false, error: 'Guild not found' });
              continue;
            }
            
            try {
              const config = serverConfigs.get(guildId);
              let channel = null;
              
              if (config?.welcome_channel) {
                channel = guild.channels.cache.get(config.welcome_channel);
              }
              
              if (!channel) {
                channel = guild.systemChannel || 
                  guild.channels.cache.find(c => c.type === 0 && c.permissionsFor(guild.members.me).has('SendMessages'));
              }
              
              if (channel) {
                await channel.send({ embeds: [embed] });
                results.push({ guildId, guildName: guild.name, success: true });
              } else {
                results.push({ guildId, guildName: guild.name, success: false, error: 'No suitable channel' });
              }
            } catch (error) {
              results.push({ guildId, guildName: guild?.name, success: false, error: error.message });
            }
          }
          
          addActivity('announcement', { title, targetCount: targetGuilds.length, successCount: results.filter(r => r.success).length });
          
          res.writeHead(200);
          res.end(JSON.stringify({ success: true, results }));
        } catch (error) {
          res.writeHead(500);
          res.end(JSON.stringify({ error: error.message }));
        }
      });
      return;
    }

    // GET /servers - List all connected servers (for dropdowns)
    if (req.url === "/servers" && req.method === "GET") {
      const servers = client.guilds.cache.map(g => ({
        id: g.id,
        name: g.name,
        icon: g.iconURL({ size: 64 }),
        memberCount: g.memberCount,
      }));
      
      res.writeHead(200);
      res.end(JSON.stringify({ servers }));
      return;
    }

    // GET /user-lookup/:query - Search for a user by ID or username
    if (req.url.startsWith("/user-lookup/") && req.method === "GET") {
      const query = decodeURIComponent(req.url.split("/user-lookup/")[1].split("?")[0]);
      
      if (!query || query.length < 2) {
        res.writeHead(400);
        res.end(JSON.stringify({ error: "Query too short" }));
        return;
      }
      
      (async () => {
        try {
          const results = [];
          const isNumericId = /^\d{17,19}$/.test(query);
          
          for (const guild of client.guilds.cache.values()) {
            try {
              if (isNumericId) {
                const member = await guild.members.fetch(query).catch(() => null);
                if (member) {
                  const existingIdx = results.findIndex(r => r.id === member.id);
                  if (existingIdx === -1) {
                    results.push({
                      id: member.id,
                      tag: member.user.tag,
                      username: member.user.username,
                      displayName: member.displayName,
                      avatar: member.user.displayAvatarURL({ size: 128 }),
                      bot: member.user.bot,
                      createdAt: member.user.createdAt.toISOString(),
                      joinedAt: member.joinedAt?.toISOString(),
                      roles: member.roles.cache.filter(r => r.name !== '@everyone').map(r => ({ id: r.id, name: r.name, color: r.hexColor })).slice(0, 10),
                      servers: [{ id: guild.id, name: guild.name }],
                      heat: getHeat(member.id),
                    });
                  } else {
                    results[existingIdx].servers.push({ id: guild.id, name: guild.name });
                  }
                }
              } else {
                const members = await guild.members.fetch({ query, limit: 10 }).catch(() => new Map());
                for (const member of members.values()) {
                  const existingIdx = results.findIndex(r => r.id === member.id);
                  if (existingIdx === -1) {
                    results.push({
                      id: member.id,
                      tag: member.user.tag,
                      username: member.user.username,
                      displayName: member.displayName,
                      avatar: member.user.displayAvatarURL({ size: 128 }),
                      bot: member.user.bot,
                      createdAt: member.user.createdAt.toISOString(),
                      joinedAt: member.joinedAt?.toISOString(),
                      roles: member.roles.cache.filter(r => r.name !== '@everyone').map(r => ({ id: r.id, name: r.name, color: r.hexColor })).slice(0, 10),
                      servers: [{ id: guild.id, name: guild.name }],
                      heat: getHeat(member.id),
                    });
                  } else {
                    results[existingIdx].servers.push({ id: guild.id, name: guild.name });
                  }
                }
              }
            } catch (e) {}
          }
          
          // Fetch Supabase profile data if available
          if (supabase && results.length > 0) {
            for (const user of results) {
              try {
                const { data: link } = await supabase
                  .from('discord_links')
                  .select('user_id, primary_arm')
                  .eq('discord_id', user.id)
                  .single();
                
                if (link) {
                  user.linked = true;
                  user.realm = link.primary_arm;
                  
                  const { data: profile } = await supabase
                    .from('user_profiles')
                    .select('username, xp, daily_streak, badges')
                    .eq('id', link.user_id)
                    .single();
                  
                  if (profile) {
                    user.aethexUsername = profile.username;
                    user.xp = profile.xp || 0;
                    user.level = Math.floor(Math.sqrt((profile.xp || 0) / 100));
                    user.dailyStreak = profile.daily_streak || 0;
                    user.badges = profile.badges || [];
                  }
                }
                
                const { data: warnings } = await supabase
                  .from('warnings')
                  .select('id, reason, created_at')
                  .eq('user_id', user.id)
                  .order('created_at', { ascending: false })
                  .limit(5);
                
                user.warnings = warnings || [];
                
                const { data: modActions } = await supabase
                  .from('mod_actions')
                  .select('action, reason, created_at')
                  .eq('user_id', user.id)
                  .order('created_at', { ascending: false })
                  .limit(5);
                
                user.modHistory = modActions || [];
              } catch (e) {}
            }
          }
          
          res.writeHead(200);
          res.end(JSON.stringify({
            results: results.slice(0, 20),
            count: results.length,
            query,
            timestamp: new Date().toISOString(),
          }));
        } catch (error) {
          res.writeHead(500);
          res.end(JSON.stringify({ error: error.message }));
        }
      })();
      return;
    }

    // GET /mod-actions - Get recent moderation actions
    if (req.url === "/mod-actions" && req.method === "GET") {
      if (!supabase) {
        res.writeHead(200);
        res.end(JSON.stringify({ success: false, message: "Supabase not configured", actions: [] }));
        return;
      }
      
      (async () => {
        try {
          const { data: actions, error } = await supabase
            .from('mod_actions')
            .select('*')
            .order('created_at', { ascending: false })
            .limit(50);
          
          if (error) throw error;
          
          const { count: warnCount } = await supabase.from('warnings').select('*', { count: 'exact', head: true });
          const { count: banCount } = await supabase.from('mod_actions').select('*', { count: 'exact', head: true }).eq('action', 'ban');
          const { count: kickCount } = await supabase.from('mod_actions').select('*', { count: 'exact', head: true }).eq('action', 'kick');
          const { count: timeoutCount } = await supabase.from('mod_actions').select('*', { count: 'exact', head: true }).eq('action', 'timeout');
          
          res.writeHead(200);
          res.end(JSON.stringify({
            success: true,
            actions: actions || [],
            counts: {
              warnings: warnCount || 0,
              bans: banCount || 0,
              kicks: kickCount || 0,
              timeouts: timeoutCount || 0,
            },
            timestamp: new Date().toISOString(),
          }));
        } catch (error) {
          res.writeHead(500);
          res.end(JSON.stringify({ success: false, error: error.message }));
        }
      })();
      return;
    }

    // GET /studio-feed - Get AeThex Studio community feed
    if (req.url === "/studio-feed" && req.method === "GET") {
      if (!supabase) {
        res.writeHead(200);
        res.end(JSON.stringify({ 
          success: false, 
          message: "Supabase not configured - Studio feed unavailable",
          posts: [] 
        }));
        return;
      }
      
      (async () => {
        try {
          const { data: posts, error } = await supabase
            .from('community_posts')
            .select('*')
            .order('created_at', { ascending: false })
            .limit(20);
          
          if (error) throw error;
          
          res.writeHead(200);
          res.end(JSON.stringify({
            success: true,
            posts: posts || [],
            count: posts?.length || 0,
            timestamp: new Date().toISOString(),
          }));
        } catch (error) {
          res.writeHead(200);
          res.end(JSON.stringify({ 
            success: false, 
            message: "No community posts table available",
            posts: [] 
          }));
        }
      })();
      return;
    }

    // GET /foundation-stats - Get AeThex Foundation statistics
    if (req.url === "/foundation-stats" && req.method === "GET") {
      (async () => {
        const foundationGuild = client.guilds.cache.get(REALM_GUILDS.foundation);
        
        const stats = {
          success: true,
          contributors: 0,
          projects: 0,
          commits: 0,
          members: foundationGuild?.memberCount || 0,
          activity: [],
          timestamp: new Date().toISOString(),
        };
        
        if (supabase) {
          try {
            const { count: contributorCount } = await supabase
              .from('user_profiles')
              .select('*', { count: 'exact', head: true })
              .not('foundation_contributions', 'is', null);
            stats.contributors = contributorCount || 0;
            
            const { data: activity } = await supabase
              .from('foundation_activity')
              .select('*')
              .order('created_at', { ascending: false })
              .limit(10);
            
            if (activity) {
              stats.activity = activity.map(a => ({
                type: a.type || 'commit',
                message: a.message || a.description,
                author: a.author || a.username,
                date: a.created_at,
              }));
            }
          } catch (e) {
            // Tables may not exist, use defaults
          }
        }
        
        // Estimate projects from federation mappings
        stats.projects = federationMappings.size || 5;
        stats.commits = Math.floor(Math.random() * 50) + 100; // Placeholder
        
        res.writeHead(200);
        res.end(JSON.stringify(stats));
      })();
      return;
    }

    // POST /test-webhook - Test a Discord webhook
    if (req.url === "/test-webhook" && req.method === "POST") {
      let body = '';
      req.on('data', chunk => { body += chunk; });
      req.on('end', async () => {
        try {
          const { url, message, username } = JSON.parse(body);
          
          if (!url || !url.includes('discord.com/api/webhooks')) {
            res.writeHead(400);
            res.end(JSON.stringify({ success: false, error: 'Invalid webhook URL' }));
            return;
          }
          
          if (!message) {
            res.writeHead(400);
            res.end(JSON.stringify({ success: false, error: 'Message is required' }));
            return;
          }
          
          const webhookPayload = {
            content: message,
            username: username || 'AeThex Dashboard Test',
          };
          
          const response = await fetch(url, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(webhookPayload),
          });
          
          if (response.ok || response.status === 204) {
            res.writeHead(200);
            res.end(JSON.stringify({ success: true, message: 'Webhook test sent successfully' }));
          } else {
            const errorText = await response.text();
            res.writeHead(200);
            res.end(JSON.stringify({ success: false, error: `Webhook failed: ${response.status} - ${errorText}` }));
          }
        } catch (error) {
          res.writeHead(500);
          res.end(JSON.stringify({ success: false, error: error.message }));
        }
      });
      return;
    }

    // Analytics endpoint with detailed command data
    if (req.url === "/command-analytics" || req.url.startsWith("/command-analytics?")) {
      (async () => {
        try {
          const url = new URL(req.url, `http://localhost:${healthPort}`);
          const days = parseInt(url.searchParams.get('days') || '7');
          const analytics = await getCommandAnalytics(days);
          const totalCount = await getTotalCommandCount();
          
          res.writeHead(200);
          res.end(JSON.stringify({
            success: true,
            totalCommands: totalCount,
            analytics,
            timestamp: new Date().toISOString(),
          }));
        } catch (error) {
          res.writeHead(500);
          res.end(JSON.stringify({ success: false, error: error.message }));
        }
      })();
      return;
    }

    res.writeHead(404);
    res.end(JSON.stringify({ error: "Not found" }));
  });

// =============================================================================
// WEBSOCKET SERVER FOR REAL-TIME UPDATES
// =============================================================================

const wsClients = new Set();
const wss = new WebSocket.Server({ noServer: true });

wss.on('connection', (ws) => {
  wsClients.add(ws);
  console.log(`[WebSocket] Client connected. Total: ${wsClients.size}`);
  
  ws.send(JSON.stringify({
    type: 'init',
    data: {
      status: 'online',
      guilds: client.guilds.cache.size,
      commands: client.commands?.size || 0,
      uptime: Math.floor(process.uptime()),
      heatMapSize: heatMap.size,
      activeTickets: activeTickets.size,
      federationLinks: federationMappings.size,
    }
  }));
  
  ws.on('close', () => {
    wsClients.delete(ws);
    console.log(`[WebSocket] Client disconnected. Total: ${wsClients.size}`);
  });
  
  ws.on('error', (err) => {
    console.error('[WebSocket] Error:', err.message);
    wsClients.delete(ws);
  });
});

function wsBroadcast(type, data) {
  const message = JSON.stringify({ type, data, timestamp: new Date().toISOString() });
  for (const wsClient of wsClients) {
    if (wsClient.readyState === WebSocket.OPEN) {
      try {
        wsClient.send(message);
      } catch (err) {
        console.error('[WebSocket] Broadcast error:', err.message);
      }
    }
  }
}

setInterval(() => {
  if (wsClients.size > 0) {
    wsBroadcast('stats', {
      guilds: client.guilds.cache.size,
      commands: client.commands?.size || 0,
      uptime: Math.floor(process.uptime()),
      heatMapSize: heatMap.size,
      activeTickets: activeTickets.size,
      federationLinks: federationMappings.size,
      memory: process.memoryUsage(),
      cpu: getCpuUsage(),
    });
  }
}, 5000);

// Add WebSocket upgrade handling
httpServer.on('upgrade', (request, socket, head) => {
  wss.handleUpgrade(request, socket, head, (ws) => {
    wss.emit('connection', ws, request);
  });
});

httpServer.listen(healthPort, () => {
  console.log(`Health/API server running on port ${healthPort}`);
  console.log(`WebSocket server available at ws://localhost:${healthPort}`);
  console.log(`Register commands at: POST http://localhost:${healthPort}/register-commands`);
});

// =============================================================================
// EXPRESS WEB PORTAL (Discord OAuth, User Dashboard, API)
// =============================================================================

const webPort = process.env.PORT || 5000;
const expressApp = createWebServer(client, supabase);
const webServer = http.createServer(expressApp);

webServer.listen(webPort, '0.0.0.0', () => {
  console.log(`Web portal running on port ${webPort}`);
  console.log(`Dashboard: http://localhost:${webPort}/dashboard`);
  console.log(`Landing page: http://localhost:${webPort}/`);
});


// =============================================================================
// BOT LOGIN AND READY
// =============================================================================

client.login(token).catch((error) => {
  console.error("Failed to login to Discord");
  console.error(`Error Code: ${error.code}`);
  console.error(`Error Message: ${error.message}`);

  if (error.code === "TokenInvalid") {
    console.error("\nDISCORD_BOT_TOKEN is invalid!");
    console.error("Get a new token from: https://discord.com/developers/applications");
  }

  process.exit(1);
});

// =============================================================================
// BOT STATUS - WATCHING PROTECTING THE FEDERATION
// =============================================================================

function setWardenStatus(client) {
  try {
    client.user.setPresence({
      activities: [{
        name: 'Protecting the Federation',
        type: 3 // ActivityType.Watching
      }],
      status: 'online'
    });
    console.log('[Status] Set to: WATCHING Protecting the Federation');
  } catch (e) {
    console.error('[Status] Error setting status:', e.message);
  }
}

client.once("clientReady", async () => {
  console.log(`Bot logged in as ${client.user.tag}`);
  console.log(`Bot ID: ${client.user.id}`);
  console.log(`CLIENT_ID from env: ${process.env.DISCORD_CLIENT_ID}`);
  console.log(`IDs match: ${client.user.id === process.env.DISCORD_CLIENT_ID}`);
  console.log(`Watching ${client.guilds.cache.size} server(s)`);
  
  // Load persisted data from Supabase
  await loadFederationMappings();
  await loadActiveTickets();
  await loadServerConfigs();
  
  // Auto-register commands on startup
  console.log("Registering slash commands with Discord...");
  const regResult = await registerDiscordCommands();
  if (regResult.success) {
    console.log(`Successfully registered ${regResult.count} commands`);
  } else {
    console.error("Failed to register commands:", regResult.error);
  }
  
  // Static status: WATCHING Protecting the Federation
  setWardenStatus(client);
  
  if (setupFeedListener && supabase) {
    setupFeedListener(client);
  }
  
  sendAlert(`Warden is now online! Watching ${client.guilds.cache.size} servers.`);
});

// =============================================================================
// ERROR HANDLING
// =============================================================================

process.on("unhandledRejection", (error) => {
  console.error("Unhandled Promise Rejection:", error);
});

process.on("uncaughtException", (error) => {
  console.error("Uncaught Exception:", error);
  process.exit(1);
});

module.exports = client;
