import type { StatsConfigDashboard, StatsConfigDashboardPatch } from '@nexumi/shared';
import { prisma } from '../prisma';
import { addJobAndAwait, getStatsQueue, getStatsQueueEvents } from '../queues';

async function ensureStatsConfig(guildId: string) {
  await prisma.guild.upsert({ where: { id: guildId }, update: {}, create: { id: guildId } });
  return prisma.statsConfig.upsert({ where: { guildId }, update: {}, create: { guildId } });
}

function toDashboard(config: Awaited<ReturnType<typeof ensureStatsConfig>>): StatsConfigDashboard {
  return {
    enabled: config.enabled,
    membersChannelId: config.membersChannelId ?? '',
    onlineChannelId: config.onlineChannelId ?? '',
    boostsChannelId: config.boostsChannelId ?? '',
    membersTemplate: config.membersTemplate,
    onlineTemplate: config.onlineTemplate,
    boostsTemplate: config.boostsTemplate
  };
}

/**
 * Dashboard has no discord.js Client, so channel renames are delegated to the bot
 * via the `stats` BullMQ queue (`statsRefreshGuild`).
 */
async function enqueueStatsRefresh(guildId: string): Promise<void> {
  const { confirmed } = await addJobAndAwait(
    getStatsQueue(),
    getStatsQueueEvents(),
    'statsRefreshGuild',
    { guildId },
    {
      jobId: `stats-refresh-${guildId}-${Date.now()}`,
      removeOnComplete: true,
      removeOnFail: 25
    },
    30_000
  );

  if (!confirmed) {
    console.warn('[stats] guild refresh not confirmed in time', { guildId });
  }
}

async function maybeRefreshStatsChannels(guildId: string): Promise<void> {
  const config = await prisma.statsConfig.findUnique({ where: { guildId } });
  if (
    !config?.enabled ||
    (!config.membersChannelId && !config.onlineChannelId && !config.boostsChannelId)
  ) {
    return;
  }

  // Config save must succeed even if Discord rename fails (permissions / bot down).
  try {
    await enqueueStatsRefresh(guildId);
  } catch (error) {
    console.warn('[stats] refresh after dashboard save failed', { guildId, error });
  }
}

export async function getStatsDashboard(guildId: string): Promise<StatsConfigDashboard> {
  const config = await ensureStatsConfig(guildId);
  return toDashboard(config);
}

export async function updateStatsDashboard(
  guildId: string,
  patch: StatsConfigDashboardPatch
): Promise<StatsConfigDashboard> {
  await ensureStatsConfig(guildId);

  const { membersChannelId, onlineChannelId, boostsChannelId, ...rest } = patch;
  const updated = await prisma.statsConfig.update({
    where: { guildId },
    data: {
      ...rest,
      ...(membersChannelId !== undefined
        ? { membersChannelId: membersChannelId === '' ? null : membersChannelId }
        : {}),
      ...(onlineChannelId !== undefined
        ? { onlineChannelId: onlineChannelId === '' ? null : onlineChannelId }
        : {}),
      ...(boostsChannelId !== undefined
        ? { boostsChannelId: boostsChannelId === '' ? null : boostsChannelId }
        : {})
    }
  });

  await maybeRefreshStatsChannels(guildId);
  return toDashboard(updated);
}
