<script lang="ts">
import { mediaListCollection, Type, type Media } from "$lib/Data/AniList/media";
import { hydrateMediaListCache } from "$lib/Data/AniList/cacheHydration";
import type { AniListAuthorisation } from "$lib/Data/AniList/identity";
import { onMount } from "svelte";
import anime from "$stores/anime";
import lastPruneTimes from "$stores/lastPruneTimes";
import settings from "$stores/settings";
import AnimeList from "./AnimeListTemplate.svelte";
import { addNotification } from "$lib/Notification/store";
import locale from "$stores/locale";
import identity from "$stores/identity";

export let user: AniListAuthorisation = {
	accessToken: "",
	refreshToken: "",
	expiresIn: 0,
	tokenType: "",
};
export let dummy = false;
export let dummyCount = 7;
export let disableFilter = false;
export let limit: number | undefined = undefined;
let animeLists: Promise<Media[]>;
let startTime: number;
let endTime: number;

onMount(async () => {
	await hydrateMediaListCache("anime");

	startTime = performance.now();

	if (dummy) {
		const sampleAnime = (await (
			await fetch("/sample-media/anime.json")
		).json()) as Media[];

		// Use deterministic selection for consistent display
		const filtered = sampleAnime.filter(
			(anime) =>
				anime.episodes &&
				!anime.tags.some((tag) => tag.name === "Nudity") &&
				!anime.tags.some((tag) => tag.name === "Rape") &&
				!anime.tags.some((tag) => tag.name === "Tragedy") &&
				!anime.tags.some((tag) => tag.name === "Bondage") &&
				!anime.genres.some((genre) => genre === "Hentai") &&
				anime.genres.some((genre) => genre === "Comedy") &&
				anime.status !== "NOT_YET_RELEASED" &&
				anime.episodes > 1,
		);
		animeLists = Promise.resolve(
			filtered.slice(0, dummyCount).map((anime, index) => {
				const mediaListEntry =
					anime.mediaListEntry ||
					({ progress: 0 } as NonNullable<Media["mediaListEntry"]>);

				anime.status = "FINISHED";
				anime.nextAiringEpisode = {
					airingAt: Math.floor(Date.now() / 1000) + (index + 1) * 24 * 60 * 60,
					episode: Math.floor((anime.episodes || 12) * 0.8),
				};
				mediaListEntry.progress = Math.floor(
					(anime.nextAiringEpisode.episode || 5) * 0.6,
				);
				anime.mediaListEntry = mediaListEntry;
				return anime;
			}) as unknown as Media[],
		);
	} else {
		animeLists = mediaListCollection(
			user,
			$identity,
			Type.Anime,
			$anime,
			$lastPruneTimes.anime,
			{
				addNotification,
			},
		);
	}
});

const cleanMedia = (anime: Media[]) => {
	if (anime && dummy) return anime;

	if (anime === undefined) return [];

	const outdatedCompletedAnime = anime.filter(
		(media: Media) =>
			media.status === "FINISHED" &&
			(media.mediaListEntry || { status: "DROPPED" }).status !== "DROPPED" &&
			(media.mediaListEntry || { status: "DROPPED" }).status !==
				($settings.displayPausedMedia ? "" : "PAUSED") &&
			(media.mediaListEntry || { progress: 0 }).progress >=
				($settings.displayNotStarted ? 0 : 1),
	);

	outdatedCompletedAnime.sort((a: Media, b: Media) => {
		switch ($settings.displayAnimeSort) {
			case "difference": {
				const difference = (anime: Media) =>
					(anime.nextAiringEpisode?.episode === -1
						? 99999
						: anime.nextAiringEpisode?.episode || -1) -
					(anime.mediaListEntry || { progress: 0 }).progress;

				return difference(a) - difference(b);
			}

			case "end_date":
				return (
					new Date(a.endDate.year, a.endDate.month - 1).getTime() -
					new Date(b.endDate.year, b.endDate.month - 1).getTime()
				);

			case "start_date":
				return (
					new Date(a.startDate.year, a.startDate.month - 1).getTime() -
					new Date(b.startDate.year, b.startDate.month - 1).getTime()
				);

			case "time_remaining":
				return (
					(a.nextAiringEpisode?.airingAt || 9999) -
					(b.nextAiringEpisode?.airingAt || 9999)
				);

			default:
				return 0;
		}
	});

	if (!endTime) endTime = performance.now() - startTime;

	return outdatedCompletedAnime;
};
</script>

<AnimeList
  {endTime}
  {cleanMedia}
  bind:animeLists
  {user}
  title={$locale().lists.completed.anime}
  completed
  {dummy}
  {disableFilter}
  {limit}
/>
