/**
 * AuditLog Entity
 *
 * Tracks all important actions in the system for security and compliance
 *
 * Business Rules:
 * - Every sensitive action must be logged
 * - Audit logs are immutable (cannot be edited or deleted)
 * - Must capture user, action, resource, and timestamp
 * - Support filtering and searching for compliance audits
 */

export enum AuditAction {
  // Booking actions
  BOOKING_CREATED = 'booking_created',
  BOOKING_UPDATED = 'booking_updated',
  BOOKING_CANCELLED = 'booking_cancelled',
  BOOKING_STATUS_CHANGED = 'booking_status_changed',

  // User actions
  USER_LOGIN = 'user_login',
  USER_LOGOUT = 'user_logout',
  USER_CREATED = 'user_created',
  USER_UPDATED = 'user_updated',
  USER_DELETED = 'user_deleted',
  USER_ROLE_CHANGED = 'user_role_changed',

  // Organization actions
  ORGANIZATION_CREATED = 'organization_created',
  ORGANIZATION_UPDATED = 'organization_updated',

  // Document actions
  DOCUMENT_UPLOADED = 'document_uploaded',
  DOCUMENT_DOWNLOADED = 'document_downloaded',
  DOCUMENT_DELETED = 'document_deleted',

  // Rate actions
  RATE_SEARCHED = 'rate_searched',

  // Export actions
  DATA_EXPORTED = 'data_exported',

  // Settings actions
  SETTINGS_UPDATED = 'settings_updated',
}

export enum AuditStatus {
  SUCCESS = 'success',
  FAILURE = 'failure',
  WARNING = 'warning',
}

export interface AuditLogProps {
  id: string;
  action: AuditAction;
  status: AuditStatus;
  userId: string;
  userEmail: string;
  organizationId: string;
  resourceType?: string; // e.g., 'booking', 'user', 'document'
  resourceId?: string;
  resourceName?: string;
  metadata?: Record<string, any>; // Additional context
  ipAddress?: string;
  userAgent?: string;
  errorMessage?: string;
  timestamp: Date;
}

export class AuditLog {
  private readonly props: AuditLogProps;

  private constructor(props: AuditLogProps) {
    this.props = props;
  }

  /**
   * Factory method to create a new audit log entry
   */
  static create(props: Omit<AuditLogProps, 'id' | 'timestamp'> & { id: string }): AuditLog {
    return new AuditLog({
      ...props,
      timestamp: new Date(),
    });
  }

  /**
   * Factory method to reconstitute from persistence
   */
  static fromPersistence(props: AuditLogProps): AuditLog {
    return new AuditLog(props);
  }

  // Getters
  get id(): string {
    return this.props.id;
  }

  get action(): AuditAction {
    return this.props.action;
  }

  get status(): AuditStatus {
    return this.props.status;
  }

  get userId(): string {
    return this.props.userId;
  }

  get userEmail(): string {
    return this.props.userEmail;
  }

  get organizationId(): string {
    return this.props.organizationId;
  }

  get resourceType(): string | undefined {
    return this.props.resourceType;
  }

  get resourceId(): string | undefined {
    return this.props.resourceId;
  }

  get resourceName(): string | undefined {
    return this.props.resourceName;
  }

  get metadata(): Record<string, any> | undefined {
    return this.props.metadata;
  }

  get ipAddress(): string | undefined {
    return this.props.ipAddress;
  }

  get userAgent(): string | undefined {
    return this.props.userAgent;
  }

  get errorMessage(): string | undefined {
    return this.props.errorMessage;
  }

  get timestamp(): Date {
    return this.props.timestamp;
  }

  /**
   * Check if action was successful
   */
  isSuccessful(): boolean {
    return this.props.status === AuditStatus.SUCCESS;
  }

  /**
   * Check if action failed
   */
  isFailed(): boolean {
    return this.props.status === AuditStatus.FAILURE;
  }

  /**
   * Convert to plain object
   */
  toObject(): AuditLogProps {
    return {
      ...this.props,
      metadata: this.props.metadata ? { ...this.props.metadata } : undefined,
    };
  }
}
