import { getSiteConfig } from "#site-config/server/composables/getSiteConfig";
import { createError, getRequestHost, H3Error, setHeader } from "h3";
import { logger } from "../../logger.js";
import { getBuildCachedImage, setBuildCachedImage } from "../og-image/cache/buildCache.js";
import { resolveContext } from "../og-image/context.js";
import { fetchPathHtmlAndExtractOptions } from "../og-image/devtools.js";
import { html } from "../og-image/templates/html.js";
import { useOgImageRuntimeConfig } from "../utils.js";
import { useOgImageBufferCache } from "./cache.js";
export async function imageEventHandler(e) {
  const ctx = await resolveContext(e).catch((err) => {
    logger.error(`resolveContext error for ${e.path}:`, err?.message || err);
    throw err;
  });
  if (ctx instanceof H3Error)
    return ctx;
  const { isDevToolsContextRequest, extension, renderer } = ctx;
  const { debug, baseCacheKey, security } = useOgImageRuntimeConfig();
  if (!import.meta.prerender && !import.meta.dev && security?.restrictRuntimeImagesToOrigin) {
    const siteHost = new URL(getSiteConfig(e).url).host;
    const allowedHosts = [siteHost, ...security.restrictRuntimeImagesToOrigin.map((o) => {
      try {
        return new URL(o).host;
      } catch {
        return o;
      }
    })];
    const requestHost = getRequestHost(e, { xForwardedHost: true });
    if (!requestHost || !allowedHosts.includes(requestHost)) {
      return createError({
        statusCode: 403,
        statusMessage: "[Nuxt OG Image] Host not allowed."
      });
    }
  }
  if ((import.meta.dev || debug) && isDevToolsContextRequest) {
    setHeader(e, "Content-Type", "application/json");
    const [extract, rendererDebug] = await Promise.all([
      fetchPathHtmlAndExtractOptions(e, ctx.basePath, ctx.key),
      renderer.debug ? renderer.debug(ctx).catch((err) => {
        logger.debug(`renderer.debug failed for ${ctx.options.component}: ${err?.message || err}`);
        return {};
      }) : {}
    ]);
    return {
      extract,
      siteUrl: getSiteConfig(e).url,
      ...rendererDebug
    };
  }
  switch (extension) {
    case "html":
      setHeader(e, "Content-Type", `text/html`);
      return html(ctx);
    case "svg": {
      if (!debug && !import.meta.dev) {
        return createError({
          statusCode: 404
        });
      }
      if (ctx.renderer.name !== "satori") {
        return createError({
          statusCode: 400,
          statusMessage: `[Nuxt OG Image] Generating ${extension}'s with ${renderer.name} is not supported.`
        });
      }
      setHeader(e, "Content-Type", `image/svg+xml`);
      const debugResult = await ctx.renderer.debug(ctx);
      return debugResult.svg;
    }
    case "png":
    case "jpeg":
    case "jpg":
      if (!renderer.supportedFormats.includes(extension)) {
        return createError({
          statusCode: 400,
          statusMessage: `[Nuxt OG Image] Generating ${extension}'s with ${renderer.name} is not supported.`
        });
      }
      setHeader(e, "Content-Type", `image/${extension === "jpg" ? "jpeg" : extension}`);
      break;
    default:
      return createError({
        statusCode: 400,
        statusMessage: `[Nuxt OG Image] Invalid request for og.${extension}.`
      });
  }
  const buildCachedImage = import.meta.prerender ? getBuildCachedImage(ctx.options, extension) : null;
  if (buildCachedImage) {
    return buildCachedImage;
  }
  const cacheApi = await useOgImageBufferCache(ctx, {
    cacheMaxAgeSeconds: ctx.options.cacheMaxAgeSeconds,
    baseCacheKey
  });
  if (typeof cacheApi === "undefined")
    return;
  if (cacheApi instanceof H3Error)
    return cacheApi;
  let image = cacheApi.cachedItem;
  if (!image) {
    const { security: security2 } = useOgImageRuntimeConfig();
    const timeout = security2?.renderTimeout || 15e3;
    let timer;
    image = await Promise.race([
      renderer.createImage(ctx),
      new Promise((_, reject) => {
        timer = setTimeout(() => reject(new Error(`OG image render timed out after ${timeout}ms`)), timeout);
      })
    ]).catch((err) => {
      if (err?.message?.includes("timed out")) {
        logger.error(`renderer.createImage timeout for ${e.path}`);
        return createError({ statusCode: 408, statusMessage: `[Nuxt OG Image] Request timed out while waiting for OG image render.` });
      }
      logger.error(`renderer.createImage error for ${e.path}:`, err?.stack || err?.message || err);
      throw err;
    }).finally(() => {
      clearTimeout(timer);
    });
    if (image instanceof H3Error)
      return image;
    if (!image) {
      return createError({
        statusCode: 500,
        statusMessage: `Failed to generate og.${extension}.`
      });
    }
    await cacheApi.update(image);
    if (import.meta.prerender && ctx.options.cacheMaxAgeSeconds) {
      setBuildCachedImage(ctx.options, extension, image, ctx.options.cacheMaxAgeSeconds);
    }
  }
  return image;
}
