import { prisma } from "@/lib/db"; import { topAlbums } from "@/lib/lastfm"; import { cached, normKey, CACHE_TTL } from "@/lib/apicache"; import { LIMIT, getLastfmCreds, parsePeriod, wantsRefresh } from "../_creds"; function albumKey(artist: string, album: string): string { return `${artist} ${album}`.trim().toLowerCase(); } export async function GET(request: Request) { const creds = await getLastfmCreds(); if (!creds) return Response.json({ error: "Last.fm not configured" }, { status: 400 }); const url = new URL(request.url); const period = parsePeriod(url); const page = Number(url.searchParams.get("page")) || 1; // Cache ONLY the raw Last.fm payload; own-state (owned/wanted) is annotated live below. let result; try { result = await cached( `lfm-top-albums:${normKey(creds.username)}:${period}:${page}`, 12 * CACHE_TTL.HOUR, () => topAlbums(creds.username, creds.apiKey, { period, page, limit: LIMIT }), { force: wantsRefresh(url) }, ); } catch (e) { return Response.json({ error: e instanceof Error ? e.message : "Last.fm request failed" }, { status: 502 }); } const [libraryItems, monitoredReleases] = await Promise.all([ prisma.libraryItem.findMany({ select: { artist: true, album: true } }), prisma.monitoredRelease.findMany({ where: { OR: [{ monitored: true }, { currentQualityClass: { not: null } }] }, select: { artistName: true, album: true }, }), ]); const ownedKeys = new Set(libraryItems.map((r) => albumKey(r.artist, r.album))); const wantedKeys = new Set(monitoredReleases.map((r) => albumKey(r.artistName, r.album))); const albums = result.items.map((a) => { const key = albumKey(a.artist, a.name); const owned = ownedKeys.has(key); const wanted = wantedKeys.has(key); return { ...a, inLibrary: owned || wanted, owned, wanted }; }); return Response.json({ albums, totalPages: result.totalPages, page: result.page }); }