import { EventSeverity, Prisma } from '@prisma/client';
import { prisma } from '../lib/prisma';
import { logger } from '../utils/logger';

// ─── Event Creation ───────────────────────────────────────────────

/**
 * Create an instance event (error, warning, or info).
 * Deduplicates: won't create a duplicate event if one with the same
 * source + title exists for this instance within the last 5 minutes.
 */
export async function createEvent(
  instanceId: string,
  severity: 'ERROR' | 'WARNING' | 'INFO',
  source: string,
  title: string,
  message: string,
  metadata?: Record<string, unknown>
): Promise<void> {
  // Deduplicate: avoid spamming the same event within 5 minutes
  const fiveMinAgo = new Date(Date.now() - 5 * 60 * 1000);
  const existing = await prisma.instanceEvent.findFirst({
    where: {
      instanceId,
      source,
      title,
      createdAt: { gte: fiveMinAgo },
    },
  });

  if (existing) {
    logger.debug(`[events] Skipping duplicate event: ${title} for instance ${instanceId}`);
    return;
  }

  await prisma.instanceEvent.create({
    data: {
      instanceId,
      severity: severity as EventSeverity,
      source,
      title,
      message,
      metadata: metadata as Prisma.InputJsonValue ?? undefined,
    },
  });

  logger.info(`[events] ${severity} event for instance ${instanceId}: ${title}`);
}

// ─── Event Queries ────────────────────────────────────────────────

export interface EventFilters {
  instanceId?: string;
  severity?: EventSeverity;
  acknowledged?: boolean;
  source?: string;
  from?: Date;
  to?: Date;
  page?: number;
  limit?: number;
}

/**
 * List events across all instances with filtering and pagination.
 */
export async function listEvents(filters: EventFilters) {
  const page = filters.page || 1;
  const limit = Math.min(filters.limit || 50, 100);

  const where: Prisma.InstanceEventWhereInput = {};
  if (filters.instanceId) where.instanceId = filters.instanceId;
  if (filters.severity) where.severity = filters.severity;
  if (filters.acknowledged !== undefined) where.acknowledged = filters.acknowledged;
  if (filters.source) where.source = filters.source;
  if (filters.from || filters.to) {
    where.createdAt = {};
    if (filters.from) where.createdAt.gte = filters.from;
    if (filters.to) where.createdAt.lte = filters.to;
  }

  const [data, total] = await Promise.all([
    prisma.instanceEvent.findMany({
      where,
      orderBy: { createdAt: 'desc' },
      skip: (page - 1) * limit,
      take: limit,
      include: {
        instance: { select: { id: true, name: true, slug: true } },
        acknowledgedBy: { select: { id: true, name: true, email: true } },
      },
    }),
    prisma.instanceEvent.count({ where }),
  ]);

  return { data, total, page, limit };
}

/**
 * List events for a single instance.
 */
export async function listInstanceEvents(instanceId: string, page = 1, limit = 50) {
  return listEvents({ instanceId, page, limit });
}

/**
 * Acknowledge a single event.
 */
export async function acknowledgeEvent(eventId: string, userId: string) {
  const event = await prisma.instanceEvent.findUnique({ where: { id: eventId } });
  if (!event) throw new Error('Event not found');

  return prisma.instanceEvent.update({
    where: { id: eventId },
    data: {
      acknowledged: true,
      acknowledgedAt: new Date(),
      acknowledgedById: userId,
    },
  });
}

/**
 * Acknowledge all unacknowledged events for an instance.
 */
export async function acknowledgeAllForInstance(instanceId: string, userId: string) {
  const result = await prisma.instanceEvent.updateMany({
    where: {
      instanceId,
      acknowledged: false,
    },
    data: {
      acknowledged: true,
      acknowledgedAt: new Date(),
      acknowledgedById: userId,
    },
  });

  return { acknowledged: result.count };
}

/**
 * Get summary of unacknowledged events by severity (for dashboard).
 */
export async function getUnacknowledgedSummary() {
  const [errors, warnings, infos] = await Promise.all([
    prisma.instanceEvent.count({
      where: { acknowledged: false, severity: EventSeverity.ERROR },
    }),
    prisma.instanceEvent.count({
      where: { acknowledged: false, severity: EventSeverity.WARNING },
    }),
    prisma.instanceEvent.count({
      where: { acknowledged: false, severity: EventSeverity.INFO },
    }),
  ]);

  // Also get the 5 most recent unacknowledged errors for dashboard display
  const recentErrors = await prisma.instanceEvent.findMany({
    where: { acknowledged: false, severity: { in: [EventSeverity.ERROR, EventSeverity.WARNING] } },
    orderBy: { createdAt: 'desc' },
    take: 5,
    include: {
      instance: { select: { id: true, name: true, slug: true } },
    },
  });

  return {
    errors,
    warnings,
    infos,
    total: errors + warnings + infos,
    recentErrors,
  };
}
