import { auditLogs } from '@/db/schema';
import { db } from '@/lib/db';

type AuditValue = Record<string, unknown> | null;

export const AUDIT_MODULE = {
  AUTHENTICATION: 'AUTHENTICATION',
  ORGANIZATIONS: 'ORGANIZATIONS',
  TRAINING_RECORDS: 'TRAINING_RECORDS',
  HRD_REVIEW: 'HRD_REVIEW',
  COURSE_MASTER: 'COURSE_MASTER',
  TRAINING_POLICY: 'TRAINING_POLICY',
  EMPLOYEE_IMPORT: 'EMPLOYEE_IMPORT',
  MASTER_REVIEW: 'MASTER_REVIEW',
  NOTIFICATIONS: 'NOTIFICATIONS',
  ANNOUNCEMENTS: 'ANNOUNCEMENTS',
  ONLINE_LESSONS: 'ONLINE_LESSONS'
} as const;

export const AUDIT_ACTION = {
  LOGIN_SUCCESS: 'LOGIN_SUCCESS',
  LOGIN_FAILED: 'LOGIN_FAILED',
  ORGANIZATION_CREATE: 'ORGANIZATION_CREATE',
  ORGANIZATION_UPDATE: 'ORGANIZATION_UPDATE',
  ORGANIZATION_SOFT_DELETE: 'ORGANIZATION_SOFT_DELETE',
  CREATE: 'CREATE',
  UPDATE: 'UPDATE',
  DELETE: 'DELETE',
  CLONE: 'CLONE',
  ACTIVATE: 'ACTIVATE',
  DEACTIVATE: 'DEACTIVATE',
  APPROVE: 'APPROVE',
  REJECT: 'REJECT',
  IMPORT: 'IMPORT',
  EMPLOYEE_TARGET_CREATE: 'EMPLOYEE_TARGET_CREATE',
  EMPLOYEE_TARGET_UPDATE: 'EMPLOYEE_TARGET_UPDATE',
  NOTIFICATION_MARK_READ: 'NOTIFICATION_MARK_READ',
  NOTIFICATION_MARK_ALL_READ: 'NOTIFICATION_MARK_ALL_READ',
  NOTIFICATION_CREATE: 'NOTIFICATION_CREATE',
  ANNOUNCEMENT_CREATE: 'ANNOUNCEMENT_CREATE',
  ANNOUNCEMENT_DRAFT_SAVED: 'ANNOUNCEMENT_DRAFT_SAVED',
  ANNOUNCEMENT_UPDATE: 'ANNOUNCEMENT_UPDATE',
  ANNOUNCEMENT_SUBMIT: 'ANNOUNCEMENT_SUBMIT',
  ANNOUNCEMENT_APPROVE: 'ANNOUNCEMENT_APPROVE',
  ANNOUNCEMENT_RETURN: 'ANNOUNCEMENT_RETURN',
  ANNOUNCEMENT_REJECT: 'ANNOUNCEMENT_REJECT',
  ANNOUNCEMENT_PUBLISH: 'ANNOUNCEMENT_PUBLISH',
  ANNOUNCEMENT_PINNED: 'ANNOUNCEMENT_PINNED',
  ANNOUNCEMENT_UNPINNED: 'ANNOUNCEMENT_UNPINNED',
  ANNOUNCEMENT_ARCHIVE: 'ANNOUNCEMENT_ARCHIVE',
  ANNOUNCEMENT_DELETE: 'ANNOUNCEMENT_DELETE',
  ONLINE_LESSON_CREATE: 'ONLINE_LESSON_CREATE',
  ONLINE_LESSON_DRAFT_SAVED: 'ONLINE_LESSON_DRAFT_SAVED',
  ONLINE_LESSON_UPDATE: 'ONLINE_LESSON_UPDATE',
  ONLINE_LESSON_SUBMIT: 'ONLINE_LESSON_SUBMIT',
  ONLINE_LESSON_APPROVE: 'ONLINE_LESSON_APPROVE',
  ONLINE_LESSON_RETURN: 'ONLINE_LESSON_RETURN',
  ONLINE_LESSON_REJECT: 'ONLINE_LESSON_REJECT',
  ONLINE_LESSON_PUBLISH: 'ONLINE_LESSON_PUBLISH',
  ONLINE_LESSON_ARCHIVE: 'ONLINE_LESSON_ARCHIVE',
  ONLINE_LESSON_DELETE: 'ONLINE_LESSON_DELETE'
} as const;

export async function logAuditEvent({
  organizationId,
  userId,
  module,
  action,
  entityName,
  entityId,
  oldValue,
  newValue,
  ipAddress,
  userAgent
}: {
  organizationId?: string | null;
  userId?: string | null;
  module: string;
  action: string;
  entityName?: string | null;
  entityId?: string | number | null;
  oldValue?: AuditValue;
  newValue?: AuditValue;
  ipAddress?: string | null;
  userAgent?: string | null;
}) {
  try {
    await db.insert(auditLogs).values({
      organizationId: organizationId ?? null,
      userId: userId ?? null,
      moduleName: module,
      action,
      entityName: entityName ?? null,
      entityId: entityId === undefined || entityId === null ? null : String(entityId),
      oldValue: oldValue ?? null,
      newValue: newValue ?? null,
      ipAddress: ipAddress ?? null,
      userAgent: userAgent ?? null
    });
  } catch (error) {
    console.error('Failed to write audit log', error);
  }
}

export function getRequestMetadata(request: Request) {
  const forwardedFor = request.headers.get('x-forwarded-for');
  const realIp = request.headers.get('x-real-ip');

  return {
    ipAddress: forwardedFor?.split(',')[0]?.trim() || realIp?.trim() || null,
    userAgent: request.headers.get('user-agent')?.trim() || null
  };
}

export function toAuditValue<T>(value: T): AuditValue {
  if (value === undefined || value === null) {
    return null;
  }

  return JSON.parse(JSON.stringify(value)) as Record<string, unknown>;
}
