import { TRPCError } from "@trpc/server";
import { jwtVerify, SignJWT } from "jose";
import { JWTExpired } from "jose/errors";
import { env } from "~/env";
import { type Session, sessionSchema } from "~/server/api/trpc";

const secret = new TextEncoder().encode(env.JWT_SECRET);

export async function signToken(
	payload: Session,
	expiresIn: string,
	type: "accessToken" | "refreshToken",
) {
	try {
		return await new SignJWT({ payload, type })
			.setProtectedHeader({ alg: "HS256" })
			.setIssuedAt()
			.setExpirationTime(expiresIn)
			.sign(secret);
	} catch (e) {
		throw new TRPCError({
			code: "INTERNAL_SERVER_ERROR",
			message: `Error signing JWT token: ${(e as Error).message}`,
		});
	}
}

type VerifySuccess = {
	expired: false;
	session: Session;
};

type VerifyExpired = {
	expired: true;
	session: null;
};

type VerifyFailure = {
	expired: boolean;
	session: null;
};

type VerifyResult = VerifySuccess | VerifyExpired | VerifyFailure;

export async function verifyToken(token: string): Promise<VerifyResult> {
	try {
		const { payload } = await jwtVerify(token, secret, {
			requiredClaims: ["exp"],
		});

		const parse = sessionSchema.safeParse(payload.payload);
		if (!parse.success) {
			//console.error("JWT payload invalid:", parse.error);
			return { expired: false, session: null };
		}
		return { expired: false, session: parse.data };
	} catch (e) {
		if (e instanceof JWTExpired) {
			return { expired: true, session: null };
		}
		console.error("JWT verification Internal Error:", (e as Error).message);
		return { expired: false, session: null };
	}
}
