import type { Meta, StoryObj } from "@storybook/react";
import React, { useEffect, useMemo, useRef, useState } from "react";

import { AngularVideoPlayerAdapter } from "../src/angular";
import type { EngineStrategy, VideoPlayerRuntimePreload } from "../src/core";

interface AngularAdapterStoryArgs {
	src: string;
	type: string;
	strategy: EngineStrategy;
	preload: VideoPlayerRuntimePreload;
	autoplay: boolean;
	controls: boolean;
	responsive: boolean;
	aspectRatio: string;
	fluid: boolean;
	muted: boolean;
	poster: string;
	preferHQ: boolean;
	debug: boolean;
	initialTime: number;
	isIOS: boolean;
	isMobile: boolean;
	full: boolean;
	withRewind: boolean;
	skipSeconds: number;
	classNames: string;
}

const DEMO_HLS_SOURCE = "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8";
const DEMO_POSTER =
	"https://images.unsplash.com/photo-1574267432553-4b4628081c31?auto=format&fit=crop&w=1280&q=80";

const toAdapterInput = (args: AngularAdapterStoryArgs) => ({
	source: {
		src: args.src,
		type: args.type,
	},
	strategy: args.strategy,
	preload: args.preload,
	autoplay: args.autoplay,
	controls: args.controls,
	responsive: args.responsive,
	aspectRatio: args.aspectRatio === "none" ? undefined : args.aspectRatio,
	fluid: args.fluid,
	muted: args.muted,
	poster: args.poster || undefined,
	preferHQ: args.preferHQ,
	debug: args.debug,
	initialTime: args.initialTime,
	isIOS: args.isIOS,
	isMobile: args.isMobile,
	full: args.full,
	withRewind: args.withRewind,
	skipSeconds: args.skipSeconds,
	classNames: args.classNames
		.split(",")
		.map(item => item.trim())
		.filter(Boolean),
});

const statusText = ({
	initialized,
	engine,
	source,
}: {
	initialized: boolean;
	engine: string | null;
	source?: { src: string } | null;
}) => {
	const sourceText = source?.src ? source.src : "none";
	return `initialized=${initialized}; engine=${engine ?? "none"}; source=${sourceText}`;
};

const AngularAdapterHarness = (args: AngularAdapterStoryArgs) => {
	const hostRef = useRef<HTMLDivElement | null>(null);
	const adapterRef = useRef<AngularVideoPlayerAdapter | null>(null);
	const [status, setStatus] = useState("initializing");
	const input = useMemo(() => toAdapterInput(args), [args]);

	useEffect(() => {
		const host = hostRef.current;
		if (!host) {
			return;
		}

		const adapter = new AngularVideoPlayerAdapter();
		adapterRef.current = adapter;
		let active = true;

		void adapter
			.attach(host, input)
			.then(state => {
				if (!active) {
					return;
				}
				setStatus(statusText(state.runtime));
			})
			.catch(error => {
				if (!active) {
					return;
				}
				setStatus(`attach error: ${String(error)}`);
			});

		return () => {
			active = false;
			adapter.destroy();
			adapterRef.current = null;
		};
	}, []);

	useEffect(() => {
		const adapter = adapterRef.current;
		if (!adapter) {
			return;
		}

		let active = true;

		void adapter
			.update(input)
			.then(state => {
				if (!active) {
					return;
				}
				setStatus(statusText(state.runtime));
			})
			.catch(error => {
				if (!active) {
					return;
				}
				setStatus(`update error: ${String(error)}`);
			});

		return () => {
			active = false;
		};
	}, [input]);

	return (
		<div>
			<div
				style={{
					marginBottom: 12,
					fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
					fontSize: 12,
					color: "#4f4f4f",
				}}
			>
				{status}
			</div>
			<div style={{ width: "100%", maxWidth: 960, minHeight: 320 }} ref={hostRef} />
		</div>
	);
};

const meta: Meta<AngularAdapterStoryArgs> = {
	title: "Angular/VideoPlayerAdapter",
	component: AngularAdapterHarness,
	tags: ["autodocs"],
	args: {
		src: DEMO_HLS_SOURCE,
		type: "application/x-mpegurl",
		strategy: "auto",
		preload: "auto",
		autoplay: false,
		controls: true,
		responsive: true,
		aspectRatio: "16:9",
		fluid: true,
		muted: true,
		poster: DEMO_POSTER,
		preferHQ: false,
		debug: false,
		initialTime: 0,
		isIOS: false,
		isMobile: false,
		full: true,
		withRewind: true,
		skipSeconds: 10,
		classNames: "",
	},
	argTypes: {
		src: { control: "text" },
		type: {
			control: { type: "select" },
			options: [
				"application/x-mpegurl",
				"application/vnd.apple.mpegurl",
				"video/mp4",
			],
		},
		strategy: {
			control: { type: "inline-radio" },
			options: ["auto", "force-hls", "force-videojs"],
		},
		preload: {
			control: { type: "inline-radio" },
			options: ["auto", "metadata", "none", "visibility"],
		},
		aspectRatio: {
			control: { type: "select" },
			options: ["16:9", "4:3", "1:1", "none"],
		},
		initialTime: { control: { type: "number", min: 0, step: 1 } },
		skipSeconds: { control: { type: "number", min: 1, step: 1 } },
		classNames: {
			control: "text",
			description: "Comma-separated class names (e.g. test-one,test-two)",
		},
	},
	render: args => <AngularAdapterHarness {...args} />,
};

export default meta;

type Story = StoryObj<AngularAdapterStoryArgs>;

export const Playground: Story = {};
