import { Resolver, presence } from "../util";
import { getVideoID as getDefaultVideoID } from "./default";
import { getVideoID as getShortsVideoID } from "./shorts";

const videoCache = new Map<string, YouTubeAPIResponse>(),
	videoCacheLoading = new Set<string>();

interface YouTubeAPIResponse {
	videoDetails: {
		title: string;
		lengthSeconds: string;
		channelId: string;
		shortDescription: string;
		thumbnail: {
			thumbnails: {
				url: string;
			}[];
		};
		allowRatings: boolean;
		viewCount: string;
		author: string;
		isPrivate: boolean;
		isLiveContent: boolean;
	};
}

async function fetchVideoData(id: string) {
	const data = await presence.getPageVariable(
			"yt.config_.INNERTUBE_API_KEY",
			"yt.config_.INNERTUBE_CLIENT_NAME",
			"yt.config_.INNERTUBE_CLIENT_VERSION"
		),
		request = fetch(
			`https://www.youtube.com/youtubei/v1/player?key=${data["yt.config_.INNERTUBE_API_KEY"]}`,
			{
				method: "POST",
				headers: {
					"Content-Type": "application/json",
				},
				body: JSON.stringify({
					videoId: id,
					context: {
						client: {
							clientName: data["yt.config_.INNERTUBE_CLIENT_NAME"],
							clientVersion: data["yt.config_.INNERTUBE_CLIENT_VERSION"],
						},
					},
				}),
			}
		).then(res => res.json() as Promise<YouTubeAPIResponse>);
	videoCacheLoading.add(id);
	videoCache.set(id, await request);
	videoCacheLoading.delete(id);
}

function isActive(): boolean {
	const currentVideoID = getVideoID();
	if (
		!videoCache.has(currentVideoID) &&
		!videoCacheLoading.has(currentVideoID)
	) {
		fetchVideoData(currentVideoID).catch(() => {
			presence.error("Failed to fetch video data through API");
		});
		return false;
	} else if (videoCacheLoading.has(currentVideoID)) return false;

	return (
		!!getTitle() && !!getUploader() && !!currentVideoID && !!getChannelURL()
	);
}

function getTitle(): string {
	return videoCache.get(getVideoID())?.videoDetails?.title;
}

function getUploader(): string {
	return videoCache.get(getVideoID())?.videoDetails?.author;
}

export function getVideoID(): string {
	return getDefaultVideoID() ?? getShortsVideoID();
}

export function getChannelURL(): string {
	return `https://www.youtube.com/channel/${
		videoCache.get(getVideoID())?.videoDetails?.channelId
	}`;
}

const resolver: Resolver = {
	isActive,
	getTitle,
	getUploader,
	getChannelURL,
	getVideoID,
};

export default resolver;
