import { moderationQueue } from '../../queues.js';
import type { BotContext } from '../../types.js';
import { PermissionFlagsBits, type ChatInputCommandInteraction } from 'discord.js';
import type { Prisma } from '@prisma/client';
import { buildCaseMetadata, type CaseAuditSource } from '@nexumi/shared';

type CreateCaseInput = {
  guildId: string;
  targetUserId: string;
  moderatorId: string;
  action: string;
  reason?: string;
  source?: CaseAuditSource;
  channelId?: string;
  metadata?: Record<string, unknown>;
};

export async function createCase(context: BotContext, input: CreateCaseInput) {
  await context.prisma.guild.upsert({
    where: { id: input.guildId },
    update: {},
    create: { id: input.guildId }
  });

  const lastCase = await context.prisma.case.findFirst({
    where: { guildId: input.guildId },
    orderBy: { caseNumber: 'desc' }
  });

  const metadata = buildCaseMetadata({
    source: input.source ?? 'slash_command',
    channelId: input.channelId,
    extras: input.metadata
  });

  return context.prisma.case.create({
    data: {
      guildId: input.guildId,
      caseNumber: (lastCase?.caseNumber ?? 0) + 1,
      targetUserId: input.targetUserId,
      moderatorId: input.moderatorId,
      action: input.action,
      reason: input.reason,
      metadata: metadata as Prisma.InputJsonValue
    }
  }).then(async (created) => {
    const { logModAction } = await import('../logging/events.js');
    await logModAction(context, {
      guildId: input.guildId,
      caseNumber: created.caseNumber,
      action: input.action,
      targetUserId: input.targetUserId,
      moderatorId: input.moderatorId,
      reason: input.reason
    });
    return created;
  });
}

export async function scheduleTempBanExpire(
  guildId: string,
  userId: string,
  durationMs: number,
  reason?: string
) {
  await moderationQueue.add(
    'tempBanExpire',
    { guildId, userId, reason: reason ?? null },
    {
      delay: durationMs,
      removeOnComplete: 1000,
      removeOnFail: 500
    }
  );
}

export async function applyWarnEscalation(
  interaction: ChatInputCommandInteraction,
  context: BotContext,
  userId: string,
  moderatorId: string
): Promise<string | null> {
  const guildId = interaction.guildId;
  if (!guildId || !interaction.guild) {
    return null;
  }

  const warningCount = await context.prisma.warning.count({
    where: { guildId, userId }
  });

  const rule = await context.prisma.escalationRule.findUnique({
    where: { guildId_warnCount: { guildId, warnCount: warningCount } }
  });

  if (!rule || !rule.enabled) {
    return null;
  }

  const member = await interaction.guild.members.fetch(userId);
  const reason = rule.reason ?? `Auto escalation at ${warningCount} warnings`;

  if (rule.action === 'TIMEOUT') {
    if (!rule.durationMs) {
      return `Escalation rule for ${warningCount} warns skipped (missing duration).`;
    }
    if (!interaction.guild.members.me?.permissions.has(PermissionFlagsBits.ModerateMembers)) {
      return `Escalation rule for ${warningCount} warns skipped (missing bot permissions).`;
    }
    await member.timeout(rule.durationMs, reason);
    await createCase(context, {
      guildId,
      targetUserId: userId,
      moderatorId,
      action: 'TIMEOUT',
      reason,
      channelId: interaction.channelId ?? undefined,
      source: 'escalation',
      metadata: { escalation: true, durationMs: rule.durationMs, warningCount }
    });
    return `Auto escalation applied: timeout (${rule.durationMs} ms).`;
  }

  if (rule.action === 'KICK') {
    if (!interaction.guild.members.me?.permissions.has(PermissionFlagsBits.KickMembers)) {
      return `Escalation rule for ${warningCount} warns skipped (missing bot permissions).`;
    }
    await member.kick(reason);
    await createCase(context, {
      guildId,
      targetUserId: userId,
      moderatorId,
      action: 'KICK',
      reason,
      channelId: interaction.channelId ?? undefined,
      source: 'escalation',
      metadata: { escalation: true, warningCount }
    });
    return 'Auto escalation applied: kick.';
  }

  if (!interaction.guild.members.me?.permissions.has(PermissionFlagsBits.BanMembers)) {
    return `Escalation rule for ${warningCount} warns skipped (missing bot permissions).`;
  }
  await interaction.guild.members.ban(userId, { reason });
  await createCase(context, {
    guildId,
    targetUserId: userId,
    moderatorId,
    action: 'BAN',
    reason,
    channelId: interaction.channelId ?? undefined,
    source: 'escalation',
    metadata: { escalation: true, warningCount }
  });
  return 'Auto escalation applied: ban.';
}
