// node dependencies
const WebSocket = require('ws');
const fs = require('fs');
const path = require('path');
require('dotenv').config({ path: '../../.env' });

// internal dependencies
const connections = require('./connections.js'); // connection manager
const stopService = require('./stop.js');

module.exports = async function startWebsocketServer() {
    loadActions(actionsDir);

    try {
        const wss = new WebSocket.Server({
            host: process.env.HOST,
            port: parseInt(process.env.WS_PORT)
        });
        stopService.setServer(wss);
        console.log('WebSocket server started on host localhost and port 3001');

        // Start heartbeat system
        connections.startHeartbeat();

        wss.on('connection', (ws, req) => {

            if (key !== process.env.INTERNAL_SECRET || url.origin !== process.env.CONN_URI) {
                ws.close();
                return;
            }

            // Add client to connection manager
            const connectionId = connections.add(ws, {
                connectedAt: Date.now()
            });

            console.log('New client connected:', connectionId);

            // Handle incoming messages
            ws.on('message', async (raw) => {
                let msg;

                try {
                    msg = JSON.parse(raw);
                } catch (err) {
                    console.error('Invalid JSON received:', raw);
                    return;
                }

                // Expected format:
                // { action: "namespace.actionName", data: {...} }
                if (!msg.action) return;

                const actionHandler = actions[msg.action];

                if (!actionHandler) {
                    console.warn('Unknown action:', msg.action);
                    return;
                }

                try {
                    await actionHandler(msg.data, msg.sec, ws, connectionId);
                } catch (err) {
                    console.error('Error executing action:', msg.action, err);
                }
            });

            // Remove connection on close
            ws.on('close', () => {
                console.log('Client disconnected:', connectionId);
                connections.remove(connectionId);
            });

            // Remove connection on error
            ws.on('error', (err) => {
                console.error('WebSocket error on', connectionId, err);
                connections.remove(connectionId);
            });
        });

        return { online: true, server: wss };
    } catch (err) {
        console.error('WebSocket server failed to start:', err);
        return { online: false, error: err };
    }
};