"use server";

import { constructAPIUrl } from "@/util/url";
import { cookies } from "next/headers";
import { parseSetCookie } from "@/util/cookies";
import makeFetchCookie from "fetch-cookie";
import fetchCookie from "fetch-cookie";
import { User, Auth } from "@/models";
import { AuthContextProviderProps } from "@/providers";

type LoginReturn = {
	cookie?: unknown;
	errorMessage?: string;
};

async function attemptAPILogin(
	method: string,
	formData: FormData
): Promise<LoginReturn | null> {
	// Check if form data is present with required fields, return null if not
	if (
		!formData ||
		!formData.get("input_username") ||
		!formData.get("input_password")
	)
		return null;

	// Instantiate header object
	let headers: Headers = new Headers();

	// Prepare fetchCookie
	const { CookieJar, Cookie } = fetchCookie.toughCookie;
	const jar = new CookieJar();
	const fetchWithCookie = makeFetchCookie(fetch, jar);

	// Set Basic Auth
	headers.set(
		"Authorization",
		`Basic ${Buffer.from(
			`${formData.get("input_username")}:${formData.get(
				"input_password"
			)}`
		).toString("base64")}`
	);
	let res = await fetchWithCookie(await constructAPIUrl("auth"), {
		method: "POST",
		credentials: "include",
		headers: headers,
	});

	console.log(jar.store.idx["localhost"]["/"]);

	let koek = res.headers.getSetCookie();

	let cookieDict = parseSetCookie(koek);

	await cookies().set("auth", cookieDict.auth);
	return {
		cookie: cookieDict.auth,
		errorMessage: "",
	};
	// console.log(koek);
}

export async function serverAttemptAuthenticateUser(
	_currentState: unknown,
	formData: FormData
): Promise<LoginReturn | null> {
	try {
		const signInStatus = await attemptAPILogin("credentials", formData);
		return signInStatus;
	} catch (error: any) {
		if (error) {
			console.log(error);
			switch (error.type) {
				case "CredentialsSignin":
					return { errorMessage: "invalidCredentials" };
				default:
					return { errorMessage: "Something went wrong." };
			}
		}
		throw Error;
	}
}

export async function serverValidateSessionCookie(
	koek: string
): Promise<boolean> {
	const validateSession = await fetch(
		await constructAPIUrl("auth/validate"),
		{
			method: "POST",
			headers: {
				Cookie: `auth=${koek};`,
			},
		}
	);
	if (validateSession.status == 200) return true;
	else return false;
}

export async function userIsAdmin(): Promise<boolean> {
	const cookieAuthValue = await cookies().get("auth")?.value;
	const cookieAuthSanitized = cookieAuthValue
		? JSON.parse(JSON.stringify(cookieAuthValue))
		: "";

	if (!cookieAuthSanitized) return false;
	const parsedAuth = JSON.parse(cookieAuthSanitized);

	if (!parsedAuth.id || !parsedAuth.token || !parsedAuth.user_id)
		return false;

	const p: AuthContextProviderProps = {
		auth: {
			id: parsedAuth.id,
			token: parsedAuth.token,
			user_id: parsedAuth.user_id,
		},
	};

	const foundAuth = await Auth.findOne({ where: { id: p.auth?.id } });
	if (!foundAuth || foundAuth.token != p.auth?.token) return false;

	return true;
}

export async function getCookieAuth(): Promise<AuthContextProviderProps> {
	const cookieAuthValue = await cookies().get("auth")?.value;
	const cookieAuthSanitized = cookieAuthValue
		? JSON.parse(JSON.stringify(cookieAuthValue))
		: "";
	console.log("kanker koek");

	if (!cookieAuthSanitized) return {};

	const kd = JSON.parse(cookieAuthSanitized);
	if (!kd.id || !kd.token || !kd.user_id) return {};

	const foundAuth = await Auth.findOne({
		where: { id: kd.id },
		include: { model: User },
	});
	if (!foundAuth) return {};
	const authObject: AuthContextProviderProps = {
		auth: {
			id: kd.id,
			token: kd.token,
			user_id: kd.user_id,
		},
		user: await foundAuth.user,
	};
	return authObject;
}
