import { cachified } from "@epic-web/cachified";
import { cache } from "~/utils/cache.server";
import { IS_E2E_TEST_RUN } from "~/utils/e2e";
import { logger } from "~/utils/logger";
import { twitchFetch } from "./fetch";
import { type RawStream, type StreamsResponse, streamsSchema } from "./schemas";

// const STREAMS_MOCK = [
//   {
//     thumbnailUrl:
//       "https://static-cdn.jtvnw.net/previews-ttv/live_user_777_jared-{width}x{height}.jpg",
//     twitchUserName: "777_jared",
//     viewerCount: 129,
//   },
//   {
//     thumbnailUrl:
//       "https://static-cdn.jtvnw.net/previews-ttv/live_user_ano_rta-{width}x{height}.jpg",
//     twitchUserName: "ano_rta",
//     viewerCount: 50,
//   },
//   {
//     thumbnailUrl:
//       "https://static-cdn.jtvnw.net/previews-ttv/live_user_mikashita0104-{width}x{height}.jpg",
//     twitchUserName: "mikashita0104",
//     viewerCount: 49,
//   },
//   {
//     thumbnailUrl:
//       "https://static-cdn.jtvnw.net/previews-ttv/live_user_veenam-{width}x{height}.jpg",
//     twitchUserName: "veenam",
//     viewerCount: 42,
//   },
//   {
//     thumbnailUrl:
//       "https://static-cdn.jtvnw.net/previews-ttv/live_user_minijutopia-{width}x{height}.jpg",
//     twitchUserName: "minijutopia",
//     viewerCount: 25,
//   },
//   {
//     thumbnailUrl:
//       "https://static-cdn.jtvnw.net/previews-ttv/live_user_liligravybread-{width}x{height}.jpg",
//     twitchUserName: "liligravybread",
//     viewerCount: 25,
//   },
//   {
//     thumbnailUrl:
//       "https://static-cdn.jtvnw.net/previews-ttv/live_user_ajx_live-{width}x{height}.jpg",
//     twitchUserName: "ajx_live",
//     viewerCount: 19,
//   },
//   {
//     thumbnailUrl:
//       "https://static-cdn.jtvnw.net/previews-ttv/live_user_yuzuki729-{width}x{height}.jpg",
//     twitchUserName: "yuzuki729",
//     viewerCount: 18,
//   },
//   {
//     thumbnailUrl:
//       "https://static-cdn.jtvnw.net/previews-ttv/live_user_noname_nosplat-{width}x{height}.jpg",
//     twitchUserName: "noname_nosplat",
//     viewerCount: 14,
//   },
//   {
//     thumbnailUrl:
//       "https://static-cdn.jtvnw.net/previews-ttv/live_user_dosankoneet-{width}x{height}.jpg",
//     twitchUserName: "dosankoneet",
//     viewerCount: 13,
//   },
// ];

export async function getStreams() {
	try {
		const result = await cachified({
			key: "twitch-streams",
			cache,
			// 2 minutes
			ttl: 1000 * 60 * 2,
			// 10 minutes
			staleWhileRevalidate: 1000 * 60 * 5 * 2,
			async getFreshValue() {
				return (await getAllStreams())
					.map(mapRawStream)
					.sort((a, b) => b.viewerCount - a.viewerCount);
			},
		});

		return result;
	} catch (e) {
		logger.error(e);
		return [];
	}
}

function mapRawStream(stream: RawStream) {
	return {
		thumbnailUrl: stream.thumbnail_url,
		twitchUserName: stream.user_login.toLowerCase(),
		viewerCount: stream.viewer_count,
	};
}

const SPLATOON_3_TWITCH_GAME_ID = "1158884259";
async function getAllStreams() {
	if (process.env.NODE_ENV === "test" || IS_E2E_TEST_RUN) return [];

	const result: RawStream[] = [];

	let cursor: string | undefined;
	let count = 0;
	while (true) {
		if (count === 50) {
			throw new Error("Stuck getting streams");
		}
		const { data, pagination } = await getStreamsChunk(cursor);

		result.push(
			// filter to ensure each streamer appears only once
			...data.filter(
				(stream) =>
					!result.some(
						(existingStream) => existingStream.user_id === stream.user_id,
					),
			),
		);
		if (!pagination.cursor) {
			return result;
		}

		cursor = pagination.cursor;
		count++;
	}
}

async function getStreamsChunk(cursor?: string): Promise<StreamsResponse> {
	const res = await twitchFetch(
		`https://api.twitch.tv/helix/streams?game_id=${SPLATOON_3_TWITCH_GAME_ID}&first=100&after=${
			cursor ?? ""
		}`,
	);

	const parsed = streamsSchema.safeParse(await res.json());
	if (!parsed.success) {
		throw new Error(parsed.error.message);
	}

	return parsed.data;
}
