import { Logger } from '@nestjs/common';

type LogMetadata = Record<string, unknown>;

const SENSITIVE_KEY = /password|token|cookie|authorization|secret|htmlcontent|textcontent/i;

/**
 * Emits consistent, searchable service events while redacting credentials and
 * message content before anything reaches application logs.
 */
export class ServiceLogger {
  private readonly logger: Logger;

  constructor(context: string) {
    this.logger = new Logger(context);
  }

  log(event: string, metadata: LogMetadata = {}) {
    this.logger.log(this.serialize(event, 'success', metadata));
  }

  warn(event: string, metadata: LogMetadata = {}) {
    this.logger.warn(this.serialize(event, 'warning', metadata));
  }

  error(event: string, error: unknown, metadata: LogMetadata = {}) {
    const errorDetails = this.toErrorDetails(error);
    this.logger.error(
      this.serialize(event, 'error', { ...metadata, ...errorDetails }),
      errorDetails.stack,
    );
  }

  private serialize(event: string, outcome: string, metadata: LogMetadata) {
    return JSON.stringify(
      { event, outcome, ...metadata },
      (key, value) => (SENSITIVE_KEY.test(key) ? '[REDACTED]' : value),
    );
  }

  private toErrorDetails(error: unknown) {
    if (error instanceof Error) {
      return {
        errorName: error.name,
        errorMessage: error.message,
        stack: error.stack,
        errorCode:
          typeof error === 'object' && error !== null && 'code' in error
            ? String((error as { code?: unknown }).code)
            : undefined,
      };
    }

    return { errorName: 'UnknownError', errorMessage: String(error) };
  }
}
