Source: RouterEvents/eventPersons/service.js

import { query, UUID2hex, HEX2uuid } from '@commtool/sql-query';
import { getListing } from '../../Router/listEntries.js';
import { updateList } from '../../Router/list/service.js';

/**
 * Helper function to replace special characters with underscores
 * @param {string} str - String to sanitize
 * @returns {string} Sanitized string
 */
export const nameReplace = (str) => {
    return str.replace(/[&\/\\#, +()$~%.'":*?<>{}]/g, '_');
};

/**
 * Get the event that a list belongs to
 * @param {Buffer} listUID - List UID in hex format
 * @returns {Promise<Array>} Event information
 */
export const getEventForList = async (listUID) => {
    const events = await query(`SELECT event.UID, list.Type FROM ObjectBase AS list 
        INNER JOIN Links AS eLink ON (eLink.UID=list.UID AND eLink.Type IN ('member','memberA'))
        INNER JOIN ObjectBase AS event ON (event.UID=eLink.UIDTarget AND event.Type='event')
        WHERE list.UID=?
    `, [listUID], { log: false });
    
    return events;
};

/**
 * Update a list for an event
 * @param {Object} req - Request object with body data
 * @param {Buffer} listUID - List UID in hex format
 * @param {string} listType - Type of the list
 * @returns {Promise<Object>} Update result
 */
export const updateEventList = async (req, listUID, listType) => {
    const result = await updateList(req, listUID, listType);
    return result;
};

/**
 * Get all lists for an event with participants
 * @param {Buffer} eventUID - Event UID in hex format
 * @param {Buffer} userUID - User UID in hex format
 * @param {boolean} isAdmin - Whether user is admin
 * @param {Object} queryParams - Query parameters from request
 * @param {Object} session - Session object
 * @returns {Promise<Array>} Lists with participants
 */
export const getEventLists = async (eventUID, userUID, isAdmin, queryParams, session) => {
    const lists = await query(`SELECT ObjectBase.UID, Member.Data, owner.UIDTarget AS UIDowner,
        ownerO.Title AS TitleOwner, ownerM.Display AS DisplayOwner, Visible.UID AS visible
        FROM ObjectBase
        INNER JOIN Member ON (Member.UID=ObjectBase.UID)
        INNER JOIN Links ON (Links.UID=ObjectBase.UID AND Links.Type IN ('memberA','member'))
        INNER JOIN ObjectBase AS event ON (event.UID=Links.UIDTarget AND event.Type='event')
        INNER JOIN Links AS owner ON (owner.UID=ObjectBase.UID AND owner.Type='memberA' )
        INNER JOIN ObjectBase AS ownerO ON (ownerO.UID=owner.UIDTarget)
        INNER JOIN Member AS ownerM ON (ownerM.UID=ownerO.UIDBelongsTo)
        LEFT JOIN Visible ON (Visible.UID=owner.UID AND Visible.UIDUser=?)
        WHERE ObjectBase.Type IN ('list','dlist')
        AND Links.UIDTarget=?`, [userUID, eventUID], { cast: ['json', 'UUID'], log: false });

    const result = await Promise.all(lists.map(list =>
        new Promise(async (fulfill, reject) => {
            try {
                if (list.Data.tag.includes('all') || list.visible || isAdmin) {
                    const query = { ...queryParams, guest: true };
                    
                    if (list.Data.extraParameter) {
                        const extraFields = list.Data.extraParameter.map(para => ({
                            path: '$.' + nameReplace(para.name),
                            alias: '__extra_' + nameReplace(para.name)
                        }));
                        query.ExtraData = JSON.stringify(extraFields);
                    }
                    
                    const members = await getListing({
                        params: { UID: list.UID },
                        session: session,
                        query: query
                    }, true);
                    
                    fulfill({ ...list, visible: true, participants: members });
                } else {
                    fulfill({ ...list, visible: false, participants: [] });
                }
            } catch (error) {
                reject(error);
            }
        })
    ));

    return result;
};