---
import type { InternalVideoProps } from './types'
import { getControllerStyle } from './types'
import './amk-video.css'

type VideoElementTag = 'hls-video' | 'video' | 'vimeo-video' | 'youtube-video'
type VideoAttributes = astroHTML.JSX.VideoHTMLAttributes

export type Props = InternalVideoProps & {
	/** Which custom element to render. */
	element: VideoElementTag
	/** HLS URL for noscript fallback. */
	hlsUrl?: string | undefined
	/** MP4 fallback URL for noscript. */
	mp4Url?: string | undefined
}

const {
	aspectRatio,
	autoPlay,
	captions,
	controls,
	element,
	hlsConfig,
	hlsUrl,
	intrinsicWidth,
	loop,
	mp4Url,
	muted,
	posterUrl,
	preload,
	resolvedLabel,
	videoSrc,
	zoom,
} = Astro.props

const isHls = element === 'hls-video'
const isEmbed = element === 'vimeo-video' || element === 'youtube-video'
const isNative = controls === 'native'

const controllerStyle = getControllerStyle(intrinsicWidth, aspectRatio)

const videoAttributes: VideoAttributes = {
	autoplay: autoPlay || undefined,
	crossorigin: 'anonymous',
	...(isHls && { disablepictureinpicture: 'true' }),
	loop: loop || undefined,
	muted: muted || undefined,
	playsinline: 'true',
	poster: posterUrl,
	preload,
}

const hlsConfigJson =
	isHls && Object.keys(hlsConfig).length > 0 ? JSON.stringify(hlsConfig) : undefined
---

<script>
	import 'media-chrome'
	// Prevent fullscreen buttons used as zoom triggers from entering native
	// fullscreen. The lightbox click handler on .pswp-video-trigger opens
	// PhotoSwipe instead.
	for (const button of document.querySelectorAll<HTMLElement>(
		'media-fullscreen-button.pswp-video-trigger',
	)) {
		button.addEventListener('mediaenterfullscreenrequest', (event) => {
			event.stopPropagation()
			event.preventDefault()
		})
	}

	// Lightbox mode: hide controls when inactive, even while paused/ended.
	// Media-chrome's shadow DOM CSS keeps controls visible when mediapaused
	// is set. Shadow DOM ::slotted() rules can't be overridden from light DOM,
	// so we toggle inline styles via the userinactivechange event.
	for (const controller of document.querySelectorAll<HTMLElement>('media-controller.lightbox')) {
		const controlBar = controller.querySelector<HTMLElement>('media-control-bar')
		if (!controlBar) {
			continue
		}

		const { style } = controlBar
		const update = () => {
			if (controller.hasAttribute('userinactive')) {
				style.opacity = '0'
				style.pointerEvents = 'none'
			} else {
				style.opacity = ''
				style.pointerEvents = ''
			}
		}

		controller.addEventListener('userinactivechange', update)
		update()
	}
</script>

{isHls && <script>
	import 'hls-video-element'
	import type { HlsVideoElement } from 'hls-video-element'

	// Apply hls.js config before source loading.
	// Config must be set before src so hls.js uses it during initialization.
	// Elements render with data-src instead of src, then we set config + src here.
	for (const element of document.querySelectorAll<HlsVideoElement>('hls-video[data-src]')) {
		const configAttribute = element.dataset.hlsConfig
		if (configAttribute) {
			try {
				element.config = JSON.parse(configAttribute)
			} catch {
				console.warn('[astro-media-kit] Failed to parse HLS config:', configAttribute)
			}
		}

		element.setAttribute('src', element.dataset.src!)
	}
</script>}

{element === 'vimeo-video' && <script>
	import 'vimeo-video-element'
</script>}

{element === 'youtube-video' && <script>
	import 'youtube-video-element'
</script>}

<div
	aria-label={resolvedLabel}
	class:list={['amk', 'not-content', { 'amk-embed': isEmbed }]}
	role="group"
