#!/usr/bin/env bun
/**
 * One-off diagnostic. Logs in with each configured Discord bot token, walks
 * every guild it sees, and prints the bot member's effective permission bits.
 *
 * Output is meant to verify capability claims like "we have Read Message
 * History" / "we have Manage Channels" empirically rather than guessing from
 * intents.
 */
import { Client, GatewayIntentBits, PermissionsBitField } from 'discord.js';
import fs from 'fs';
import path from 'path';

function loadEnv(): Record<string, string> {
  const envPath = path.join(import.meta.dir, '..', '.env');
  if (!fs.existsSync(envPath)) return {};
  const out: Record<string, string> = {};
  for (const line of fs.readFileSync(envPath, 'utf-8').split('\n')) {
    const m = line.match(/^([A-Z_][A-Z0-9_]*)=(.*)$/);
    if (m) out[m[1]] = m[2].replace(/^["']|["']$/g, '');
  }
  return out;
}

const env = loadEnv();
const TOKENS: Array<[string, string]> = [
  ['owner', env.DISCORD_OWNER_BOT_TOKEN ?? ''],
  ['reviewer', env.DISCORD_REVIEWER_BOT_TOKEN ?? ''],
  ['arbiter', env.DISCORD_ARBITER_BOT_TOKEN ?? ''],
].filter(([, t]) => t.length > 0) as Array<[string, string]>;

// Subset of permissions we actually care about for the capability matrix.
const RELEVANT = [
  'ViewChannel',
  'SendMessages',
  'EmbedLinks',
  'AttachFiles',
  'ReadMessageHistory',
  'AddReactions',
  'ManageMessages',
  'ManageChannels',
  'ManageThreads',
  'CreatePublicThreads',
  'CreatePrivateThreads',
  'SendMessagesInThreads',
  'MentionEveryone',
  'UseExternalEmojis',
] as const;

async function diagnose(role: string, token: string) {
  const client = new Client({
    intents: [
      GatewayIntentBits.Guilds,
      GatewayIntentBits.GuildMessages,
      GatewayIntentBits.MessageContent,
      GatewayIntentBits.DirectMessages,
    ],
  });

  await new Promise<void>((resolve, reject) => {
    client.once('ready', () => resolve());
    client.once('error', reject);
    client.login(token).catch(reject);
  });

  console.log(
    `\n=== role=${role} bot=${client.user?.tag} (id=${client.user?.id}) ===`,
  );
  const guilds = await client.guilds.fetch();
  for (const [gid, partial] of guilds) {
    const guild = await partial.fetch();
    const me = await guild.members.fetchMe();
    const perms = me.permissions;
    const has: Record<string, boolean> = {};
    for (const name of RELEVANT) {
      has[name] = perms.has(
        PermissionsBitField.Flags[
          name as keyof typeof PermissionsBitField.Flags
        ],
      );
    }
    console.log(`  guild=${guild.name} (id=${gid})`);
    console.log(
      `    admin=${perms.has(PermissionsBitField.Flags.Administrator)}`,
    );
    for (const name of RELEVANT) console.log(`    ${name}=${has[name]}`);
  }
  client.destroy();
}

for (const [role, token] of TOKENS) {
  try {
    await diagnose(role, token);
  } catch (err) {
    console.log(`\n=== role=${role} FAILED ===`);
    console.log(err);
  }
}
