/**
 * Admin Activity Logger
 * Tracks all admin actions for audit trails and compliance
 */

export type AdminActionType =
  | 'withdrawal_approved'
  | 'withdrawal_rejected'
  | 'withdrawal_processed'
  | 'batch_approval'
  | 'batch_rejection'
  | 'report_generated'
  | 'report_exported'
  | 'settings_changed'
  | 'user_created'
  | 'user_deleted'
  | 'user_role_changed'
  | 'fraud_alert_acknowledged'
  | 'fraud_alert_dismissed'
  | 'login'
  | 'logout'
  | 'permission_denied'
  | 'data_accessed'
  | 'system_alert';

export interface AdminActivity {
  id: string;
  adminId: number;
  adminEmail: string;
  action: AdminActionType;
  description: string;
  timestamp: Date;
  ipAddress?: string;
  userAgent?: string;
  status: 'success' | 'failure' | 'warning';
  details: Record<string, any>;
  affectedUsers?: number[];
  affectedResources?: string[];
  severity: 'low' | 'medium' | 'high' | 'critical';
}

export interface ActivityFilter {
  adminId?: number;
  action?: AdminActionType[];
  status?: ('success' | 'failure' | 'warning')[];
  severity?: ('low' | 'medium' | 'high' | 'critical')[];
  startDate?: Date;
  endDate?: Date;
  ipAddress?: string;
}

/**
 * Admin Activity Logger Service
 */
export class AdminActivityLoggerService {
  private activities: Map<string, AdminActivity> = new Map();
  private activityHistory: AdminActivity[] = [];
  private maxHistorySize: number = 10000;

  constructor() {}

