// ─── Bitwise Permission Engine ──────────────────────────────────────────────
// Single source of truth for all permission bits. Used by both server and client.
// SQLite stores as TEXT (decimal string). Never put raw bigint into JSON.

export const PermissionBits = {
  ADMINISTRATOR:        1n << 0n,
  VIEW_CHANNEL:         1n << 1n,
  MANAGE_CHANNELS:      1n << 2n,
  MANAGE_ROLES:         1n << 3n,
  MANAGE_SPACE:         1n << 4n,
  CREATE_INVITE:        1n << 5n,
  KICK_MEMBERS:         1n << 6n,
  BAN_MEMBERS:          1n << 7n,
  SEND_MESSAGES:        1n << 10n,
  MANAGE_MESSAGES:      1n << 11n,
  ATTACH_FILES:         1n << 12n,
  READ_MESSAGE_HISTORY: 1n << 13n,
  ADD_REACTIONS:        1n << 14n,
  CONNECT:              1n << 20n,
  SPEAK:                1n << 21n,
  MUTE_MEMBERS:         1n << 22n,
  DEAFEN_MEMBERS:       1n << 23n,
  MOVE_MEMBERS:         1n << 24n,
  STREAM:               1n << 25n,
  DISCONNECT_MEMBERS:   1n << 26n,
} as const;

export type PermissionBit = (typeof PermissionBits)[keyof typeof PermissionBits];

export const ALL_PERMISSIONS = Object.values(PermissionBits).reduce((a, b) => a | b, 0n);

export const DEFAULT_EVERYONE_PERMISSIONS =
  PermissionBits.VIEW_CHANNEL |
  PermissionBits.SEND_MESSAGES |
  PermissionBits.CREATE_INVITE |
  PermissionBits.CONNECT |
  PermissionBits.SPEAK |
  PermissionBits.ATTACH_FILES |
  PermissionBits.READ_MESSAGE_HISTORY |
  PermissionBits.ADD_REACTIONS |
  PermissionBits.STREAM;

// ─── Helpers ────────────────────────────────────────────────────────────────

/** Check if a permissions value has a specific bit set. Accepts bigint or decimal string. */
export function hasPermissionBit(perms: bigint | string | undefined | null, bit: bigint): boolean {
  if (perms === undefined || perms === null) return false;
  const p = typeof perms === 'string' ? BigInt(perms) : perms;
  // ADMINISTRATOR grants everything
  if ((p & PermissionBits.ADMINISTRATOR) !== 0n) return true;
  return (p & bit) === bit;
}

/** Convert a bigint to a decimal string safe for JSON serialization. */
export function permissionsToString(perms: bigint): string {
  return perms.toString();
}

/** Convert a decimal string back to bigint. Returns 0n for falsy/invalid input. */
export function stringToPermissions(str: string | undefined | null): bigint {
  if (!str) return 0n;
  try {
    return BigInt(str);
  } catch {
    // Fallback: legacy JSON array format (e.g. '["VIEW_CHANNEL","SEND_MESSAGES"]')
    try {
      const parsed = JSON.parse(str);
      if (Array.isArray(parsed)) {
        let result = 0n;
        for (const key of parsed) {
          const bit = PermissionBits[key as keyof typeof PermissionBits];
          if (bit !== undefined) result |= bit;
        }
        return result;
      }
    } catch { /* not JSON either */ }
    return 0n;
  }
}
