import { z } from "zod";
// Import client-db index directly as requested.
// On the server, `db` will be null (because `browser` is false in that module).
import { db, ensureSeeded, getSongsForMalAnimeIds } from "$lib/db/client-db";
import {
	MalAnimeListQuerySchema,
	MalAnimeListResponseSchema,
	MalAnimeListStatusEnum,
} from "$lib/types/mal";
import type { PageLoad } from "./$types";

const LIST_QUERY_LIMIT = 1000;

const SearchSchema = MalAnimeListQuerySchema.extend({
	// Username
	mal: z.string().optional(),

	// Allow empty string to mean "All"
	status: MalAnimeListStatusEnum.or(z.literal("")).optional(),
}).strict();

type StatusParam = z.infer<typeof SearchSchema>["status"];
function normalizeStatus(
	status: StatusParam,
): z.infer<typeof MalAnimeListStatusEnum> | undefined {
	if (status == null || status === "") return undefined;
	return status;
}

export const load: PageLoad = async ({ url, fetch, depends }) => {
	depends("mal:animelist");
	depends("clientdb:songs");

	const parsed = SearchSchema.safeParse(
		Object.fromEntries(url.searchParams.entries()),
	);

	const mal = parsed.success ? parsed.data.mal : undefined;
	const status = parsed.success
		? normalizeStatus(parsed.data.status)
		: undefined;

	const username = (mal ?? "").trim();

	// Always return a stable shape for hydration
	if (!username) {
		return {
			LIST_QUERY_LIMIT,
			username: "",
			status: status ?? null,
			malResponse: null as z.infer<typeof MalAnimeListResponseSchema> | null,
			songRows: [] as Awaited<ReturnType<typeof getSongsForMalAnimeIds>>,
		};
	}

	// This endpoint proxies MAL and works server-side.
	const malUrl = new URL(
		`/api/mal/animelist/${encodeURIComponent(username)}`,
		url.origin,
	);

	malUrl.searchParams.set("limit", String(LIST_QUERY_LIMIT));
	if (status) malUrl.searchParams.set("status", status);

	// NOTE: If you later want to support sort/offset, add them here from SearchSchema too.
	const malRes = await fetch(malUrl);

	if (!malRes.ok) {
		// Let +page.svelte decide how to display errors; throw to use SvelteKit error page
		throw new Error(`MAL request failed (${malRes.status})`);
	}

	const malJson: unknown = await malRes.json();
	const malResponse = MalAnimeListResponseSchema.parse(malJson);

	// Client-only DB: on the server `db` is null, so return [] and let hydration re-run load in browser.
	if (!db) {
		return {
			LIST_QUERY_LIMIT,
			username,
			status: status ?? null,
			malResponse,
			songRows: [] as Awaited<ReturnType<typeof getSongsForMalAnimeIds>>,
		};
	}

	// Browser path: seed then query local DB for songs by MAL ids
	await ensureSeeded({ fetch });

	const malIds = malResponse.data.map((e) => e.node.id);
	const songRows = await getSongsForMalAnimeIds(db, malIds);

	return {
		LIST_QUERY_LIMIT,
		username,
		status: status ?? null,
		malResponse,
		songRows,
	};
};
