import { env } from '../config/env.js';

const API = 'https://discord.com/api/v10';

export interface DiscordUser {
  id: string;
  username: string;
  global_name: string | null;
  avatar: string | null;
}

export interface DiscordGuildSummary {
  id: string;
  name: string;
  icon: string | null;
  owner: boolean;
  permissions: string;
}

export function buildDiscordAuthorizeUrl(state: string): string {
  const url = new URL('https://discord.com/oauth2/authorize');
  url.searchParams.set('client_id', env.DISCORD_CLIENT_ID);
  url.searchParams.set('response_type', 'code');
  url.searchParams.set('redirect_uri', env.OAUTH_REDIRECT_URI);
  url.searchParams.set('scope', 'identify guilds');
  url.searchParams.set('state', state);
  return url.toString();
}

export async function exchangeCode(code: string) {
  const body = new URLSearchParams({
    client_id: env.DISCORD_CLIENT_ID,
    client_secret: env.DISCORD_CLIENT_SECRET,
    grant_type: 'authorization_code',
    code,
    redirect_uri: env.OAUTH_REDIRECT_URI
  });

  const response = await fetch(`${API}/oauth2/token`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body
  });

  if (!response.ok) throw new Error(`Échec OAuth2 Discord (${response.status})`);
  return response.json() as Promise<{
    access_token: string;
    refresh_token?: string;
    expires_in: number;
  }>;
}

async function discordGet<T>(path: string, accessToken: string): Promise<T> {
  const response = await fetch(`${API}${path}`, {
    headers: { Authorization: `Bearer ${accessToken}` }
  });
  if (!response.ok) throw new Error(`Discord API ${path} (${response.status})`);
  return response.json() as Promise<T>;
}

export const fetchDiscordUser = (token: string) => discordGet<DiscordUser>('/users/@me', token);
export const fetchDiscordGuilds = (token: string) => discordGet<DiscordGuildSummary[]>('/users/@me/guilds', token);

export function canManageGuild(guild: DiscordGuildSummary): boolean {
  const permissions = BigInt(guild.permissions);
  const administrator = 1n << 3n;
  const manageGuild = 1n << 5n;
  return guild.owner || (permissions & administrator) === administrator || (permissions & manageGuild) === manageGuild;
}
