import type { DiscordChannelOption, DiscordRoleOption } from '@nexumi/shared';
import { DASHBOARD_CHANNEL_TYPES } from './discord-channel-types';
import { env } from './env';
import { redis } from './redis';

const DISCORD_API_BASE = 'https://discord.com/api/v10';
const CACHE_TTL_SECONDS = 60;

export async function discordBotFetch<T>(
  path: string,
  init?: { method?: string; body?: unknown }
): Promise<T> {
  const method = init?.method ?? 'GET';
  const response = await fetch(`${DISCORD_API_BASE}${path}`, {
    method,
    headers: {
      Authorization: `Bot ${env.BOT_TOKEN}`,
      ...(init?.body !== undefined ? { 'Content-Type': 'application/json' } : {})
    },
    body: init?.body !== undefined ? JSON.stringify(init.body) : undefined,
    cache: 'no-store'
  });
  if (!response.ok) {
    throw new Error(`Discord API request to ${path} failed with status ${response.status}`);
  }
  if (response.status === 204) {
    return undefined as T;
  }
  return (await response.json()) as T;
}

interface DiscordChannelRest {
  id: string;
  name: string;
  type: number;
  parent_id?: string | null;
  position?: number;
}

interface DiscordRoleRest {
  id: string;
  name: string;
  color: number;
  position: number;
  managed?: boolean;
}

export async function listGuildChannelsForDashboard(guildId: string): Promise<DiscordChannelOption[]> {
  const cacheKey = `dashboard:guild:${guildId}:channels:v2`;
  const cached = await redis.get(cacheKey);
  if (cached) {
    return JSON.parse(cached) as DiscordChannelOption[];
  }

  const channels = await discordBotFetch<DiscordChannelRest[]>(`/guilds/${guildId}/channels`);
  const options = channels
    .filter((channel) => DASHBOARD_CHANNEL_TYPES.has(channel.type))
    .map((channel) => ({
      id: channel.id,
      name: channel.name,
      type: channel.type,
      parentId: channel.parent_id ?? null
    }))
    .sort((a, b) => a.name.localeCompare(b.name));

  await redis.set(cacheKey, JSON.stringify(options), 'EX', CACHE_TTL_SECONDS);
  return options;
}

export async function listGuildRolesForDashboard(guildId: string): Promise<DiscordRoleOption[]> {
  const cacheKey = `dashboard:guild:${guildId}:roles`;
  const cached = await redis.get(cacheKey);
  if (cached) {
    return JSON.parse(cached) as DiscordRoleOption[];
  }

  const roles = await discordBotFetch<DiscordRoleRest[]>(`/guilds/${guildId}/roles`);
  const options = roles
    .filter((role) => role.name !== '@everyone')
    .map((role) => ({
      id: role.id,
      name: role.name,
      color: role.color,
      position: role.position
    }))
    .sort((a, b) => b.position - a.position);

  await redis.set(cacheKey, JSON.stringify(options), 'EX', CACHE_TTL_SECONDS);
  return options;
}

export { CHANNEL_TYPES, channelPrefix, type ChannelKind } from './discord-channel-types';
