import { WebSocketManager, WebSocketShardEvents, type SessionInfo } from '@discordjs/ws';
import { REST } from 'discord.js';
import { env } from './env';
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
import type Logger from './structures/Logger';

const sessionFile = './sessions.json';

function loadSessions(): Record<number, SessionInfo> {
	try {
		if (existsSync(sessionFile)) {
			const data = readFileSync(sessionFile, 'utf8');
			return JSON.parse(data) as Record<number, SessionInfo>;
		}
	} catch (error) {
		console.error('Failed to load session store:', error);
	}
	return {};
}

function saveSessions(logger: Logger, sessionStore: Record<number, SessionInfo>) {
	try {
		writeFileSync(sessionFile, JSON.stringify(sessionStore, null, 2));
		logger.info('Session store saved.');
	} catch (error) {
		logger.error('Failed to save session store:', error);
	}
}

const sessionStore = loadSessions();

export async function SocketStart(logger: Logger) {
	const manager = new WebSocketManager({
		token: env.TOKEN,
		intents: 0,
		shardCount: null,
		rest: new REST().setToken(env.TOKEN),
		retrieveSessionInfo(shardId: number): SessionInfo | null {
			if (sessionStore[shardId]) {
				logger.start(`[CLIENT] Retrieved session info for shard ${shardId}`);
				return sessionStore[shardId];
			}
			return null;
		},
		updateSessionInfo(shardId: number, sessionInfo: SessionInfo | null): Promise<void> {
			return new Promise(resolve => {
				if (sessionInfo) {
					sessionStore[shardId] = sessionInfo;
					logger.start(`[CLIENT] Updated session info for shard ${shardId}`);
				} else {
					logger.start(`[CLIENT] Session info for shard ${shardId} is null. Removing session.`);
					delete sessionStore[shardId];
				}
				saveSessions(logger, sessionStore);
				resolve();
			});
		},
	});

	manager
		.on(WebSocketShardEvents.Debug, (shardId, message) => console.log('Debug', shardId, message))
		.on(WebSocketShardEvents.Hello, shardId => {
			console.log('Hello', shardId);
		})
		.on(WebSocketShardEvents.Ready, shardId => {
			console.log('Ready', shardId);
		})
		.on(WebSocketShardEvents.Resumed, async shardId => {
			console.log('Resumed', shardId);
		});

	await manager.connect();

	logger.start('[CLIENT] Socket connected.');
}