import { API_ACCESS_TOKEN_COOKIE_NAME, API_REFRESH_TOKEN_COOKIE_NAME, API_UID_COOKIE_NAME } from "#lib/constants.js";
import type { AstroGlobal } from "astro";
import moment from "moment";
import { createCaller } from "../../astro-typesafe-api-caller.js"
import jwt from "jsonwebtoken"
import { TokenData, TokenType } from "#lib/auth/types.js";

export async function validateAccessTokenServer(astro: AstroGlobal) {
	const accessToken = astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value;
	const refreshToken = astro.cookies.get(API_REFRESH_TOKEN_COOKIE_NAME)?.value;

	if (!refreshToken) {
		// Wir haben keinen Refresh Token, also müssen wir uns neu anmelden.
		astro.cookies.delete(API_ACCESS_TOKEN_COOKIE_NAME);
		astro.cookies.delete(API_REFRESH_TOKEN_COOKIE_NAME);
		astro.cookies.delete(API_UID_COOKIE_NAME)
		return false;
	}

	if (accessToken) {
		const { exp, typ, uid } = jwt.decode(accessToken, {
			json: true
		}) as TokenData

		if (exp > Date.now() && typ === TokenType.Access) {
			return true;
		} else {
			astro.cookies.delete(API_ACCESS_TOKEN_COOKIE_NAME);
		}
	}

	// Wir haben keinen Access Token mehr, vielleicht ist dieser ausgelaufen.
	// Wir haben einen Refresh Token, also versuchen wir uns damit anzumelden.
	// Wenn das klappt, dann haben wir auch einen neuen Access Token.
	// Wenn das nicht klappt, dann müssen wir uns neu anmelden.
	// TODO: Schlägt fehl! Ich habe keine Ahnung warum. Ich habe das Gefühl, dass das an der Astro-Implementierung liegt. Der Refresh Token updated sich nicht richtig....
	try {
		const { accessToken: newAccessToken, accessTokenExpiry, refreshToken: newRefreshToken, refreshTokenExpiry } = await createCaller(astro).auth["access-token"].GET.fetch({
			refreshToken
		})

		astro.cookies.set(API_ACCESS_TOKEN_COOKIE_NAME, newAccessToken, {
			domain: `.${astro.url.host}`,
			path: "/",
			expires: moment.unix(accessTokenExpiry).toDate()
		});
		astro.cookies.set(API_REFRESH_TOKEN_COOKIE_NAME, newRefreshToken, {
			domain: `.${astro.url.host}`,
			path: "/",
			expires: moment.unix(refreshTokenExpiry).toDate()
		})

		return true;
	} catch (e) {
		astro.cookies.delete(API_ACCESS_TOKEN_COOKIE_NAME);
		astro.cookies.delete(API_REFRESH_TOKEN_COOKIE_NAME);
		astro.cookies.delete(API_UID_COOKIE_NAME)
		return false;
	}
}