/**
 * @ai-summary Centralized audit logging service
 * @ai-context Provides simple API for all features to log audit events
 */

import { AuditLogRepository } from '../data/audit-log.repository';
import {
  AuditLogCategory,
  AuditLogSeverity,
  AuditLogEntry,
  AuditLogFilters,
  AuditLogPagination,
  AuditLogSearchResult,
  isValidCategory,
  isValidSeverity,
} from './audit-log.types';
import { logger } from '../../../core/logging/logger';

export class AuditLogService {
  constructor(private repository: AuditLogRepository) {}

  /**
   * Log an audit event
   *
   * @param category - Event category (auth, vehicle, user, system, admin)
   * @param severity - Event severity (info, warning, error)
   * @param userId - User who performed the action (null for system actions)
   * @param action - Human-readable description of the action
   * @param resourceType - Type of resource affected (optional)
   * @param resourceId - ID of affected resource (optional)
   * @param details - Additional structured data (optional)
   */
  async log(
    category: AuditLogCategory,
    severity: AuditLogSeverity,
    userId: string | null,
    action: string,
    resourceType?: string | null,
    resourceId?: string | null,
    details?: Record<string, unknown> | null
  ): Promise<AuditLogEntry> {
    // Validate category
    if (!isValidCategory(category)) {
      const error = new Error(`Invalid audit log category: ${category}`);
      logger.error('Invalid audit log category', { category });
      throw error;
    }

    // Validate severity
    if (!isValidSeverity(severity)) {
      const error = new Error(`Invalid audit log severity: ${severity}`);
      logger.error('Invalid audit log severity', { severity });
      throw error;
    }

    try {
      const entry = await this.repository.create({
        category,
        severity,
        userId,
        action,
        resourceType,
        resourceId,
        details,
      });

      logger.debug('Audit log created', {
        id: entry.id,
        category,
        severity,
        action,
      });

      return entry;
    } catch (error) {
      logger.error('Error creating audit log', { error, category, action });
      throw error;
    }
  }

  /**
   * Convenience method for info-level logs
   */
  async info(
    category: AuditLogCategory,
    userId: string | null,
    action: string,
    resourceType?: string | null,
    resourceId?: string | null,
    details?: Record<string, unknown> | null
  ): Promise<AuditLogEntry> {
    return this.log(category, 'info', userId, action, resourceType, resourceId, details);
  }

  /**
   * Convenience method for warning-level logs
   */
  async warning(
    category: AuditLogCategory,
    userId: string | null,
    action: string,
    resourceType?: string | null,
    resourceId?: string | null,
    details?: Record<string, unknown> | null
  ): Promise<AuditLogEntry> {
    return this.log(category, 'warning', userId, action, resourceType, resourceId, details);
  }

  /**
   * Convenience method for error-level logs
   */
  async error(
    category: AuditLogCategory,
    userId: string | null,
    action: string,
    resourceType?: string | null,
    resourceId?: string | null,
    details?: Record<string, unknown> | null
  ): Promise<AuditLogEntry> {
    return this.log(category, 'error', userId, action, resourceType, resourceId, details);
  }

  /**
   * Search audit logs with filters and pagination
   */
  async search(
    filters: AuditLogFilters,
    pagination: AuditLogPagination
  ): Promise<AuditLogSearchResult> {
    try {
      return await this.repository.search(filters, pagination);
    } catch (error) {
      logger.error('Error searching audit logs', { error, filters });
      throw error;
    }
  }

  /**
   * Get logs for CSV export (limited to 5000 records)
   */
  async getForExport(filters: AuditLogFilters): Promise<{ logs: AuditLogEntry[]; truncated: boolean }> {
    try {
      return await this.repository.getForExport(filters);
    } catch (error) {
      logger.error('Error getting audit logs for export', { error, filters });
      throw error;
    }
  }

  /**
   * Run retention cleanup (delete logs older than specified days)
   */
  async cleanup(olderThanDays: number = 90): Promise<number> {
    try {
      const deletedCount = await this.repository.cleanup(olderThanDays);
      logger.info('Audit log cleanup completed', { olderThanDays, deletedCount });
      return deletedCount;
    } catch (error) {
      logger.error('Error running audit log cleanup', { error, olderThanDays });
      throw error;
    }
  }
}
