import {
  ABOUT_REDIS_KEY,
  BotAboutConfigPatchSchema,
  BotAboutConfigSchema,
  MessageComponentsV2Schema,
  WelcomeEmbedSchema,
  type BotAboutConfig,
  type MessageComponentsV2,
  type WelcomeEmbed
} from '@nexumi/shared';
import { Prisma } from '@prisma/client';
import { prisma } from './prisma';
import { redis } from './redis';

function parseEmbed(raw: unknown): WelcomeEmbed | null {
  const parsed = WelcomeEmbedSchema.safeParse(raw);
  return parsed.success ? parsed.data : null;
}

function parseComponents(raw: unknown): MessageComponentsV2 | null {
  const parsed = MessageComponentsV2Schema.safeParse(raw);
  return parsed.success ? parsed.data : null;
}

function mapRow(row: {
  enabled: boolean;
  messageType: string;
  content: string | null;
  embed: unknown;
  components: unknown;
}): BotAboutConfig {
  return BotAboutConfigSchema.parse({
    enabled: row.enabled,
    messageType: row.messageType,
    content: row.content,
    embed: parseEmbed(row.embed),
    components: parseComponents(row.components)
  });
}

export async function getAboutConfig(): Promise<BotAboutConfig> {
  const row = await prisma.botAboutConfig.upsert({
    where: { id: 'singleton' },
    create: { id: 'singleton' },
    update: {}
  });
  return mapRow(row);
}

export async function updateAboutConfig(patch: unknown): Promise<BotAboutConfig> {
  const data = BotAboutConfigPatchSchema.parse(patch);
  const current = await getAboutConfig();
  const next = { ...current, ...data };

  const row = await prisma.botAboutConfig.upsert({
    where: { id: 'singleton' },
    create: {
      id: 'singleton',
      enabled: next.enabled,
      messageType: next.messageType,
      content: next.content,
      embed: next.embed === null ? Prisma.JsonNull : (next.embed as Prisma.InputJsonValue),
      components:
        next.components === null ? Prisma.JsonNull : (next.components as Prisma.InputJsonValue)
    },
    update: {
      enabled: next.enabled,
      messageType: next.messageType,
      content: next.content,
      embed: next.embed === null ? Prisma.JsonNull : (next.embed as Prisma.InputJsonValue),
      components:
        next.components === null ? Prisma.JsonNull : (next.components as Prisma.InputJsonValue)
    }
  });
  const mapped = mapRow(row);
  await redis.set(ABOUT_REDIS_KEY, JSON.stringify(mapped));
  return mapped;
}
