Source: src/routes/api/settings.js

"use strict";

const boom = require("@hapi/boom");

/**
 * Registers settings-related API routes on the Hapi server.
 *
 * This module defines endpoints for managing user settings:
 *
 * - **GET /api.settings**: Retrieves the settings for the authenticated user.
 * - **POST /api/settings**: Creates new settings for the authenticated user.
 * - **PUT /api/settings/{id}**: Updates settings for the authenticated user.
 * - **DELETE /api/settings/{id}**: Deletes settings for the authenticated user.
 *
 * Each route uses a "try" authentication mode. If the user is not authenticated, an unauthorized
 * error is returned.
 *
 * @async
 * @param {Object} server - The Hapi server instance.
 * @returns {Promise<void>} A promise that resolves when the routes have been successfully registered.
 */
module.exports.register = async server => {
    server.route( {
        method: "GET",
        path: "/api.settings",
        options: {
            auth: {mode: "try"}
        },

        /**
         * Handler for retrieving user settings.
         *
         * Checks if the request is authenticated. If authenticated, retrieves the settings
         * for the user from the SQL client's `getSettings` method.
         *
         * @async
         * @param {Object} request - The Hapi request object.
         * @param {Object} request.auth - The authentication object.
         * @param {boolean} request.auth.isAuthenticated - Indicates if the user is authenticated.
         * @param {Object} request.auth.credentials - The credentials which contain user profile details.
         * @returns {Promise<Array<Object>>|Object} A promise that resolves to the retrieved settings recordset,
         * or an unauthorized error if the user is not authenticated.
         */
        handler: async request => {
            try {
                if(!request.auth.isAuthenticated) {
                    return boom.unauthorized();
                }
                const db = request.server.plugins.sql.client;

                const userId = request.auth.credentials.profile.id;
                const res = await db.settings.getSettings(userId);

                return res.recordset;
            } catch (err) {
                console.log(err);
            }
        }
    });

    server.route({
        method: "POST",
        path: "/api/settings",
        options: {
            auth: {mode: "try"}
        },

        /**
         * Handler for creating new settings.
         *
         * Validates the user's authentication and then uses the request payload to create a new settings
         * record. The payload is expected to contain:
         *   - `theme`: The selected theme.
         *   - `layout`: The chosen layout.
         *   - `quotes`: The quotes configuration.
         *
         * @async
         * @param {Object} request - The Hapi request object.
         * @param {Object} request.auth - The authentication object.
         * @param {Object} request.payload - The settings data payload.
         * @param {string} request.payload.theme - The theme selection.
         * @param {string} request.payload.layout - The layout configuration.
         * @param {string} request.payload.quotes - The quotes configuration.
         * @returns {Promise<Object>|Object} A promise that resolves to the newly created settings record,
         * or an unauthorized error if the user is not authenticated.
         */
        handler: async request => {
            try {
                if (!request.auth.isAuthenticated) {
                    return boom.unauthorized();
                }
                const db = request.server.plugins.sql.client;
                const userId = request.auth.credentials.profile.id;
                const {theme, layout, quotes} = request.payload;
                const res = await db.settings.addSetting({userId, theme, layout, quotes});
                return res.recordset[0];
            } catch (err) {
                console.log(err);
                return boom.boomify(err);
            }
        }
    });

    server.route({
        method: "PUT",
        path: "/api/settings/{id}",
        options: {
            auth: {mode: "try"}
        },

        /**
         * Handler for updating existing settings.
         *
         * Validates the user's authentication and then updates the settings record identified by the
         * route parameter `id` using the data provided in the payload. Expected payload properties:
         *   - `theme`: The updated theme.
         *   - `layout`: The updated layout.
         *   - `quotes`: The updated quotes configuration.
         *
         * @async
         * @param {Object} request - The Hapi request object.
         * @param {Object} request.auth - The authentication object.
         * @param {Object} request.params - The route parameters.
         * @param {string} request.params.id - The ID of the settings record to update.
         * @param {Object} request.payload - The updated settings data.
         * @param {string} request.payload.theme - The updated theme selection.
         * @param {string} request.payload.layout - The updated layout configuration.
         * @param {string} request.payload.quotes - The updated quotes configuration.
         * @returns {Promise<Object>|Object} A promise that resolves to the updated settings record,
         * or an unauthorized error if the user is not authenticated.
         */
        handler: async request => {
            try {
                if (!request.auth.isAuthenticated) {
                    return boom.unauthorized();
                }
                const db = request.server.plugins.sql.client;
                const userId = request.auth.credentials.profile.id;
                const {id} = request.params;
                const {theme, layout, quotes} = request.payload;

                const res = await db.settings.updateSetting({id, userId, theme, layout, quotes});
                return res.recordset[0];
            } catch (err) {
                console.log(err);
                return boom.boomify(err);
            }
        }
    });

    server.route( {
        method: "DELETE",
        path: "/api/settings/{id}",
        options: {
            auth: {mode: "try"}
        },

        /**
         * Handler for deleting settings.
         *
         * Validates the user's authentication and then deletes the settings record specified by the
         * route parameter `id`. Returns a 204 (No Content) status if the deletion was successful,
         * or a not found error if no matching record exists.
         *
         * @async
         * @param {Object} request - The Hapi request object.
         * @param {Object} request.auth - The authentication object.
         * @param {Object} request.params - The route parameters.
         * @param {string} request.params.id - The ID of the settings record to delete.
         * @param {Object} h - The Hapi response toolkit.
         * @returns {Promise<Object>|Object} A promise that resolves to an empty response with a 204 status code
         * if deletion is successful, or an error if not.
         */
        handler: async (request, h) => {
            try {
                if (!request.auth.isAuthenticated) {
                    return boom.unauthorized();
                }   
                const id = request.params.id;
                const userId = request.auth.credentials.profile.id;
                const db = request.server.plugins.sql.client;
                const res = await db.settings.deleteSetting({id, userId});
                    
                return res.rowsAffected[0] === 1 ? h.response().code(204) : boom.notFound();
            } catch (err) {
                console.log(err);
                return boom.boomify(err);
            }
        }
    });

};