import { Injectable, type LoggerService as NestLoggerService } from '@nestjs/common';
import pinoLogger, { type Logger, stdTimeFunctions } from 'pino';
import { maskPii } from './pii-masker';

@Injectable()
export class LoggerService implements NestLoggerService {
  private readonly logger: Logger;

  constructor() {
    this.logger = pinoLogger({
      level: process.env['LOG_LEVEL'] ?? 'info',
      transport:
        process.env['NODE_ENV'] !== 'production'
          ? { target: 'pino-pretty', options: { colorize: true } }
          : undefined,
      redact: {
        paths: [
          'password', 'passwordHash', 'token', 'accessToken', 'refreshToken',
          'secret', 'authorization', 'cookie', 'creditCard', 'cardNumber',
          'cvv', 'ssn', 'cmnd', 'cccd', 'email', 'phone', 'kycData',
          'idNumber', 'identityNumber', 'dateOfBirth', 'dob', 'address',
          'bankAccount', 'accountNumber', 'apiKey', 'privateKey', 'encryptionKey',
          'req.headers.authorization', 'req.headers.cookie',
          'user.email', 'user.phone', 'user.kycData',
          'body.password', 'body.token', 'body.email', 'body.phone',
        ],
        censor: '[REDACTED]',
      },
      formatters: {
        level(label) {
          return { level: label };
        },
        log(object) {
          return maskPii(object) as Record<string, unknown>;
        },
      },
      base: { service: 'goodgo-api' },
      timestamp: stdTimeFunctions.isoTime,
    });
  }

  log(message: string, context?: string): void {
    this.logger.info({ context }, message);
  }

  error(message: string, trace?: string, context?: string): void {
    this.logger.error({ context, trace }, message);
  }

  warn(message: string, context?: string): void {
    this.logger.warn({ context }, message);
  }

  debug(message: string, context?: string): void {
    this.logger.debug({ context }, message);
  }

  verbose(message: string, context?: string): void {
    this.logger.trace({ context }, message);
  }

  child(bindings: Record<string, unknown>): Logger {
    return this.logger.child(bindings);
  }
}
