type LogLevel = "error" | "warn" | "info" | "http" | "debug";

export interface LogEntry {
  level: LogLevel;
  timestamp: string;
  message: any;
  metadata?: any;
}

interface Error {
  code: string;
  message: string;
  userHint?: string;
  detail?: string;
  error?: any;
  actionable?: boolean;
}

class BrowserLogger {
  private async sendLog(entry: LogEntry) {
    try {
      // Only send logs to server in production
      if (process.env.NODE_ENV === "production") {
        await fetch("/api/logs", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(entry),
        });
      }

      // Always log to console in development
      const consoleMethod = entry.level === "debug" ? "log" : entry.level;
      // @ts-ignore
      console[consoleMethod as keyof Console](
        `[${entry.level}] ${entry.timestamp}: `,
        entry.message,
        entry.metadata || "",
      );
    } catch (err) {
      console.error("Failed to send log to server:", err);
      // @ts-ignore
      console[entry.level as keyof Console](entry.message);
    }
  }

  private createLogEntry(
    level: LogLevel,
    message: any,
    metadata?: any,
  ): LogEntry {
    return {
      level,
      timestamp: new Date().toISOString(),
      message,
      metadata,
    };
  }

  error(message: any, metadata?: any) {
    this.sendLog(this.createLogEntry("error", message, metadata));
  }

  warn(message: any, metadata?: any) {
    this.sendLog(this.createLogEntry("warn", message, metadata));
  }

  info(message: any, metadata?: any) {
    this.sendLog(this.createLogEntry("info", message, metadata));
  }

  http(message: any, metadata?: any) {
    this.sendLog(this.createLogEntry("http", message, metadata));
  }

  debug(message: any, metadata?: any) {
    this.sendLog(this.createLogEntry("debug", message, metadata));
  }
}

const ClientLogger = new BrowserLogger();

function getError(payload: Error, error?: any) {
  ClientLogger.error(payload);
  if (error) {
    ClientLogger.error(error);
  }
  return {
    code: payload.code,
    message: payload.message,
    userHint: payload.userHint,
    detail: payload.detail,
    error: error,
    actionable: payload.actionable,
  } as Error;
}

export { ClientLogger, getError };
