import { logAudit, type AuditEvent, type LogAuditResult } from '@platform-modules/audit'

export type LegacyAuditChanges = Record<string, [unknown, unknown]>

export type LegacyAuditWrite = {
  tenantId: string
  actorId?: string | null
  actorType?: string | null
  apiKeyId?: string | null
  entityType: string
  entityId: string
  action: string
  changes?: LegacyAuditChanges | null
  requestId?: string | null
  ip?: string | null
}

export type LegacyAuditRow = LegacyAuditWrite & {
  id: string
  createdAt: Date
}

export type PlatformAuditBackfillRow = {
  id: string
  tenantId: string
  actorId: string | null
  actorType: string | null
  actorLabel: string | null
  entityType: string
  entityId: string
  action: string
  metadata: Record<string, unknown> | null
  ip: string | null
  createdAt: Date
}

function buildActorLabel(input: { actorType?: string | null; apiKeyId?: string | null }): string | null {
  if (input.actorType === 'api_key' && input.apiKeyId) {
    return `api_key:${input.apiKeyId}`
  }
  return null
}

function buildMetadata(input: {
  apiKeyId?: string | null
  changes?: LegacyAuditChanges | null
  requestId?: string | null
}): Record<string, unknown> | null {
  const metadata = Object.fromEntries(
    Object.entries({
      apiKeyId: input.apiKeyId ?? null,
      changes: input.changes ?? null,
      requestId: input.requestId ?? null,
    }).filter(([, value]) => value !== null),
  )

  return Object.keys(metadata).length > 0 ? metadata : null
}

export function toPlatformAuditEvent(input: LegacyAuditWrite): AuditEvent {
  return {
    tenantId: input.tenantId,
    actorId: input.actorId ?? null,
    actorType: input.actorType ?? null,
    actorLabel: buildActorLabel(input),
    action: input.action,
    entityType: input.entityType,
    entityId: input.entityId,
    metadata: buildMetadata(input),
    ip: input.ip ?? null,
  }
}

export async function recordAudit(
  db: Parameters<typeof logAudit>[0],
  input: LegacyAuditWrite,
): Promise<LogAuditResult> {
  return logAudit(db, toPlatformAuditEvent(input))
}

export function buildPlatformAuditBackfillRows(rows: LegacyAuditRow[]): PlatformAuditBackfillRow[] {
  return rows.map((row) => ({
    id: row.id,
    tenantId: row.tenantId,
    actorId: row.actorId ?? null,
    actorType: row.actorType ?? null,
    actorLabel: buildActorLabel(row),
    entityType: row.entityType,
    entityId: row.entityId,
    action: row.action,
    metadata: buildMetadata(row),
    ip: row.ip ?? null,
    createdAt: row.createdAt,
  }))
}

export function createLegacyAuditInsertValues(event: AuditEvent): LegacyAuditWrite {
  const metadata = event.metadata ?? {}
  const changes = metadata.changes
  const requestId = metadata.requestId
  const apiKeyId = metadata.apiKeyId

  return {
    tenantId: event.tenantId ?? '',
    actorId: event.actorId ?? null,
    actorType: event.actorType ?? 'user',
    apiKeyId: typeof apiKeyId === 'string' ? apiKeyId : null,
    entityType: event.entityType,
    entityId: event.entityId,
    action: event.action,
    changes: isLegacyAuditChanges(changes) ? changes : null,
    requestId: typeof requestId === 'string' ? requestId : null,
    ip: event.ip ?? null,
  }
}

function isLegacyAuditChanges(value: unknown): value is LegacyAuditChanges {
  if (!value || typeof value !== 'object') return false
  return Object.values(value).every((entry) => Array.isArray(entry) && entry.length === 2)
}
