import { readFile } from "node:fs/promises";
import { join } from "node:path";
import { ImageResponse } from "next/og";
import type { Locale } from "next-intl";
import { getTranslations } from "next-intl/server";
import enMessages from "../../../messages/en.json";
import { OG_IMAGE } from "@/config/seo";
import { site } from "@/config/site";
import { routing } from "@/i18n/routing";

export const dynamic = "force-static";

// Enumerating the locales is what keeps the two cards prerendered at build time
// (`● /[locale]/opengraph-image`) rather than rendered on the first request.
export function generateStaticParams() {
  return routing.locales.map((locale) => ({ locale }));
}

/**
 * A module-level constant is shared by every `[locale]`, so `alt` cannot be
 * localised here. It stays as the English fallback for any segment that lets
 * Next inject this file on its own; the `og:image:alt` actually emitted comes
 * from `ogImagesFor` (`src/config/seo/meta.ts`), which declares this same card
 * per locale.
 *
 * Localising it through `generateImageMetadata` was tried and reverted: the
 * metadata route loader then emits its own `generateStaticParams` and re-exports
 * every other named export, so ours would be a duplicate — `[locale]` is never
 * enumerated, the route stops being prerendered, and the public URL gains an
 * `/[__metadata_id__]` segment.
 */
export const alt = enMessages.OpenGraph.imageAlt;
export const size = OG_IMAGE.size;
export const contentType = OG_IMAGE.contentType;

// Satori (the renderer behind `ImageResponse`) only decodes PNG/APNG/JPEG/GIF/SVG
// — WebP and AVIF throw `Unsupported image type`. So the hero shot cannot be read
// from `public/home/*.webp`; `og-product.jpg` is its JPEG derivative, cropped and
// resized to the exact panel box (560×630) so the renderer never has to resample
// it. It is co-located here rather than in `public/` because it is a build-time
// input to this route, not a public asset.
const PRODUCT_IMAGE = join(process.cwd(), "src", "app", "[locale]", "og-product.jpg");

const PANEL_WIDTH = 560;

// Design tokens, inlined: `ImageResponse` renders outside the document, so it
// has no access to the CSS custom properties declared in `globals.css`.
const CHARCOAL = site.themeColor; // --foreground
const OFF_WHITE = "#f9f9f7"; // --background
const GOLD = "#a6863f"; // --color-gold

export default async function Image({ params }: { params: Promise<{ locale: Locale }> }) {
  const { locale } = await params;
  const t = await getTranslations({ locale, namespace: "IndexPage.seo" });
  const product = await readFile(PRODUCT_IMAGE);

  return new ImageResponse(
    <div
      style={{
        width: "100%",
        height: "100%",
        display: "flex",
        background: CHARCOAL,
        color: OFF_WHITE,
      }}
    >
      <div
        style={{
          display: "flex",
          flexDirection: "column",
          justifyContent: "center",
          width: size.width - PANEL_WIDTH,
          height: "100%",
          padding: "0 56px",
        }}
      >
        <div
          style={{
            display: "flex",
            fontSize: 32,
            fontWeight: 600,
            letterSpacing: "0.32em",
            textTransform: "uppercase",
          }}
        >
          {site.wordmark}
        </div>
        <div
          style={{
            display: "flex",
            marginTop: 12,
            fontSize: 14,
            fontWeight: 500,
            letterSpacing: "0.26em",
            textTransform: "uppercase",
            color: GOLD,
          }}
        >
          {site.name}
        </div>
        <div
          style={{ display: "flex", width: 64, height: 2, background: GOLD, margin: "34px 0" }}
        />
        <div
          style={{
            display: "flex",
            fontSize: 52,
            lineHeight: 1.12,
            letterSpacing: "-0.01em",
            color: "#ffffff",
          }}
        >
          {t("title")}
        </div>
      </div>
      {/* eslint-disable-next-line @next/next/no-img-element -- satori renders a raw
          <img>; `next/image` is a DOM component and has no meaning in an OG image. */}
      <img
        alt=""
        src={`data:image/jpeg;base64,${product.toString("base64")}`}
        width={PANEL_WIDTH}
        height={size.height}
        style={{ width: PANEL_WIDTH, height: size.height, objectFit: "cover" }}
      />
    </div>,
    { ...size },
  );
}
