import pino, { Logger as PinoLogger } from 'pino';
import type { LoggerService } from './logger-service';
import { config } from '../../config';

export class PinoLoggerService implements LoggerService {
  private readonly logger: PinoLogger;

  constructor(name?: string, parent?: PinoLogger) {
    if (parent) {
      this.logger = parent.child({ name });
    } else {
      // In Next.js, especially in the Edge runtime or during instrumentation,
      // pino transports (which use worker threads) can cause issues.
      // We disable transport in production and during instrumentation.
      const useTransport = config.isDevelopment && typeof window === 'undefined';

      this.logger = pino({
        name: name || 'app',
        level: config.logging.level,
        transport: useTransport
          ? {
              target: 'pino-pretty',
              options: {
                colorize: true,
              },
            }
          : undefined,
      });
    }
  }

  trace(msg: string, ...args: any[]) {
    // @ts-expect-error - pino types can be strict
    this.logger.trace(msg, ...args);
  }

  debug(msg: string, ...args: any[]) {
    // @ts-expect-error - pino types can be strict
    this.logger.debug(msg, ...args);
  }

  info(msg: string, ...args: any[]) {
    // @ts-expect-error - pino types can be strict
    this.logger.info(msg, ...args);
  }

  warn(msg: string, ...args: any[]) {
    // @ts-expect-error - pino types can be strict
    this.logger.warn(msg, ...args);
  }

  error(msg: string, ...args: any[]) {
    // @ts-expect-error - pino types can be strict
    this.logger.error(msg, ...args);
  }

  fatal(msg: string, ...args: any[]) {
    // @ts-expect-error - pino types can be strict
    this.logger.fatal(msg, ...args);
  }

  child(bindings: Record<string, any>): LoggerService {
    const childPino = this.logger.child(bindings);
    // Bypass the constructor to avoid creating an orphaned, leaking pino instance
    const service = Object.create(PinoLoggerService.prototype);
    service.logger = childPino;
    return service;
  }
}
