import { json, error } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
import {
	listComments,
	listReplies,
	createComment,
	getMyVotes,
	getUserById,
	type CommentSort
} from '$lib/server/pocketbase';
import { resolveAvatarUrl } from '$lib/server/minio';
import { log } from '$lib/server/logger';

/**
 * GET /api/comments/[slug]?sort=new|top
 * Returns top-level comments + their replies + current visitor's votes + avatar URLs.
 * Response: { comments: BookComment[], myVotes: Record<string, 'up'|'down'>, avatarUrls: Record<string, string> }
 * Each top-level comment has a `replies` array attached.
 */
export const GET: RequestHandler = async ({ params, url, locals }) => {
	const { slug } = params;
	const sortParam = url.searchParams.get('sort') ?? 'new';
	const sort: CommentSort = sortParam === 'top' ? 'top' : 'new';
	const chapter = parseInt(url.searchParams.get('chapter') ?? '0', 10) || 0;

	try {
		const topLevel = await listComments(slug, sort, chapter);

		// Fetch replies for all top-level comments in parallel
		const repliesPerComment = await Promise.all(topLevel.map((c) => listReplies(c.id)));
		const allReplies = repliesPerComment.flat();

		// Build comment+reply list for vote lookup
		const allIds = [...topLevel.map((c) => c.id), ...allReplies.map((r) => r.id)];
		const myVotes = await getMyVotes(allIds, locals.sessionId, locals.user?.id);

		// Attach replies to each top-level comment
		const comments = topLevel.map((c, i) => ({
			...c,
			replies: repliesPerComment[i]
		}));

		// Batch-resolve avatar URLs for all unique user_ids
		// MinIO first (custom upload), fall back to OAuth provider picture.
		const allComments = [...topLevel, ...allReplies];
		const uniqueUserIds = [...new Set(allComments.map((c) => c.user_id).filter(Boolean))];
		const avatarEntries = await Promise.all(
			uniqueUserIds.map(async (userId) => {
				try {
					const user = await getUserById(userId);
					const url = await resolveAvatarUrl(userId, user?.avatar_url);
					return [userId, url] as [string, string | null];
				} catch {
					return [userId, null] as [string, null];
				}
			})
		);
		const avatarUrls: Record<string, string> = {};
		for (const [userId, url] of avatarEntries) {
			if (url) avatarUrls[userId] = url;
		}

		return json({ comments, myVotes, avatarUrls });
	} catch (e) {
		log.error('api/comments/[slug]', 'listComments failed', { slug, err: String(e) });
		error(500, 'Failed to load comments');
	}
};

/**
 * POST /api/comments/[slug]
 * Body: { body: string, parent_id?: string }
 * Creates a new comment or reply. Requires authentication.
 */
export const POST: RequestHandler = async ({ params, request, locals }) => {
	if (!locals.user) error(401, 'Login required to comment');

	const { slug } = params;
	let body: { body?: string; parent_id?: string; chapter?: number };
	try {
		body = await request.json();
	} catch {
		error(400, 'Invalid JSON body');
	}

	const text = (body.body ?? '').trim();
	if (!text) error(400, 'Comment body is required');
	if (text.length > 2000) error(400, 'Comment is too long (max 2000 characters)');

	const parentId = body.parent_id?.trim() || undefined;
	const chapter = typeof body.chapter === 'number' ? body.chapter : 0;

	try {
		const comment = await createComment(
			slug,
			text,
			locals.user.id,
			locals.user.username,
			parentId,
			chapter
		);
		return json(comment, { status: 201 });
	} catch (e) {
		log.error('api/comments/[slug]', 'createComment failed', { slug, err: String(e) });
		error(500, 'Failed to post comment');
	}
};
