import { eventHandler, createError, isError, getRequestHeader, readRawBody, createApp, toNodeListener, setResponseHeader } from 'h3';
import { n as normalizeBaseKey, a as normalizeKey, d as stringify } from './shared/unstorage.zVDD2mZo.mjs';

const MethodToTypeMap = {
  GET: "read",
  HEAD: "read",
  PUT: "write",
  DELETE: "write"
};
function createH3StorageHandler(storage, opts = {}) {
  return eventHandler(async (event) => {
    const _path = opts.resolvePath?.(event) ?? event.path;
    const lastChar = _path[_path.length - 1];
    const isBaseKey = lastChar === ":" || lastChar === "/";
    const key = isBaseKey ? normalizeBaseKey(_path) : normalizeKey(_path);
    if (!(event.method in MethodToTypeMap)) {
      throw createError({
        statusCode: 405,
        statusMessage: `Method Not Allowed: ${event.method}`
      });
    }
    try {
      await opts.authorize?.({
        type: MethodToTypeMap[event.method],
        event,
        key
      });
    } catch (error) {
      const _httpError = isError(error) ? error : createError({
        statusMessage: error?.message,
        statusCode: 401,
        ...error
      });
      throw _httpError;
    }
    if (event.method === "GET") {
      if (isBaseKey) {
        const keys = await storage.getKeys(key);
        return keys.map((key2) => key2.replace(/:/g, "/"));
      }
      const isRaw = getRequestHeader(event, "accept") === "application/octet-stream";
      const driverValue = await (isRaw ? storage.getItemRaw(key) : storage.getItem(key));
      if (driverValue === null) {
        throw createError({
          statusCode: 404,
          statusMessage: "KV value not found"
        });
      }
      setMetaHeaders(event, await storage.getMeta(key));
      return isRaw ? driverValue : stringify(driverValue);
    }
    if (event.method === "HEAD") {
      if (!await storage.hasItem(key)) {
        throw createError({
          statusCode: 404,
          statusMessage: "KV value not found"
        });
      }
      setMetaHeaders(event, await storage.getMeta(key));
      return "";
    }
    if (event.method === "PUT") {
      const isRaw = getRequestHeader(event, "content-type") === "application/octet-stream";
      const topts = {
        ttl: Number(getRequestHeader(event, "x-ttl")) || void 0
      };
      if (isRaw) {
        const value = await readRawBody(event, false);
        await storage.setItemRaw(key, value, topts);
      } else {
        const value = await readRawBody(event, "utf8");
        if (value !== void 0) {
          await storage.setItem(key, value, topts);
        }
      }
      return "OK";
    }
    if (event.method === "DELETE") {
      await (isBaseKey ? storage.clear(key) : storage.removeItem(key));
      return "OK";
    }
    throw createError({
      statusCode: 405,
      statusMessage: `Method Not Allowed: ${event.method}`
    });
  });
}
function setMetaHeaders(event, meta) {
  if (meta.mtime) {
    setResponseHeader(
      event,
      "last-modified",
      new Date(meta.mtime).toUTCString()
    );
  }
  if (meta.ttl) {
    setResponseHeader(event, "x-ttl", `${meta.ttl}`);
    setResponseHeader(event, "cache-control", `max-age=${meta.ttl}`);
  }
}
function createStorageServer(storage, options = {}) {
  const app = createApp({ debug: true });
  const handler = createH3StorageHandler(storage, options);
  app.use(handler);
  return {
    handle: toNodeListener(app)
  };
}

export { createH3StorageHandler, createStorageServer };
