import { zValidator } from "@hono/zod-validator";
import { count, desc, eq } from "drizzle-orm";
import { Hono } from "hono";
import { createMiddleware } from "hono/factory";
import { database } from "@/db";
import { libraryFolders, titles } from "@/db/schema";
import auth from "@/lib/auth";
import { createHTTPException } from "@/lib/errors";
import type { ExtendHonoEnv } from "@/lib/types";
import {
	type LibraryAllOutput,
	LibraryTitlesInput,
	type LibraryTitlesOutput,
} from "@/models/api/library";

type LibraryHonoEnv = ExtendHonoEnv<{
	session: Exclude<Awaited<ReturnType<typeof auth.api.getSession>>, null>;
}>;

const authenticationMiddleware = createMiddleware<LibraryHonoEnv>(
	async (c, next) => {
		const session = await auth.api.getSession({
			headers: c.req.raw.headers,
		});

		if (!session) {
			throw createHTTPException(
				401,
				"Authentication required. Please log in to continue.",
			);
		}
		c.set("session", session);
		return await next();
	},
);

const LibraryRouter = new Hono<LibraryHonoEnv>()
	.use(authenticationMiddleware)
	.get("/all", async (c) => {
		const libraries = await database
			.select({
				id: libraryFolders.id,
				name: libraryFolders.name,
				type: libraryFolders.type,
				path: libraryFolders.path,
			})
			.from(libraryFolders)
			.orderBy(libraryFolders.name);

		return c.json<LibraryAllOutput>(libraries);
	})
	.get("/titles", zValidator("param", LibraryTitlesInput), async (c) => {
		const { libraryId, page, limit } = c.req.valid("param");
		// Verify library exists
		const library = await database
			.select({ id: libraryFolders.id })
			.from(libraryFolders)
			.where(eq(libraryFolders.id, libraryId))
			.limit(1);

		if (library.length === 0) {
			throw createHTTPException(404, "Library not found");
		}

		// Get total count
		const totalCountResult = await database
			.select({ count: count() })
			.from(titles)
			.where(eq(titles.libraryFolderId, libraryId));

		const total = totalCountResult[0].count;
		const totalPages = Math.ceil(total / limit);

		// Calculate offset
		const offset = (page - 1) * limit;

		// Get paginated titles
		const titlesData = await database
			.select({
				id: titles.id,
				title: titles.title,
				year: titles.year,
				poster: titles.poster,
				type: titles.type,
			})
			.from(titles)
			.where(eq(titles.libraryFolderId, libraryId))
			.orderBy(desc(titles.createdAt))
			.limit(limit)
			.offset(offset);

		return c.json<LibraryTitlesOutput>({
			titles: titlesData,
			pagination: {
				total,
				page,
				limit,
				totalPages,
			},
		});
	});

export { LibraryRouter };
