import { isAxiosError, isCancel } from "axios";
import { z } from "zod";
import { defaultT } from "../config/i18n.mjs";
import { RestUtils } from "./rest.utils.mjs";
class ApplicationException extends Error {
  code;
  serverMessage = null;
  constructor(message, code, serverMessage) {
    super(message);
    this.code = code;
    this.serverMessage = serverMessage;
  }
}
class ErrorHandler {
  entries = [];
  t;
  onRethrowError;
  constructor({ entries, t = defaultT, onRethrowError }) {
    this.t = t;
    this.onRethrowError = onRethrowError;
    const dataValidationError = {
      code: "DATA_VALIDATION_ERROR",
      condition: (e) => {
        return e instanceof z.ZodError;
      },
      getMessage: () => this.t("openapi.sharedErrors.dataValidation")
    };
    const internalError = {
      code: "INTERNAL_ERROR",
      condition: (e) => {
        if (isAxiosError(e)) {
          return e.response?.status != null && e.response.status >= 500 && e.response.status < 600;
        }
        return false;
      },
      getMessage: () => this.t("openapi.sharedErrors.internalError")
    };
    const networkError = {
      code: "NETWORK_ERROR",
      condition: (e) => {
        if (isAxiosError(e)) {
          return e.code === "ERR_NETWORK";
        }
        return false;
      },
      getMessage: () => this.t("openapi.sharedErrors.networkError")
    };
    const canceledError = {
      code: "CANCELED_ERROR",
      condition: (e) => {
        if (isCancel(e)) {
          return true;
        }
        if (isAxiosError(e) && e.code === "ECONNABORTED") {
          return true;
        }
        return false;
      },
      getMessage: () => this.t("openapi.sharedErrors.canceledError")
    };
    const unknownError = {
      code: "UNKNOWN_ERROR",
      condition: () => true,
      getMessage: (_, e) => {
        const code = RestUtils.extractServerResponseCode(e);
        const serverMessage = RestUtils.extractServerErrorMessage(e);
        if (code) {
          let message = `Unknown error, message from server: ${code}`;
          if (serverMessage) {
            message += ` ${serverMessage}`;
          }
          return message;
        }
        return this.t("openapi.sharedErrors.unknownError");
      }
    };
    this.entries = [...entries, dataValidationError, internalError, networkError, canceledError, unknownError];
  }
  matchesEntry(error, entry, code) {
    if (entry.condition) {
      return entry.condition(error);
    }
    return code === entry.code;
  }
  setTranslateFunction(t) {
    this.t = t;
  }
  rethrowError(error) {
    const code = RestUtils.extractServerResponseCode(error);
    const errorEntry = this.entries.find((entry) => this.matchesEntry(error, entry, code));
    const serverMessage = RestUtils.extractServerErrorMessage(error);
    const exception = new ApplicationException(errorEntry.getMessage(this.t, error), errorEntry.code, serverMessage);
    this.onRethrowError?.(error, exception);
    throw exception;
  }
  getError(error) {
    if (error instanceof ApplicationException) {
      return error;
    }
    return null;
  }
  getErrorCode(error) {
    if (error instanceof ApplicationException) {
      return error.code;
    }
    return null;
  }
  static getErrorMessage(error, fallbackToUnknown = true) {
    if (typeof error === "string") {
      return error;
    }
    if (error instanceof Error) {
      return error.message;
    }
    if (error instanceof ApplicationException) {
      return error.message;
    }
    if (fallbackToUnknown) {
      return defaultT("openapi.sharedErrors.unknownError");
    }
    return null;
  }
}
const SharedErrorHandler = new ErrorHandler({ entries: [] });
export {
  ApplicationException,
  ErrorHandler,
  SharedErrorHandler
};
