/**
 * Activity Log (Audit Trail) Model
 *
 * A platform-wide, INDEPENDENT audit layer that passively records every
 * significant action. It is intentionally separate from the existing
 * `AuditLog` model so the pre-existing admin audit page keeps working
 * unchanged — this collection is written to only by the global activity-capture
 * middleware and the central `activityLogger` service.
 *
 * Designed for high volume: lean documents, targeted compound indexes, and a
 * TTL index that auto-expires old entries.
 */

import mongoose, { Schema, Document } from 'mongoose';

export type ActivityStatus = 'success' | 'failed' | 'pending';

export interface IActivityLog extends Document {
  userId?: mongoose.Types.ObjectId | string | null;
  userName?: string;
  userEmail?: string;
  organizationId?: string | null;
  /** High-level module the action belongs to (e.g. 'auth', 'blogs', 'products'). */
  module: string;
  /** The action performed (e.g. 'create', 'update', 'delete', 'login'). */
  action: string;
  /** Human-readable one-line description. */
  description?: string;
  status: ActivityStatus;
  entityType?: string;
  entityId?: string;
  /** Snapshot of previous state (masked). */
  oldValue?: unknown;
  /** Snapshot of new state (masked). */
  newValue?: unknown;
  requestMethod?: string;
  requestUrl?: string;
  ipAddress?: string;
  browser?: string;
  device?: string;
  os?: string;
  sessionId?: string;
  requestId?: string;
  /** Server-measured request handling time in milliseconds. */
  durationMs?: number;
  /** Final HTTP status code of the request. */
  httpStatusCode?: number;
  /** Arbitrary extra context (masked). */
  metadata?: Record<string, unknown>;
  /** Populated when status === 'failed'. */
  errorDetails?: string;
  createdAt: Date;
  updatedAt: Date;
}

const ActivityLogSchema = new Schema<IActivityLog>(
  {
    userId: { type: Schema.Types.Mixed, default: null, index: true },
    userName: { type: String },
    userEmail: { type: String },
    organizationId: { type: String, default: null, index: true },
    module: { type: String, required: true, index: true },
    action: { type: String, required: true, index: true },
    description: { type: String },
    status: { type: String, enum: ['success', 'failed', 'pending'], default: 'success', index: true },
    entityType: { type: String },
    entityId: { type: String },
    oldValue: { type: Schema.Types.Mixed },
    newValue: { type: Schema.Types.Mixed },
    requestMethod: { type: String },
    requestUrl: { type: String },
    ipAddress: { type: String },
    browser: { type: String },
    device: { type: String },
    os: { type: String },
    sessionId: { type: String },
    requestId: { type: String },
    durationMs: { type: Number },
    httpStatusCode: { type: Number },
    metadata: { type: Schema.Types.Mixed },
    errorDetails: { type: String },
  },
  { timestamps: true },
);

// Compound indexes tuned for the list-page queries (newest-first + filters).
ActivityLogSchema.index({ createdAt: -1 });
ActivityLogSchema.index({ module: 1, createdAt: -1 });
ActivityLogSchema.index({ action: 1, createdAt: -1 });
ActivityLogSchema.index({ status: 1, createdAt: -1 });
ActivityLogSchema.index({ userId: 1, createdAt: -1 });
ActivityLogSchema.index({ organizationId: 1, createdAt: -1 });

// TTL: auto-remove entries older than 1 year to keep the collection bounded.
ActivityLogSchema.index({ createdAt: 1 }, { expireAfterSeconds: 365 * 24 * 60 * 60 });

export const ActivityLog =
  mongoose.models.ActivityLog || mongoose.model<IActivityLog>('ActivityLog', ActivityLogSchema);