  /**
   * Log an admin activity
   */
  logActivity(
    adminId: number,
    adminEmail: string,
    action: AdminActionType,
    description: string,
    details: Record<string, any>,
    options?: {
      ipAddress?: string;
      userAgent?: string;
      status?: 'success' | 'failure' | 'warning';
      severity?: 'low' | 'medium' | 'high' | 'critical';
      affectedUsers?: number[];
      affectedResources?: string[];
    }
  ): AdminActivity {
    const activity: AdminActivity = {
      id: `activity_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
      adminId,
      adminEmail,
      action,
      description,
      timestamp: new Date(),
      ipAddress: options?.ipAddress,
      userAgent: options?.userAgent,
      status: options?.status || 'success',
      details,
      affectedUsers: options?.affectedUsers,
      affectedResources: options?.affectedResources,
      severity: options?.severity || 'low',
    };

    // Store activity
    this.activities.set(activity.id, activity);
    this.activityHistory.push(activity);

    // Maintain history size
    if (this.activityHistory.length > this.maxHistorySize) {
      const removed = this.activityHistory.shift();
      if (removed) {
        this.activities.delete(removed.id);
      }
    }

    // Log critical activities
    if (activity.severity === 'critical') {
      console.error(
        `[AdminActivityLog] CRITICAL: ${adminEmail} - ${action}: ${description}`,
        details
      );
    } else if (activity.status === 'failure') {
      console.warn(
        `[AdminActivityLog] FAILURE: ${adminEmail} - ${action}: ${description}`,
        details
      );
    } else {
      console.log(`[AdminActivityLog] ${adminEmail} - ${action}: ${description}`);
    }

    return activity;
  }

  /**
   * Get activity by ID
   */
  getActivity(activityId: string): AdminActivity | undefined {
    return this.activities.get(activityId);
  }

  /**
   * Get all activities
   */
  getAllActivities(): AdminActivity[] {
    return this.activityHistory;
  }

  /**
   * Get activities with filters
   */
  getActivities(filter: ActivityFilter): AdminActivity[] {
    let filtered = this.activityHistory;

    if (filter.adminId) {
      filtered = filtered.filter((a) => a.adminId === filter.adminId);
    }

    if (filter.action && filter.action.length > 0) {
      filtered = filtered.filter((a) => filter.action!.includes(a.action));
    }

    if (filter.status && filter.status.length > 0) {
      filtered = filtered.filter((a) => filter.status!.includes(a.status));
    }

    if (filter.severity && filter.severity.length > 0) {
      filtered = filtered.filter((a) => filter.severity!.includes(a.severity));
    }

    if (filter.startDate) {
      filtered = filtered.filter((a) => a.timestamp >= filter.startDate!);
    }

    if (filter.endDate) {
      filtered = filtered.filter((a) => a.timestamp <= filter.endDate!);
    }

    if (filter.ipAddress) {
      filtered = filtered.filter((a) => a.ipAddress === filter.ipAddress);
    }

    return filtered;
  }

  /**
   * Get recent activities
   */
  getRecentActivities(limit: number = 50): AdminActivity[] {
    return this.activityHistory.slice(-limit).reverse();
  }

  /**
   * Get activities by admin
   */
  getActivitiesByAdmin(adminId: number, limit: number = 50): AdminActivity[] {
    return this.activityHistory
      .filter((a) => a.adminId === adminId)
      .slice(-limit)
      .reverse();
  }

  /**
   * Get activities by action type
   */
  getActivitiesByAction(action: AdminActionType, limit: number = 50): AdminActivity[] {
    return this.activityHistory
      .filter((a) => a.action === action)
      .slice(-limit)
      .reverse();
  }

  /**
   * Get suspicious activities
   */
  getSuspiciousActivities(): AdminActivity[] {
    return this.activityHistory.filter(
      (a) => a.status === 'failure' || a.severity === 'critical' || a.severity === 'high'
    );
  }

  /**
   * Export activities as CSV
   */
  exportActivitiesAsCSV(filter: ActivityFilter): string {
    const activities = this.getActivities(filter);

    const headers = [
      'ID',
      'Admin ID',
      'Admin Email',
      'Action',
      'Description',
      'Status',
      'Severity',
      'Timestamp',
      'IP Address',
      'Affected Users',
      'Affected Resources',
    ];

    const rows = activities.map((a) => [
      a.id,
      a.adminId,
      a.adminEmail,
      a.action,
      a.description,
      a.status,
      a.severity,
      a.timestamp.toISOString(),
      a.ipAddress || 'N/A',
      a.affectedUsers?.join(',') || 'N/A',
      a.affectedResources?.join(',') || 'N/A',
    ]);

    const csv = [
      headers.join(','),
      ...rows.map((row) => row.map((cell) => `"${cell}"`).join(',')),
    ].join('\n');

    return csv;
  }

  /**
   * Export activities as JSON
   */
  exportActivitiesAsJSON(filter: ActivityFilter): string {
    const activities = this.getActivities(filter);
    return JSON.stringify(activities, null, 2);
  }

  /**
   * Get statistics
   */
  getStatistics(): {
    totalActivities: number;
    activitiesByAction: Record<AdminActionType, number>;
    activitiesByStatus: Record<string, number>;
    activitiesBySeverity: Record<string, number>;
    suspiciousActivities: number;
    uniqueAdmins: number;
  } {
    const activitiesByAction: Record<AdminActionType, number> = {
      withdrawal_approved: 0,
      withdrawal_rejected: 0,
      withdrawal_processed: 0,
      batch_approval: 0,
      batch_rejection: 0,
      report_generated: 0,
      report_exported: 0,
      settings_changed: 0,
      user_created: 0,
      user_deleted: 0,
      user_role_changed: 0,
      fraud_alert_acknowledged: 0,
      fraud_alert_dismissed: 0,
      login: 0,
      logout: 0,
      permission_denied: 0,
      data_accessed: 0,
      system_alert: 0,
    };

    const activitiesByStatus: Record<string, number> = {
      success: 0,
      failure: 0,
      warning: 0,
    };

    const activitiesBySeverity: Record<string, number> = {
      low: 0,
      medium: 0,
      high: 0,
      critical: 0,
    };

    const uniqueAdmins = new Set<number>();
    let suspiciousCount = 0;

    this.activityHistory.forEach((a) => {
      activitiesByAction[a.action]++;
      activitiesByStatus[a.status]++;
      activitiesBySeverity[a.severity]++;
      uniqueAdmins.add(a.adminId);

      if (a.status === 'failure' || a.severity === 'critical' || a.severity === 'high') {
        suspiciousCount++;
      }
    });

    return {
      totalActivities: this.activityHistory.length,
      activitiesByAction,
      activitiesByStatus,
      activitiesBySeverity,
      suspiciousActivities: suspiciousCount,
      uniqueAdmins: uniqueAdmins.size,
    };
  }

  /**
   * Clear old activities
   */
  clearOldActivities(olderThanDays: number = 90): number {
    const cutoffTime = new Date(Date.now() - olderThanDays * 24 * 60 * 60 * 1000);
    let count = 0;

    for (let i = 0; i < this.activityHistory.length; i++) {
      if (this.activityHistory[i].timestamp < cutoffTime) {
        const activity = this.activityHistory[i];
        this.activities.delete(activity.id);
        count++;
      }
    }

    // Remove old activities from history
    this.activityHistory = this.activityHistory.filter((a) => a.timestamp >= cutoffTime);

    return count;
  }
}

/**
 * Global admin activity logger instance
 */
let adminActivityLogger: AdminActivityLoggerService | null = null;

/**
 * Get or create admin activity logger
 */
export function getAdminActivityLogger(): AdminActivityLoggerService {
  if (!adminActivityLogger) {
    adminActivityLogger = new AdminActivityLoggerService();
  }
  return adminActivityLogger;
}

/**
 * Log withdrawal approval
 */
export function logWithdrawalApproval(
  adminId: number,
  adminEmail: string,
  withdrawalId: string,
  playerId: number,
  amount: number,
  currency: string,
  ipAddress?: string
): AdminActivity {
  const logger = getAdminActivityLogger();
  return logger.logActivity(
    adminId,
    adminEmail,
    'withdrawal_approved',
    `Approved withdrawal of ${amount} ${currency}`,
    {
      withdrawalId,
      playerId,
      amount,
      currency,
    },
    {
      ipAddress,
      status: 'success',
      severity: 'low',
      affectedUsers: [playerId],
      affectedResources: [withdrawalId],
    }
  );
}

/**
 * Log batch approval
 */
export function logBatchApproval(
  adminId: number,
  adminEmail: string,
  count: number,
  approved: number,
  failed: number,
  ipAddress?: string
): AdminActivity {
  const logger = getAdminActivityLogger();
  return logger.logActivity(
    adminId,
    adminEmail,
    'batch_approval',
    `Batch approved ${approved} withdrawals (${failed} failed)`,
    {
      total: count,
      approved,
      failed,
    },
    {
      ipAddress,
      status: failed > 0 ? 'warning' : 'success',
      severity: 'medium',
    }
  );
}

/**
 * Log permission denied
 */
export function logPermissionDenied(
  adminId: number,
  adminEmail: string,
  action: string,
  reason: string,
  ipAddress?: string
): AdminActivity {
  const logger = getAdminActivityLogger();
  return logger.logActivity(
    adminId,
    adminEmail,
    'permission_denied',
    `Permission denied for ${action}: ${reason}`,
    {
      action,
      reason,
    },
    {
      ipAddress,
      status: 'failure',
      severity: 'high',
    }
  );
}
