import { error } from '@sveltejs/kit';
import { db } from '$lib/server/db';
import { character, characterHistory, config, friendship, user, userCharacterHistory } from '$lib/server/db/schema';
import { getDailyModeCharacters, getOrCreateTodayCharacter, getYesterdayCharacter, getTodayCharacterWinsCount, getDateKey } from '$lib/server/daily-character';
import { and, eq, inArray, like, or } from 'drizzle-orm';

export async function load(event) {
	const characters = await getDailyModeCharacters();
	const dailyCharacter = await getOrCreateTodayCharacter(characters);
	
	if (!dailyCharacter) {
		throw error(404, 'No daily character available. Please check if characters are configured in daily mode.');
	}
	
	const yesterdayCharacter = await getYesterdayCharacter(new Date(), characters);

	// Load the win count for today
	const winCount = await getTodayCharacterWinsCount(dailyCharacter.id);

	let friendsTodayResults: Array<{
		userId: string;
		name: string;
		image: string | null;
		tryCount: number;
		triedCharacters: Array<{ id: string; name: string; pictureUrl: string | null }>;
	}> = [];

	if (event.locals.user) {
		const currentUserId = event.locals.user.id;

		const acceptedFriendships = await db
			.select({
				requesterId: friendship.requesterId,
				addresseeId: friendship.addresseeId
			})
			.from(friendship)
			.where(
				and(
					eq(friendship.status, 'accepted'),
					or(eq(friendship.requesterId, currentUserId), eq(friendship.addresseeId, currentUserId))
				)
			);

		const friendIds = acceptedFriendships.map((relation) =>
			relation.requesterId === currentUserId ? relation.addresseeId : relation.requesterId
		);

		if (friendIds.length > 0) {
			const todayDate = getDateKey(new Date());

			const [todayHistoryEntry] = await db
				.select({ id: characterHistory.id })
				.from(characterHistory)
				.where(eq(characterHistory.date, todayDate))
				.limit(1);

			const todayCharacterHistoryId = todayHistoryEntry?.id;

			if (todayCharacterHistoryId) {
				const friendResultsRaw = await db
					.select({
						userId: user.id,
						name: user.name,
						image: user.image,
						tryCount: userCharacterHistory.tryCount,
						triedCharacterIds: userCharacterHistory.triedCharacterIds
					})
					.from(userCharacterHistory)
					.innerJoin(user, eq(userCharacterHistory.userId, user.id))
					.where(
						and(
							eq(userCharacterHistory.characterHistoryId, todayCharacterHistoryId),
							inArray(userCharacterHistory.userId, friendIds)
						)
					)
					.orderBy(userCharacterHistory.tryCount);

				const uniqueTriedCharacterIds = Array.from(new Set(
					friendResultsRaw.flatMap((entry) => entry.triedCharacterIds ?? [])
				));

				const triedCharacters = uniqueTriedCharacterIds.length > 0
					? await db
						.select({
							id: character.id,
							name: character.name,
							pictureUrl: character.pictureUrl
						})
						.from(character)
						.where(inArray(character.id, uniqueTriedCharacterIds))
					: [];

				const triedCharactersById = new Map(triedCharacters.map((entry) => [entry.id, entry]));

				friendsTodayResults = friendResultsRaw.map((entry) => ({
					userId: entry.userId,
					name: entry.name,
					image: entry.image,
					tryCount: entry.tryCount,
					triedCharacters: (entry.triedCharacterIds ?? [])
						.map((characterId) => triedCharactersById.get(characterId))
						.filter((triedEntry): triedEntry is (typeof triedCharacters)[number] => !!triedEntry)
				}));
			}
		}
	}

	// Load column visibility config
	const columnConfig = await db
		.select()
		.from(config)
		.where(like(config.key, 'characterHistory.column.%.visible'));

	// Convert to object for easier access
	const columnVisibility: Record<string, boolean> = {};
	columnConfig.forEach(row => {
		const match = row.key.match(/characterHistory\.column\.(.+)\.visible/);
		if (match) {
			columnVisibility[match[1]] = row.value === 'true';
		}
	});

	return {
		characters,
		dailyCharacter,
		yesterdayCharacter,
		columnVisibility,
		winCount,
		friendsTodayResults
	};
}
