/**
 * ابزار مشترک تصاویر Open Graph (۱۲۰۰×۶۳۰ PNG).
 * موتور رندر next/og حروف فارسی را به هم نمی‌چسباند؛ برای همین در تصویر فقط لوگو،
 * تصویر برداری محصول و متن لاتین استفاده می‌شود و متن فارسی در تگ‌های متا می‌ماند.
 */
import { readFile } from "node:fs/promises";
import path from "node:path";
import sharp from "sharp";
import { imageSrc } from "@/lib/media";
import { site } from "@/lib/site";
import { Children, cloneElement, Fragment, isValidElement, type ReactNode } from "react";

export const OG_SIZE = { width: 1200, height: 630 };

let wordmark: Promise<string> | undefined;

/** لوگوی متنی زهورا به‌صورت data URI (یک بار خوانده و نگه داشته می‌شود) */
export function wordmarkDataUri() {
  wordmark ??= readFile(path.join(process.cwd(), "public/brand/logo-wordmark.png")).then((b) => `data:image/png;base64,${b.toString("base64")}`);
  return wordmark;
}

export const OG_HEADERS = { "Cache-Control": "public, max-age=86400, stale-while-revalidate=604800" };

/**
 * next/og داخل <svg> فقط تگ‌های خام SVG را می‌پذیرد؛ این تابع کامپوننت‌های ساده
 * (بدون hook، مثل ProductArt و زیرکامپوننت‌هایش) را صدا می‌زند تا درخت فقط تگ خام داشته باشد.
 * تگ <text> هم پشتیبانی نمی‌شود و حذف می‌شود (برچسب کوچک روی ظرف).
 */
export function flatten(node: ReactNode): ReactNode {
  if (Array.isArray(node)) return node.map(flatten);
  if (!isValidElement(node)) return node;
  if (node.type === "text") return null;
  const props = node.props as { children?: ReactNode };
  if (typeof node.type === "function") return flatten((node.type as (p: unknown) => ReactNode)(props));
  if ((node.type as unknown) === Fragment) return flatten(props.children);
  return cloneElement(node, undefined, ...Children.toArray(props.children).map(flatten));
}

/**
 * عکس واقعی محصول برای تصویر اشتراک‌گذاری. موتور رندر WebP نمی‌خواند،
 * پس نسخه ۸۰۰ پیکسلی دریافت و به JPEG تبدیل می‌شود. در صورت خطا undefined (و طرح برداری).
 */
export async function photoDataUri(baseUrl: string): Promise<string | undefined> {
  try {
    const res = await fetch(new URL(imageSrc(baseUrl, 800), site.url), { signal: AbortSignal.timeout(5000) });
    if (!res.ok) return undefined;
    const jpeg = await sharp(Buffer.from(await res.arrayBuffer())).resize(630, 630).jpeg({ quality: 85 }).toBuffer();
    return `data:image/jpeg;base64,${jpeg.toString("base64")}`;
  } catch {
    return undefined;
  }
}
