// src/lib/log.ts
// Copyright (C) 2026 Rob Colbert <rob.colbert@openplatform.us>
// Licensed under the Apache License, Version 2.0

import { GadgetComponent } from "./component.ts";
import { GadgetLogTransportConsole } from "./log-transport-console.ts";
import { GadgetLogTransportFile } from "./log-transport-file.ts";
import { GadgetLogTransport } from "./log-transport.ts";
import { GadgetLogFile } from "./log-file.ts";

export enum GadgetLogLevel {
  debug = "debug",
  info = "info",
  warn = "warn",
  alert = "alert",
  error = "error",
  crit = "crit",
  fatal = "fatal",
}

export class GadgetLog {
  component: GadgetComponent;
  transports: GadgetLogTransport[] = [];

  private static defaultTransports: GadgetLogTransport[] = [];

  static consoleEnabled = true;
  static defaultFile: GadgetLogFile | undefined;

  constructor(component: GadgetComponent, file?: GadgetLogFile) {
    this.component = component;
    this.transports.push(...GadgetLog.defaultTransports);

    if (GadgetLog.consoleEnabled) {
      this.transports.push(new GadgetLogTransportConsole());
    }

    const fileInstance = file || GadgetLog.defaultFile;
    if (fileInstance) {
      this.transports.push(new GadgetLogTransportFile(fileInstance));
    }
  }

  public static addDefaultTransport(transport: GadgetLogTransport): void {
    GadgetLog.defaultTransports.push(transport);
  }

  public static removeDefaultTransport(transport: GadgetLogTransport): void {
    const index = GadgetLog.defaultTransports.indexOf(transport);
    if (index > -1) {
      GadgetLog.defaultTransports.splice(index, 1);
    }
  }

  public static getDefaultTransports(): GadgetLogTransport[] {
    return GadgetLog.defaultTransports;
  }

  async debug(message: string, metadata?: unknown) {
    if (!GadgetLog.consoleEnabled) {
      return;
    }
    return this.writeLog(GadgetLogLevel.debug, message, metadata);
  }

  async info(message: string, metadata?: unknown) {
    return this.writeLog(GadgetLogLevel.info, message, metadata);
  }

  async warn(message: string, metadata?: unknown) {
    return this.writeLog(GadgetLogLevel.warn, message, metadata);
  }

  async alert(message: string, metadata?: unknown) {
    return this.writeLog(GadgetLogLevel.alert, message, metadata);
  }

  async error(message: string, metadata?: unknown) {
    return this.writeLog(GadgetLogLevel.error, message, metadata);
  }

  async crit(message: string, metadata?: unknown) {
    return this.writeLog(GadgetLogLevel.crit, message, metadata);
  }

  async fatal(message: string, metadata?: unknown) {
    this.writeLog(GadgetLogLevel.fatal, message, metadata);
  }

  async writeLog(level: GadgetLogLevel, message: string, metadata?: unknown) {
    const NOW = new Date();
    for (const transport of this.transports) {
      transport.writeLog(NOW, this.component, level, message, metadata);
    }
  }
}
