import { Option } from "effect";
import { evaluationError } from "./errors.js";
import { Decimal } from "./decimal.js";
class JSONNamespace {
  brand = "JSON";
}
const JSON_INSTANCE = new JSONNamespace();
function normalizeForJSON(value) {
  if (value === null || value === void 0) return value;
  if (value instanceof Decimal) return value.toNumber();
  if (Option.isOption(value)) {
    return Option.isSome(value) ? normalizeForJSON(value.value) : null;
  }
  if (value instanceof Date) return value;
  if (value instanceof Map) {
    const out = {};
    for (const [k, v] of value) out[String(k)] = normalizeForJSON(v);
    return out;
  }
  if (Array.isArray(value)) return value.map(normalizeForJSON);
  if (typeof value === "object") {
    const proto = Object.getPrototypeOf(value);
    if (proto !== Object.prototype && proto !== null) return value;
    const out = {};
    for (const key of Object.keys(value)) {
      out[key] = normalizeForJSON(value[key]);
    }
    return out;
  }
  return value;
}
export function registerJSONBuiltins(registry) {
  registry.registerType("JSON", JSONNamespace);
  registry.registerVariable({
    name: "JSON",
    type: "JSON",
    value: JSON_INSTANCE,
    description: "JSON \u7F16\u89E3\u7801"
  });
  registry.registerFunctionOverload("JSON.parse(string): dyn", (_r, s) => {
    try {
      return globalThis.JSON.parse(s);
    } catch (e) {
      throw evaluationError("invalid_json", `JSON.parse(): ${e.message}`);
    }
  });
  registry.registerFunctionOverload(
    "JSON.stringify(dyn): string",
    (_r, v) => globalThis.JSON.stringify(normalizeForJSON(v))
  );
}
