/**
 * LuckPerms Meta Sync Service
 * Sets maxclaims and maxchunkloaders on all online servers when a subscriber's tier changes.
 * 
 * Requires: minecraft_username linked via /link command (stored in users table)
 * Uses: Pterodactyl sendCommand API to run lp commands on each online server
 * 
 * Date: April 15, 2026 (Chronicler #91, Launch Day)
 */

const db = require('../database');
const { sendCommand, getServerResources } = require('./pterodactyl');

// Tier level -> LuckPerms meta values
const TIER_META = {
  1:  { maxclaims: 90,  maxchunkloaders: 0  }, // Awakened
  2:  { maxclaims: 25,  maxchunkloaders: 0  }, // Elemental
  3:  { maxclaims: 25,  maxchunkloaders: 0  }, // Elemental (Fire/Frost split tiers)
  4:  { maxclaims: 49,  maxchunkloaders: 4  }, // Knight
  5:  { maxclaims: 49,  maxchunkloaders: 4  }, // Knight
  6:  { maxclaims: 100, maxchunkloaders: 9  }, // Master
  7:  { maxclaims: 100, maxchunkloaders: 9  }, // Master
  8:  { maxclaims: 121, maxchunkloaders: 16 }, // Legend
  9:  { maxclaims: 121, maxchunkloaders: 16 }, // Legend
  10: { maxclaims: 225, maxchunkloaders: 81 }, // Sovereign
};

// Tier level -> LuckPerms group name
const TIER_GROUP = {
  1:  'awakened',
  2:  'elemental',
  3:  'elemental',
  4:  'knight',
  5:  'knight',
  6:  'master',
  7:  'master',
  8:  'legend',
  9:  'legend',
  10: 'sovereign',
};

/**
 * Get all online Minecraft server identifiers from server_config
 */
async function getOnlineServers() {
  const result = await db.query(
    `SELECT server_identifier FROM server_config WHERE server_identifier IS NOT NULL`
  );
  const identifiers = result.rows.map(r => r.server_identifier);
  
  // Filter to only running servers
  const online = [];
  await Promise.all(identifiers.map(async (id) => {
    try {
      const res = await getServerResources(id);
      if (res.state === 'running') online.push(id);
    } catch (e) {
      // Server unreachable — skip silently
    }
  }));
  
  return online;
}

/**
 * Sync LuckPerms meta for a subscriber across all online servers.
 * Called after Stripe checkout or tier change.
 * 
 * @param {string} discordId - Discord user ID
 * @param {number} tierLevel - Subscription tier level (1-10)
 */
async function syncLuckPermsMeta(discordId, tierLevel) {
  const meta = TIER_META[tierLevel];
  if (!meta) {
    console.warn(`[LPSync] Unknown tier level ${tierLevel} for ${discordId} — skipping`);
    return { success: false, reason: 'unknown_tier' };
  }

  // Look up Minecraft username
  const userResult = await db.query(
    'SELECT minecraft_username FROM users WHERE discord_id = $1',
    [discordId]
  );

  if (userResult.rows.length === 0 || !userResult.rows[0].minecraft_username) {
    console.log(`[LPSync] No Minecraft username linked for Discord ID ${discordId} — skipping LP meta sync`);
    return { success: false, reason: 'no_minecraft_link' };
  }

  const username = userResult.rows[0].minecraft_username;

  // Get online servers
  const onlineServers = await getOnlineServers();
  
  if (onlineServers.length === 0) {
    console.warn(`[LPSync] No online servers found — LP meta sync skipped for ${username}`);
    return { success: false, reason: 'no_online_servers' };
  }

  // Send meta + group commands to all online servers
  const results = await Promise.allSettled(
    onlineServers.flatMap(serverId => [
      sendCommand(serverId, `lp user ${username} meta set maxclaims ${meta.maxclaims}`),
      sendCommand(serverId, `lp user ${username} meta set maxchunkloaders ${meta.maxchunkloaders}`),
      sendCommand(serverId, `lp user ${username} group set ${TIER_GROUP[tierLevel]}`)
    ])
  );

  const succeeded = results.filter(r => r.status === 'fulfilled').length;
  const failed = results.filter(r => r.status === 'rejected').length;

  console.log(`[LPSync] Meta sync for ${username} (tier ${tierLevel}): ${succeeded} OK, ${failed} failed across ${onlineServers.length} servers`);
  console.log(`[LPSync] maxclaims=${meta.maxclaims}, maxchunkloaders=${meta.maxchunkloaders}`);

  return { 
    success: true, 
    username, 
    tierLevel, 
    meta, 
    serversUpdated: onlineServers.length,
    commandsSucceeded: succeeded,
    commandsFailed: failed
  };
}

module.exports = { syncLuckPermsMeta };
