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: unknown[]) {
    if (args.length > 0 && typeof args[0] === "object" && args[0] !== null) {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (this.logger as any).trace(args[0] as object, msg, ...args.slice(1));
    } else {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (this.logger as any).trace(msg, ...args);
    }
  }

  debug(msg: string, ...args: unknown[]) {
    if (args.length > 0 && typeof args[0] === "object" && args[0] !== null) {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (this.logger as any).debug(args[0] as object, msg, ...args.slice(1));
    } else {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (this.logger as any).debug(msg, ...args);
    }
  }

  info(msg: string, ...args: unknown[]) {
    if (args.length > 0 && typeof args[0] === "object" && args[0] !== null) {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (this.logger as any).info(args[0] as object, msg, ...args.slice(1));
    } else {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (this.logger as any).info(msg, ...args);
    }
  }

  warn(msg: string, ...args: unknown[]) {
    if (args.length > 0 && typeof args[0] === "object" && args[0] !== null) {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (this.logger as any).warn(args[0] as object, msg, ...args.slice(1));
    } else {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (this.logger as any).warn(msg, ...args);
    }
  }

  error(msg: string, ...args: unknown[]) {
    if (args.length > 0 && typeof args[0] === "object" && args[0] !== null) {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (this.logger as any).error(args[0] as object, msg, ...args.slice(1));
    } else {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (this.logger as any).error(msg, ...args);
    }
  }

  fatal(msg: string, ...args: unknown[]) {
    if (args.length > 0 && typeof args[0] === "object" && args[0] !== null) {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (this.logger as any).fatal(args[0] as object, msg, ...args.slice(1));
    } else {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (this.logger as any).fatal(msg, ...args);
    }
  }

  child(bindings: Record<string, unknown>): LoggerService {
    const childPino = this.logger.child(bindings);
    const service = new PinoLoggerService();
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    (service as any).logger = childPino;
    return service;
  }
}
