// Server snapshot — read structure tanpa data privat
export async function snapshotGuild(guild) {
  await guild.channels.fetch();
  await guild.roles.fetch();
  await guild.emojis.fetch();

  // Roles (skip @everyone & managed/integration roles)
  const roles = [...guild.roles.cache.values()]
    .filter(r => r.id !== guild.id && !r.managed)
    .sort((a, b) => b.position - a.position)
    .map(r => ({
      id: r.id,
      name: r.name,
      color: r.color,
      hoist: r.hoist,
      mentionable: r.mentionable,
      permissions: r.permissions.bitfield.toString(),
      position: r.position,
    }));

  // Categories first
  const categories = [...guild.channels.cache.values()]
    .filter(c => c.type === 4) // GuildCategory
    .sort((a, b) => a.position - b.position)
    .map(c => ({
      id: c.id,
      name: c.name,
      position: c.position,
      permission_overwrites: serializeOverwrites(c.permissionOverwrites.cache),
    }));

  // Channels (text/voice/forum/announcement) under categories
  const channels = [...guild.channels.cache.values()]
    .filter(c => c.type !== 4)
    .sort((a, b) => a.rawPosition - b.rawPosition)
    .map(c => ({
      id: c.id,
      name: c.name,
      type: c.type,
      parent_id: c.parentId,
      topic: c.topic,
      nsfw: c.nsfw,
      rate_limit_per_user: c.rateLimitPerUser,
      bitrate: c.bitrate,
      user_limit: c.userLimit,
      permission_overwrites: serializeOverwrites(c.permissionOverwrites?.cache),
    }));

  // Emojis (URL only — caller bisa download nanti)
  const emojis = [...guild.emojis.cache.values()].map(e => ({
    name: e.name,
    url: e.url,
    animated: e.animated,
  }));

  return {
    guild_name: guild.name,
    guild_icon: guild.iconURL({ extension: 'png', size: 512 }),
    snapshotted_at: Date.now(),
    roles,
    categories,
    channels,
    emojis,
  };
}

function serializeOverwrites(cache) {
  if (!cache) return [];
  return [...cache.values()].map(o => ({
    id: o.id,
    type: o.type,        // 0 = role, 1 = member
    allow: o.allow.bitfield.toString(),
    deny: o.deny.bitfield.toString(),
  }));
}
