import { db } from '$lib/server/db';
import { dailyVerses } from '$lib/server/db/schema';
import { eq, sql } from 'drizzle-orm';
import { fetchRandomVerse, fetchRandomVerseAvoiding } from '$lib/server/bible-api';
import type { DailyVerse } from '$lib/server/db/schema';

/** Add `n` days to a YYYY-MM-DD string using pure UTC arithmetic. */
function addDays(dateStr: string, n: number): string {
	const d = new Date(dateStr + 'T00:00:00Z');
	d.setUTCDate(d.getUTCDate() + n);
	return d.toISOString().slice(0, 10);
}

export async function getVerseForDate(dateStr: string): Promise<DailyVerse> {
	// Validate date format (YYYY-MM-DD)
	if (!/^\d{4}-\d{2}-\d{2}$/.test(dateStr)) {
		throw new Error('Invalid date format');
	}

	// If there's an existing verse for this date, return it
	const existing = await db.select().from(dailyVerses).where(eq(dailyVerses.date, dateStr)).limit(1);
	if (existing.length > 0) {
		return existing[0];
	}

	// Otherwise get a new random verse for this date. Gap-fill is extended to
	// respect the no-back-to-back rule: the random verse's book must differ from
	// any committed neighbor (D-1 / D+1). This preserves the global invariant
	// that no two consecutive calendar days ever feature the same book
	// (spec: "Lazy Gap-Fill").
	const [prev] = await db
		.select({ bookId: dailyVerses.bookId })
		.from(dailyVerses)
		.where(eq(dailyVerses.date, addDays(dateStr, -1)))
		.limit(1);
	const [next] = await db
		.select({ bookId: dailyVerses.bookId })
		.from(dailyVerses)
		.where(eq(dailyVerses.date, addDays(dateStr, 1)))
		.limit(1);

	const avoid = [prev?.bookId, next?.bookId].filter((b): b is string => !!b);
	const apiVerse =
		avoid.length > 0
			? await fetchRandomVerseAvoiding(avoid)
			: await fetchRandomVerse();

	const createdAt = sql`${Math.floor(Date.now() / 1000)}`;

	const newVerse: Omit<DailyVerse, 'createdAt'> = {
		id: Bun.randomUUIDv7(),
		date: dateStr,
		bookId: apiVerse.bookId,
		verseText: apiVerse.verseText,
		reference: apiVerse.reference,
	};

	const [inserted] = await db.insert(dailyVerses).values({ ...newVerse, createdAt }).returning();
	return inserted;
}