>
	{
		/* Native mode: skip <media-controller> and use the underlying element's
		   native chrome. The `controls` attribute differs by element: native
		   <video>/<hls-video> use the boolean form (`controls`), while the
		   custom embed elements need a literal `controls=""` to satisfy the
		   `attrs.controls === ""` check inside vimeo-video-element /
		   youtube-video-element (anything else, including `controls="true"`,
		   gets coerced to `?controls=0` and disables the iframe chrome). */
		isNative &&
			(isHls ? (
				<hls-video
					{...videoAttributes}
					controls
					data-hls-config={hlsConfigJson}
					data-src={videoSrc}
					style={controllerStyle}
				>
					{captions.map((caption) => (
						<track kind="captions" {...caption} />
					))}
				</hls-video>
			) : element === 'video' ? (
				/* eslint-disable-next-line astro/jsx-a11y/media-has-caption -- captions not available for local files */
				<video {...videoAttributes} controls src={videoSrc} style={controllerStyle} />
			) : element === 'vimeo-video' ? (
				<vimeo-video {...videoAttributes} controls="" src={videoSrc} style={controllerStyle} />
			) : (
				<youtube-video {...videoAttributes} controls="" src={videoSrc} style={controllerStyle} />
			))
	}
	{!isNative && (
		<media-controller
			autohide="1"
			class:list={[controls, { autoplay: autoPlay }]}
			gesturesdisabled={controls === 'lightbox' || controls === 'none' || zoom ? '' : undefined}
			inert={controls === 'none' ? 'true' : undefined}
			style={controllerStyle}
		>
			{isHls ? (
				<hls-video
					{...videoAttributes}
					data-hls-config={hlsConfigJson}
					data-src={videoSrc}
					slot="media"
				>
					{captions.map((caption) => (
						<track kind="captions" {...caption} />
					))}
				</hls-video>
			) : element === 'video' ? (
				/* eslint-disable-next-line astro/jsx-a11y/media-has-caption -- captions not available for local files */
				<video {...videoAttributes} slot="media" src={videoSrc} />
			) : element === 'vimeo-video' ? (
				<vimeo-video {...videoAttributes} slot="media" src={videoSrc} />
			) : (
				<youtube-video {...videoAttributes} slot="media" src={videoSrc} />
			)}

			{controls === 'full' && (
				<media-control-bar>
					<media-play-button />
					<media-mute-button />
					<media-volume-range />
					<media-time-range />
					<media-time-display />
					{captions.length > 0 && <media-captions-button />}
					<media-fullscreen-button class:list={[{ 'pswp-video-trigger': zoom }]}>
						{zoom && <span slot="tooltip-enter">Zoom</span>}
					</media-fullscreen-button>
				</media-control-bar>
			)}

			{controls === 'lightbox' && (
				<media-control-bar>
					<media-play-button />
					<media-mute-button />
					<media-volume-range />
					<media-time-range />
					<media-time-display />
					{captions.length > 0 && <media-captions-button />}
				</media-control-bar>
			)}
			{controls === 'minimal' && (
				<>
					<media-control-bar style="justify-content: flex-end">
						<media-fullscreen-button class:list={[{ 'pswp-video-trigger': zoom }]}>
							{zoom && <span slot="tooltip-enter">Zoom</span>}
						</media-fullscreen-button>
					</media-control-bar>
					<media-play-button slot="centered-chrome" style="border-radius: 50%" />
				</>
			)}
		</media-controller>
	)}
	{isHls && hlsUrl !== undefined && hlsUrl !== '' && (
		<noscript>
			{/* eslint-disable-next-line astro/jsx-a11y/media-has-caption -- noscript fallback is minimal */}
			<video {...videoAttributes}>
				<source src={hlsUrl} type="application/x-mpegURL" />
				{mp4Url !== undefined && mp4Url !== '' && <source src={mp4Url} type="video/mp4" />}
				Your browser does not support HTML5 video.
			</video>
		</noscript>
	)}
</div>
