---
/**
 * EmDash Image component
 *
 * Renders images with responsive srcset for CDN providers that support it.
 * Uses the provider's getSrc function for URL-based image transformations.
 *
 * Usage:
 * ```astro
 * ---
 * import { Image } from "emdash/ui";
 * ---
 * <Image image={post.data.featured_image} />
 *
 * <!-- With overrides -->
 * <Image image={post.data.featured_image} class="hero" />
 * ```
 */
import type { MediaValue } from "../fields/types.js";
import type { HTMLAttributes } from "astro/types";
import type { ImageEmbed } from "../media/types.js";
import { getMediaProvider } from "../media/provider-loader.js";
import { buildRenderMediaUrl } from "../media/url.js";
// Standard responsive breakpoints
const BREAKPOINTS = [640, 750, 828, 960, 1080, 1280, 1600, 1920];

interface Props extends Omit<
	HTMLAttributes<"img">,
	"src" | "width" | "height"
> {
	/** Image value from content field or media library */
	image: MediaValue | string | undefined | null;
	/** Override alt text (uses image.alt by default) */
	alt?: string;
	/** Override width (uses image.width by default) */
	width?: number;
	/** Override height (uses image.height by default) */
	height?: number;
	/** Priority loading (disables lazy loading) */
	priority?: boolean;
}

const { image, alt, width, height, priority, ...attrs } = Astro.props;

// Normalize string URLs to object form
function normalizeImage(
	img: MediaValue | string | undefined | null
): MediaValue | null {
	if (!img) return null;
	if (typeof img === "string") {
		return { id: "", src: img };
	}
	return img;
}

/**
 * Build the URL for a local image. Prefers `meta.storageKey`; falls back to
 * the internal proxy with `img.id` when no storage key is available.
 */
function buildLocalImageUrl(img: MediaValue): string {
	return buildRenderMediaUrl(Astro.locals.emdash?.getPublicMediaUrl, {
		storageKey: img.meta?.storageKey as string | undefined,
		id: img.id,
	});
}

/**
 * Generate srcset using provider's getSrc function
 */
function generateSrcset(
	getSrc: NonNullable<ImageEmbed["getSrc"]>,
	maxWidth: number,
	aspectRatio?: number
): string {
	return BREAKPOINTS.filter((w) => w <= maxWidth * 2) // Include up to 2x for retina
		.map((w) => {
			const h = aspectRatio ? Math.round(w / aspectRatio) : undefined;
			return `${getSrc({ width: w, height: h })} ${w}w`;
		})
		.join(", ");
}

const img = normalizeImage(image);

// Determine final dimensions (props override image metadata)
const finalWidth = width ?? img?.width;
const finalHeight = height ?? img?.height;
const finalAlt = alt ?? img?.alt ?? "";
const aspectRatio =
	finalWidth && finalHeight ? finalWidth / finalHeight : undefined;

// Get the image source URL and srcset
let src = "";
let srcset: string | undefined;
let sizes: string | undefined;

if (img) {
	const providerId = img.provider ?? "local";

	if (providerId === "local" || img.src) {
		// Local provider or direct src URL
		src = img.src || buildLocalImageUrl(img);
	} else {
		// External provider
		try {
			const provider = await getMediaProvider(providerId);
			if (provider) {
				const result = provider.getEmbed(img, {
					width: finalWidth,
					height: finalHeight,
				});
				const embed = result instanceof Promise ? await result : result;
				if (embed.type === "image") {
					src = embed.src;

					// Generate srcset if provider supports dynamic sizing
					if (embed.getSrc) {
						// Use image width, or default to 1200 for responsive images
						const maxWidth = finalWidth || 1200;
						srcset = generateSrcset(embed.getSrc, maxWidth, aspectRatio);
						sizes = finalWidth
							? `(min-width: ${finalWidth}px) ${finalWidth}px, 100vw`
							: "100vw";
					}
				}
			} else {
				console.warn(`[EmDashImage] Provider not found: ${providerId}`);
			}
		} catch (error) {
			console.error(
				`[EmDashImage] Failed to get embed for image ${img.id}:`,
				error
			);
		}

		// Fallback to local URL if provider failed
		if (!src) {
			src = buildLocalImageUrl(img);
		}
	}
}

// Build placeholder background style
const blurhash =
	typeof image === "object"
		? (image?.meta?.blurhash as string | undefined)
		: undefined;
const dominantColor =
	typeof image === "object"
		? (image?.meta?.dominantColor as string | undefined)
		: undefined;

let placeholderStyle = "";
if (blurhash) {
	const { blurhashToImageCssString } = await import("@unpic/placeholder");
	placeholderStyle = blurhashToImageCssString(blurhash);
} else if (dominantColor) {
	placeholderStyle = `background-color: ${dominantColor};`;
}

const baseStyle = aspectRatio
	? `aspect-ratio: ${aspectRatio}; max-width: 100%; height: auto;`
	: "max-width: 100%; height: auto;";

const imgProps: Record<string, unknown> = {
	src,
	srcset,
	sizes,
	width: finalWidth,
	height: finalHeight,
	alt: finalAlt,
	loading: priority ? "eager" : "lazy",
	decoding: "async",
	style: placeholderStyle ? `${baseStyle} ${placeholderStyle}` : baseStyle,
	...attrs,
};
---

{img && src ? <img {...imgProps} /> : null}
