import { hasManageGuildPermission, type DashboardGuild } from '@nexumi/shared';
import { fetchDiscordUserGuildsCached } from './discord-oauth';
import { hasOwnerGuildBypass } from './owner-auth';
import { getOwnerGuildDiscordMeta } from './owner-guilds';
import { prisma } from './prisma';
import type { SessionPayload } from './session';

/** Administrator bit — used for synthetic owner-bypass guild entries. */
const ADMINISTRATOR_PERMISSION = '8';

/**
 * Returns the guilds the current session user can manage (Manage Guild
 * permission), enriched with whether Nexumi is already installed there.
 * Guilds where the bot is present are sorted first.
 */
export async function getManageableGuilds(session: SessionPayload): Promise<DashboardGuild[]> {
  const discordGuilds = await fetchDiscordUserGuildsCached(session.accessToken);
  const manageable = discordGuilds.filter((guild) => hasManageGuildPermission(guild.permissions));

  if (manageable.length === 0) {
    return [];
  }

  const presentGuilds = await prisma.guild.findMany({
    where: { id: { in: manageable.map((guild) => guild.id) } },
    select: { id: true }
  });
  const presentIds = new Set(presentGuilds.map((guild) => guild.id));

  return manageable
    .map<DashboardGuild>((guild) => ({
      id: guild.id,
      name: guild.name,
      icon: guild.icon,
      botPresent: presentIds.has(guild.id),
      permissions: guild.permissions
    }))
    .sort((a, b) => {
      if (a.botPresent !== b.botPresent) {
        return a.botPresent ? -1 : 1;
      }
      return a.name.localeCompare(b.name);
    });
}

/**
 * Looks up a single manageable guild by id, or null when the session user
 * does not manage it via Discord OAuth.
 */
export async function getManageableGuild(
  session: SessionPayload,
  guildId: string
): Promise<DashboardGuild | null> {
  const guilds = await getManageableGuilds(session);
  return guilds.find((guild) => guild.id === guildId) ?? null;
}

/**
 * Resolves a guild for the dashboard shell: normal Manage Guild membership,
 * or owner-panel bypass via Discord bot guild metadata when the bot is
 * installed but the user is not a Discord manager of that server.
 */
export async function resolveDashboardGuild(
  session: SessionPayload,
  guildId: string
): Promise<{ guild: DashboardGuild; ownerBypass: boolean } | null> {
  const managed = await getManageableGuild(session, guildId);
  if (managed?.botPresent) {
    return { guild: managed, ownerBypass: false };
  }

  if (!(await hasOwnerGuildBypass(session.user.id))) {
    return managed ? { guild: managed, ownerBypass: false } : null;
  }

  const dbGuild = await prisma.guild.findUnique({ where: { id: guildId } });
  if (!dbGuild) {
    return null;
  }

  const meta = await getOwnerGuildDiscordMeta(guildId);
  return {
    ownerBypass: true,
    guild: {
      id: guildId,
      name: meta?.name ?? `Guild ${guildId}`,
      icon: meta?.icon ?? null,
      botPresent: true,
      permissions: ADMINISTRATOR_PERMISSION
    }
  };
}
