import { and, desc, eq, gte, lte } from "drizzle-orm"
import { db } from "../../../db/index.js"
import { events } from "../../../db/schema.js"
import type { EventItem, EventLevel, EventSourceModule } from "@mmapp/contracts/events"

export type EventInsertInput = {
  id: string
  createdAt: string
  level: EventLevel
  eventType: string
  sourceModule: EventSourceModule
  title: string
  message: string
  entityType?: string
  entityId?: string
  payload?: Record<string, unknown>
}

export type ListEventsParams = {
  limit: number
  level?: EventLevel
  sourceModule?: EventSourceModule
  from?: string
  to?: string
}

function parsePayload(payloadJson: string | null): Record<string, unknown> {
  if (!payloadJson) return {}
  try {
    const parsed = JSON.parse(payloadJson) as unknown
    if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
      return parsed as Record<string, unknown>
    }
  } catch {
    // keep backwards compatibility with malformed legacy payloads
  }
  return {}
}

function mapEventRow(row: typeof events.$inferSelect): EventItem {
  return {
    id: row.id,
    createdAt: row.createdAt,
    level: row.level,
    eventType: row.eventType,
    sourceModule: row.sourceModule as EventSourceModule,
    title: row.title,
    message: row.message,
    entityType: row.entityType ?? null,
    entityId: row.entityId ?? null,
    payload: parsePayload(row.payloadJson ?? null),
  }
}

export function insertEventsBatch(items: EventInsertInput[]) {
  if (items.length === 0) return
  db.insert(events)
    .values(
      items.map((item) => ({
        id: item.id,
        createdAt: item.createdAt,
        level: item.level,
        eventType: item.eventType,
        sourceModule: item.sourceModule,
        title: item.title,
        message: item.message,
        entityType: item.entityType ?? null,
        entityId: item.entityId ?? null,
        payloadJson: item.payload ? JSON.stringify(item.payload) : null,
      })),
    )
    .run()
}

export function listEvents(params: ListEventsParams): EventItem[] {
  const where = and(
    params.level ? eq(events.level, params.level) : undefined,
    params.sourceModule ? eq(events.sourceModule, params.sourceModule) : undefined,
    params.from ? gte(events.createdAt, params.from) : undefined,
    params.to ? lte(events.createdAt, params.to) : undefined,
  )
  const rows = db
    .select()
    .from(events)
    .where(where)
    .orderBy(desc(events.createdAt))
    .limit(params.limit)
    .all()
  return rows.map(mapEventRow)
}
