import { createHmac, timingSafeEqual } from 'node:crypto';
import type { BackofficeSession } from '$lib/types/backoffice-user';
import type { MemberSession } from '$lib/types/member';
import { env } from '$env/dynamic/private';

const SESSION_COOKIE = 'member_session';
const SESSION_MAX_AGE = 60 * 60 * 24 * 7; // 7 hari

const BACKOFFICE_SESSION_COOKIE = 'backoffice_session';
const BACKOFFICE_SESSION_MAX_AGE = 60 * 60 * 8; // 8 jam

function getSecret(): string {
	return env.SESSION_SECRET ?? 'catatan-warung-dev-secret-change-in-production';
}

function sign(payload: string): string {
	return createHmac('sha256', getSecret()).update(payload).digest('base64url');
}

function safeEqual(a: string, b: string): boolean {
	const bufA = Buffer.from(a);
	const bufB = Buffer.from(b);
	if (bufA.length !== bufB.length) return false;
	return timingSafeEqual(bufA, bufB);
}

function parseSignedToken<T extends { id: number; email: string; nama: string }>(
	token: string
): T | null {
	const [payload, signature] = token.split('.');
	if (!payload || !signature) return null;
	if (!safeEqual(sign(payload), signature)) return null;

	try {
		const data = JSON.parse(Buffer.from(payload, 'base64url').toString('utf8')) as T;
		if (!data?.id || !data?.email || !data?.nama) return null;
		return data;
	} catch {
		return null;
	}
}

function createSignedToken<T extends object>(data: T): string {
	const payload = Buffer.from(JSON.stringify(data)).toString('base64url');
	const signature = sign(payload);
	return `${payload}.${signature}`;
}

export function createSessionToken(member: MemberSession): string {
	return createSignedToken(member);
}

export function parseSessionToken(token: string): MemberSession | null {
	return parseSignedToken<MemberSession>(token);
}

export function createBackofficeSessionToken(user: BackofficeSession): string {
	return createSignedToken(user);
}

export function parseBackofficeSessionToken(token: string): BackofficeSession | null {
	return parseSignedToken<BackofficeSession>(token);
}

export function getSessionCookieOptions() {
	return {
		path: '/',
		httpOnly: true,
		sameSite: 'lax' as const,
		secure: process.env.NODE_ENV === 'production',
		maxAge: SESSION_MAX_AGE
	};
}

export function getBackofficeSessionCookieOptions() {
	return {
		path: '/',
		httpOnly: true,
		sameSite: 'lax' as const,
		secure: process.env.NODE_ENV === 'production',
		maxAge: BACKOFFICE_SESSION_MAX_AGE
	};
}

export {
	SESSION_COOKIE,
	SESSION_MAX_AGE,
	BACKOFFICE_SESSION_COOKIE,
	BACKOFFICE_SESSION_MAX_AGE
};
