import type Redis from "ioredis";
import { sessionModel, type SessionModel } from "./entities";
import type { Result } from "$lib/core/data.types";
import { ERROR_CODES } from "$lib/core/error.codes";

export interface SessionRepository {
	getSession(id: string): Promise<Result<SessionModel>>;
	setSession(session: SessionModel): Promise<Result<boolean>>;
	deleteSession(id: string): Promise<Result<boolean>>;
}

export class SessionRepositoryImpl implements SessionRepository {
	private store: Redis;

	constructor(store: Redis) {
		this.store = store;
	}

	async getSession(id: string) {
		const session = await this.store.get(id);
		const parsed = sessionModel.safeParse(JSON.parse(session ?? "{}"));
		if (!parsed.success) {
			return {
				error: {
					code: ERROR_CODES.VALIDATION_ERROR,
					message: "Invalid session data",
					userHint: "Login again",
					detail: "Session not found",
					actionable: false,
				},
			};
		}
		return { data: parsed.data };
	}

	async setSession(session: SessionModel) {
		const parsed = sessionModel.safeParse(session);
		if (!parsed.success) {
			return {
				error: {
					code: ERROR_CODES.VALIDATION_ERROR,
					message: "Invalid session passed",
					userHint: "Login again",
					detail: "Session not found",
					actionable: false,
				},
			};
		}
		const oneWeek = 7 * 24 * 60 * 60;
		await this.store.setex(session.id, oneWeek, JSON.stringify(parsed.data));
		return { data: true };
	}

	async deleteSession(id: string) {
		const session = await this.store.get(id);
		if (!session) {
			return {
				error: {
					code: ERROR_CODES.NOT_FOUND_ERROR,
					message: "Session not found",
					userHint: "Login again",
					detail: "Session not found",
					actionable: false,
				},
			};
		}
		await this.store.del(id);
		return { data: true };
	}
}
