import type { LevelingConfigDashboard, LevelingConfigDashboardPatch } from '@nexumi/shared';
import type { Prisma } from '@prisma/client';
import { prisma } from '../prisma';

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

function toMultiplierMap(raw: unknown): Record<string, number> {
  if (!raw || typeof raw !== 'object') {
    return {};
  }
  const entries = Object.entries(raw as Record<string, unknown>).filter(
    (entry): entry is [string, number] => typeof entry[1] === 'number'
  );
  return Object.fromEntries(entries);
}

function toDashboard(config: Awaited<ReturnType<typeof ensureLevelingConfig>>): LevelingConfigDashboard {
  return {
    enabled: config.enabled,
    textXpMin: config.textXpMin,
    textXpMax: config.textXpMax,
    textCooldownSeconds: config.textCooldownSeconds,
    voiceXpPerMinute: config.voiceXpPerMinute,
    noXpChannelIds: config.noXpChannelIds,
    noXpRoleIds: config.noXpRoleIds,
    roleMultipliers: toMultiplierMap(config.roleMultipliers),
    channelMultipliers: toMultiplierMap(config.channelMultipliers),
    levelUpMode: config.levelUpMode as LevelingConfigDashboard['levelUpMode'],
    levelUpChannelId: config.levelUpChannelId ?? '',
    levelUpMessage: config.levelUpMessage,
    stackRewards: config.stackRewards,
    cardAccentColor: config.cardAccentColor,
    cardBackgroundColor: config.cardBackgroundColor
  };
}

export async function getLevelingDashboard(guildId: string): Promise<LevelingConfigDashboard> {
  const config = await ensureLevelingConfig(guildId);
  return toDashboard(config);
}

export async function updateLevelingDashboard(
  guildId: string,
  patch: LevelingConfigDashboardPatch
): Promise<LevelingConfigDashboard> {
  await ensureLevelingConfig(guildId);

  const { levelUpChannelId, roleMultipliers, channelMultipliers, ...rest } = patch;
  const data: Prisma.LevelingConfigUpdateInput = { ...rest };
  if (levelUpChannelId !== undefined) {
    data.levelUpChannelId = levelUpChannelId === '' ? null : levelUpChannelId;
  }
  if (roleMultipliers !== undefined) {
    data.roleMultipliers = roleMultipliers as Prisma.InputJsonValue;
  }
  if (channelMultipliers !== undefined) {
    data.channelMultipliers = channelMultipliers as Prisma.InputJsonValue;
  }

  const updated = await prisma.levelingConfig.update({ where: { guildId }, data });
  return toDashboard(updated);
}
