---
import type { ImageMetadata } from 'astro'
import type { MediaType } from '../types'
import { getCreditFromXmpTags } from './utils/image'

const capitalize = (s: string): string => s.charAt(0).toUpperCase() + s.slice(1).toLowerCase()

// Re-export PrefixedProps so it remains importable from `./Caption.astro`.
// The type itself lives in `./caption-props-map` because astro-eslint-parser
// fails to resolve mapped/derived types imported across `.astro` → `.astro`
// file boundaries.
export type { PrefixedProps } from './caption-props-map'

/**
 * Props for the `<Caption>` component — wraps content in
 * `<figure>`/`<figcaption>` with optional XMP credit extraction.
 */
export type Props = {
	/** Attribution name for the media creator. Overrides XMP-extracted creator. */
	creator?: string | undefined
	/** Organization or publication to credit alongside the creator. */
	organization?: string | undefined
	/**
	 * Show the credit line in the caption.
	 *
	 * @default true
	 */
	showCredit?: boolean | undefined
	/** Image source for XMP metadata extraction. Not rendered directly. */
	src?: ImageMetadata | string | undefined
	/**
	 * Semantic media type label (e.g. `'photo'`, `'screenshot'`). Shown in the
	 * credit line.
	 */
	type?: MediaType | undefined
	/**
	 * Fallback media type when XMP Label tag is missing.
	 *
	 * @default 'image'
	 */
	typeFallback?: MediaType | undefined
}

const { creator, organization, showCredit = true, src, type, typeFallback } = Astro.props

// Try to resolve credit components from exif if not provided
// Note clunky rename from "credit" in the XMP tag to "organization"
// and "label" to "type"
const {
	creator: exifCreator,
	credit: exifOrganization,
	label: exifType,
} = src !== undefined &&
showCredit &&
(organization === undefined || creator === undefined || type === undefined)
	? await getCreditFromXmpTags(src)
	: { creator: undefined, credit: undefined, label: undefined }

const resolvedOrganization = organization ?? exifOrganization
const resolvedCreator = creator ?? exifCreator
const resolvedType = type ?? exifType ?? typeFallback

// Render the credit nicely

const creditLine =
	resolvedCreator !== undefined || resolvedOrganization !== undefined
		? [
				resolvedType === undefined ? undefined : capitalize(resolvedType),
				[resolvedCreator, resolvedOrganization].filter(Boolean).join(' / '),
			]
				.filter(Boolean)
				.join(': ')
		: undefined

// Can't get rid of children in markdown, so we inspect what's in the slot
const hasCaption = Boolean(
	// eslint-disable-next-line unicorn/no-await-expression-member
	Astro.slots.default && (await Astro.slots.render('default')).trim().length > 0,
)

const hasCredit = showCredit && creditLine !== undefined
---

{hasCaption || hasCredit ? (
	<figure>
		<slot name="media-component" />
		<figcaption>
			{hasCaption && (
				<span class="caption">
					<slot />
				</span>
			)}
			{hasCredit && <span class="credit">{creditLine}</span>}
		</figcaption>
	</figure>
) : (
	<slot name="media-component" />
)}
