---
import type { PrefixedProps as PrefixedCaptionProps } from './caption-props-map'
import type { AudioService } from './utils/audio'
import type { OembedInfo } from './utils/oembed'
import { toCaptionProps } from './caption-props-map'
import Caption from './Caption.astro'
import InternalOembed from './internal/OEmbed.astro'
import { buildSoundCloudEmbedUrl, resolveAudioSource } from './utils/audio'
import { fetchOEmbed } from './utils/oembed'
import './internal/amk-audio.css'

/**
 * Props for the `<Audio>` component — audio player supporting SoundCloud,
 * oEmbed, and local files.
 */
export type Props = PrefixedCaptionProps & {
	/**
	 * Start playback automatically.
	 *
	 * @default false
	 */
	autoPlay?: boolean | undefined
	/** Accessible label for the audio player. */
	label?: string | undefined
	/**
	 * Loop playback.
	 *
	 * @default false
	 */
	loop?: boolean | undefined
	/**
	 * Mute audio.
	 *
	 * @default false
	 */
	muted?: boolean | undefined
	/**
	 * Preload behavior hint.
	 *
	 * @default 'metadata'
	 */
	preload?: 'auto' | 'metadata' | 'none' | undefined
	/** Audio service override. Inferred from `src` when omitted. */
	service?: AudioService | undefined
	/** Audio source: a URL, SoundCloud track ID, or local file path. */
	src: string
}

const {
	autoPlay = false,
	credit,
	creditMediaType,
	creditMediaTypeFallback,
	creditOrganization,
	// eslint-disable-next-line unicorn/prefer-default-parameters -- untyped MDX callers can pass null, which a destructuring default would not replace
	label,
	loop = false,
	muted = false,
	preload = 'metadata',
	service,
	src,
} = Astro.props

const { identifier, service: resolvedService } = resolveAudioSource(src, service)

const resolvedLabel = label ?? 'Audio'

let oembedInfo: OembedInfo | undefined
let embedUrl = ''
let fetchError: string | undefined

if (resolvedService === 'soundcloud') {
	embedUrl = buildSoundCloudEmbedUrl(identifier, { autoPlay })
} else if (resolvedService === 'oembed') {
	try {
		oembedInfo = await fetchOEmbed(identifier)
	} catch (error) {
		fetchError = `[astro-media-kit] Audio oEmbed "${identifier}" failed to load: ${error instanceof Error ? error.message : String(error)}`
		console.error(fetchError)
	}
}

const captionProps = toCaptionProps(
	{ credit, creditMediaType, creditMediaTypeFallback, creditOrganization },
	{ typeFallback: 'audio' },
)

const oembedAspectRatio =
	oembedInfo !== undefined && oembedInfo.width !== 0 && oembedInfo.height !== 0
		? `${oembedInfo.width} / ${oembedInfo.height}`
		: undefined
---

{resolvedService === 'local' && <script>
	import 'media-chrome'
</script>}

{fetchError !== undefined && fetchError !== '' ? (
	import.meta.env.DEV && <p style="font-family: monospace; color: red;">{fetchError}</p>
) : (
	<Caption {...captionProps}>
		{resolvedService === 'oembed' ? (
			oembedInfo && (
				<InternalOembed
					aspectRatio={oembedAspectRatio}
					html={oembedInfo.html}
					resolvedLabel={resolvedLabel}
					slot="media-component"
				/>
			)
		) : resolvedService === 'local' ? (
			<div aria-label={resolvedLabel} class="amk not-content" role="group" slot="media-component">
				<media-controller audio>
					{/* eslint-disable astro/jsx-a11y/media-has-caption -- audio elements don't have captions */}
					<audio
						autoplay={autoPlay || undefined}
						crossorigin="anonymous"
						loop={loop || undefined}
						muted={muted || undefined}
						preload={preload}
						slot="media"
						src={identifier}
					/>
					{/* eslint-enable astro/jsx-a11y/media-has-caption */}
					<media-control-bar>
						<media-play-button />
						<media-mute-button />
						<media-volume-range />
						<media-time-range />
						<media-time-display />
					</media-control-bar>
				</media-controller>
			</div>
		) : (
			<div class="amk not-content" slot="media-component">
				<iframe
					allow="autoplay"
					height="166"
					src={embedUrl}
					style="width: 100%"
					title={resolvedLabel}
				/>
			</div>
		)}
		<slot />
	</Caption>
)}
