import { lucia } from "@/server/auth";
import { type GitHubUserResult, github, isValidCallbackHost, USED_CALLBACK_URL } from "@/server/auth/oauth";
import { ALLOWED_CALLBACK_HOSTS } from "@/utils/api-config";
import { db } from "@/server/db";
import { users } from "@/server/db/schema";
import { OAuth2RequestError } from "arctic";
import { eq } from "drizzle-orm";
import { generateIdFromEntropySize } from "lucia";
import { cookies } from "next/headers";

export const dynamic = "force-dynamic";

interface GithubEmailResponse {
	email: string;
	primary: boolean;
	verified: boolean;
	visibility: string;
}

export async function GET(request: Request): Promise<Response> {
	const url = new URL(request.url);
	const code = url.searchParams.get("code");
	const state = url.searchParams.get("state");
	const storedState = cookies().get("github_oauth_state")?.value ?? null;
	
	// Log für Debugging
	console.log("OAuth Callback erhalten:", url.toString());
	console.log("Callback URL Validierung:", isValidCallbackHost(url.toString()));
	console.log("Erlaubte Hosts:", ALLOWED_CALLBACK_HOSTS);
	
	if (!code || !state || !storedState || state !== storedState) {
		return new Response(
			JSON.stringify({
				status_text: "Ungültiger OAuth-Callback",
				data: { code, state, storedState, url: url.toString() },
			}),
			{
				status: 400,
			},
		);
	}

	try {
		// GitHub OAuth Code validieren - die redirectURI ist bereits im GitHub Client konfiguriert
		const tokens = await github.validateAuthorizationCode(code);
		
		// Log zur Fehlersuche
		console.log(`GitHub OAuth Token-Validierung erfolgreich, verwendete Callback-URL: ${USED_CALLBACK_URL}`);
		
		const githubUserResponse = await fetch("https://git.i.mercedes-benz.com/api/v3/user", {
			headers: {
				Authorization: `Bearer ${tokens.accessToken}`,
			},
		});
		const githubUser: GitHubUserResult = await githubUserResponse.json();

		// Sometimes email can be null in the user query.
		if (githubUser.email === null || githubUser.email === undefined) {
			const githubEmailResponse = await fetch("https://git.i.mercedes-benz.com/api/v3/user/emails", {
				headers: {
					Authorization: `Bearer ${tokens.accessToken}`,
				},
			});
			const githubUserEmail: GithubEmailResponse[] = await githubEmailResponse.json();
			githubUser.email = githubUserEmail[0].email;
		}
		const existingUser = await db.query.users.findFirst({
			where: eq(users.github_id, githubUser.id),
		});

		if (existingUser) {
			const session = await lucia.createSession(existingUser.id, {});
			const sessionCookie = lucia.createSessionCookie(session.id);
			cookies().set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);
			return new Response(null, {
				status: 302,
				headers: {
					Location: "/",
				},
			});
		}

		const userId = generateIdFromEntropySize(10); // 16 characters long

		await db.insert(users).values({
			id: userId,
			github_id: githubUser.id,
			username: githubUser.login,
			displayName: githubUser.name,
			email: githubUser.email,
		});

		const session = await lucia.createSession(userId, {});
		const sessionCookie = lucia.createSessionCookie(session.id);
		cookies().set(sessionCookie.name, sessionCookie.value, {
			...sessionCookie.attributes,
			secure: false, // Else cookie does not get set cause IT has not provided us an SSL certificate yet
		});
		return new Response(null, {
			status: 302,
			headers: {
				Location: "/",
			},
		});
	} catch (e) {
		// the specific error message depends on the provider
		if (e instanceof OAuth2RequestError) {
			// invalid code
			return new Response(
				JSON.stringify({
					status_text: "Invalid code",
					error: JSON.stringify(e),
				}),
				{
					status: 400,
				},
			);
		}
		return new Response(null, {
			status: 500,
		});
	}
}
