import { Elysia } from "elysia";
import { validateSession, User } from "@elysia/lib/auth";

export interface AuthenticatedContext {
	user: User;
	session: any;
	isAuthenticated: boolean;
}

/**
 * Authentication middleware that validates session from cookie or authorization header
 *
 * This middleware:
 * 1. Checks for sessionId in cookie (primary method)
 * 2. Falls back to Authorization header with Bearer token
 * 3. Validates the session using validateSession from lib/auth
 * 4. Sets user and session context for authenticated routes
 * 5. Returns 401 if authentication fails
 */
export const requireAuth = new Elysia({ name: "require-auth" })
	.derive(async ({ cookie, headers, set }) => {
		let sessionId: string | null = null;

		// Try to get sessionId from cookie first
		if (cookie.sessionId && typeof cookie.sessionId.value === "string") {
			sessionId = cookie.sessionId.value;
		}
		// Fallback to Authorization header
		else if (headers.authorization) {
			const authHeader = headers.authorization;
			if (authHeader.startsWith("Bearer ")) {
				sessionId = authHeader.substring(7);
			}
		}

		// If no sessionId found, return unauthenticated
		if (!sessionId) {
			set.status = 401;
			return {
				user: null,
				session: null,
				isAuthenticated: false
			};
		}

		// Validate the session
		const validationResult = await validateSession(sessionId);

		if (!validationResult) {
			set.status = 401;
			return {
				user: null,
				session: null,
				isAuthenticated: false
			};
		}

		// Session is valid, return user and session context
		return {
			user: validationResult.user,
			session: validationResult.session,
			isAuthenticated: true
		};
	})
	.onBeforeHandle({ as: "scoped" }, ({ user, status }) => {
		if (!user) {
			return status(401, {
				message: "Authentication required."
			});
		}
	})
	.as("scoped");

export default requireAuth;
