Source: Router/maintenance.js

// @ts-check
/**
 * @import {ExpressRequestAuthorized, ExpressResponse} from '../types.js'
 */
/**
 * Maintenance Router
 * 
 * This router defines all endpoints for maintenance operations:
 * - Object recreation and template updates
 * - Database optimization and cleanup
 * - Tree rebuilding and access management
 * - Achievement processing
 * - Family and person data management
 * - Event management and participant lists
 * - System maintenance tasks
 * - SEPA/Lastschrift processing
 * 
 * All endpoints require admin rights unless otherwise specified.
 * 
 * @swagger
 * tags:
 *   - name: Maintenance
 *     description: Administrative maintenance operations for the organisation database
 * 
 * components:
 *   schemas:
 *     Error:
 *       type: object
 *       properties:
 *         success:
 *           type: boolean
 *           example: false
 *         error:
 *           type: string
 *           description: Error message
 *         message:
 *           type: string
 *           description: Human-readable error description
 */
import express from 'express';
import { checkAdmin, checkEmployee } from '../utils/authChecks.js';
import { validateSingleUID } from '../utils/uuidValidation.js';
import {
    createDB,
    recreateObjects,
    getTree,
    migrateDB,
    getAchievements,
    getAchievementsDuplicates,
    getAchievementsTree,
    requalifyPersons,
    triggerMaintenance,
    getFamilyData,
    checkFamilies,
    getVisibility,
    optimizeDatabase,
    getEventLog,
    rebuildListEntries,
    createBirthdayFilter,
    cleanFilters,
    getEventVisibility,
    getEventParticipantLists,
    deleteEvents,
    restorePerson,
    processLastschrift,
    regenerateEmbeddings,
    rebuildSearchIndex,
    compressHistory
} from './maintenance/controller.js';

/** @type {express.Express} */
const api = express();

/**
 * @swagger
 * /maintenance/recreate/{type}:
 *   get:
 *     summary: Recreate all objects of a given type via template
 *     description: |
 *       Re-renders all objects of the specified type in the current organisation using the configured
 *       template. Updates Title, SortName, Display, FullTextIndex, stage, gender, and hierarchie
 *       fields as needed. Supports person, extern, guest, job, function, event, location and other types.
 *       Sends progress events via WebSocket.
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: path
 *         name: type
 *         required: true
 *         schema:
 *           type: string
 *           enum: [person, extern, guest, job, function, event, location, group, list, dlist, email]
 *         description: Object type to recreate
 *         example: person
 *     responses:
 *       200:
 *         description: Recreate completed successfully
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *       401:
 *         description: Unauthorized - Admin rights required
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/recreate/:type', checkAdmin, /** @type {any} */ (recreateObjects) );

/**
 * @swagger
 * /maintenance/tree/{identifyer}:
 *   get:
 *     summary: Rebuild the membership tree
 *     description: |
 *       Performs a full diff-based rebuild of the membership (ownership) tree for the specified
 *       identifier. Deletes stale links and inserts missing ones. Valid identifiers are object type
 *       keywords (person, group, ggroup, guest, extern, event) or a specific UUID.
 *       Sends progress events via WebSocket.
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: path
 *         name: identifyer
 *         required: true
 *         schema:
 *           type: string
 *         description: Object type keyword or UUID to rebuild
 *         example: person
 *     responses:
 *       200:
 *         description: Tree rebuild completed or invalid identifier
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                 message:
 *                   type: string
 *                   description: Present only when the identifier is invalid
 *       401:
 *         description: Unauthorized - Admin rights required
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/tree/:identifyer', checkAdmin, /** @type {any} */ (getTree) );

/**
 * @swagger
 * /maintenance/migrateDB:
 *   get:
 *     summary: Run pending database migrations
 *     description: |
 *       Applies all pending migration modules found in src/config/migrations/.
 *       Each migration supports SQL schema changes and/or JSON data transformations.
 *       Applied migrations are tracked in the dbVersion table.
 *       Sends progress events via WebSocket.
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     responses:
 *       200:
 *         description: Migration completed
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 migrationsApplied:
 *                   type: number
 *                   description: Number of migrations that were applied
 *                   example: 2
 *                 migrationsSkipped:
 *                   type: number
 *                   description: Number of migrations already up to date
 *                   example: 5
 *       401:
 *         description: Unauthorized - Admin rights required
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/migrateDB', checkAdmin, /** @type {any} */ (migrateDB) );

/**
 * @swagger
 * /maintenance/optimize:
 *   get:
 *     summary: Optimize and analyze all database tables
 *     description: |
 *       Runs OPTIMIZE TABLE and ANALYZE TABLE on every base table in the current database.
 *       Helps reclaim storage and keep query statistics up to date.
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     responses:
 *       200:
 *         description: Optimization completed
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/optimize', /** @type {any} */ (optimizeDatabase) );

/**
 * @swagger
 * /maintenance/achievements:
 *   get:
 *     summary: Extract and return achievements for the organisation
 *     description: Returns all achievements extracted via the achievement template logic for the current organisation.
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     responses:
 *       200:
 *         description: List of achievements
 *         content:
 *           application/json:
 *             schema:
 *               type: array
 *               items:
 *                 type: object
 *       401:
 *         description: Unauthorized - Admin rights required
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/achievements', checkAdmin, /** @type {any} */ (getAchievements) );

/**
 * @swagger
 * /maintenance/achievements/duplicates:
 *   get:
 *     summary: Find duplicate achievement objects
 *     description: Returns pairs of achievement objects that share the same Title within the organisation.
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     responses:
 *       200:
 *         description: List of duplicate achievement pairs
 *         content:
 *           application/json:
 *             schema:
 *               type: array
 *               items:
 *                 type: object
 *                 properties:
 *                   UID:
 *                     type: string
 *                     format: uuid
 *                   Title:
 *                     type: string
 *                   duplicateUID:
 *                     type: string
 *                     format: uuid
 *                   duplicateTitle:
 *                     type: string
 *       401:
 *         description: Unauthorized - Admin rights required
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/achievements/duplicates', checkAdmin, /** @type {any} */ (getAchievementsDuplicates) );

/**
 * @swagger
 * /maintenance/achievements/tree:
 *   get:
 *     summary: Get the achievement-to-template tree
 *     description: Returns a flat list of achievement objects linked to their achievement templates, ordered by owner (UIDBelongsTo).
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     responses:
 *       200:
 *         description: Achievement tree
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 tree:
 *                   type: array
 *                   items:
 *                     type: object
 *                     properties:
 *                       UID:
 *                         type: string
 *                         format: uuid
 *                       UIDBelongsTo:
 *                         type: string
 *                         format: uuid
 *                       validFrom:
 *                         type: number
 *                         description: UNIX timestamp
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/achievements/tree', /** @type {any} */ (getAchievementsTree) );

/**
 * @swagger
 * /maintenance/requalify:
 *   get:
 *     summary: Recheck qualifications for all job functions
 *     description: |
 *       Iterates over all function objects in the organisation and re-evaluates the qualification
 *       status of every linked job. Sends progress events via WebSocket.
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     responses:
 *       200:
 *         description: Requalification completed
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 processedFunctions:
 *                   type: number
 *                   description: Number of function objects processed
 *                   example: 12
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/requalify', /** @type {any} */ (requalifyPersons) );

/**
 * @swagger
 * /maintenance/trigger:
 *   get:
 *     summary: Trigger the organisation tree queue
 *     description: Resets the queue-running flag for the organisation and triggers all pending tree queues.
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     responses:
 *       200:
 *         description: Queue triggered
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 message:
 *                   type: string
 *                   example: Tree queue triggered
 *       401:
 *         description: Unauthorized - Admin rights required
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/trigger', checkAdmin, /** @type {any} */ (triggerMaintenance) );

/**
 * @swagger
 * /maintenance/family/{UID}:
 *   get:
 *     summary: Process and correct family link types
 *     description: |
 *       Retrieves family objects and fixes incorrect link types between person/extern objects and
 *       family objects (family ↔ familyFees). Use `all` to process every family in the organisation,
 *       or supply a specific family UUID.
 *       Sends progress events via WebSocket.
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: path
 *         name: UID
 *         required: true
 *         schema:
 *           type: string
 *         description: Family UUID or the keyword `all`
 *         example: all
 *     responses:
 *       200:
 *         description: Family data processed
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 processed:
 *                   type: number
 *                   description: Number of corrected links
 *                   example: 3
 *       401:
 *         description: Unauthorized - Admin rights required
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/family/:UID', checkAdmin, /** @type {any} */ (getFamilyData) );

/**
 * @swagger
 * /maintenance/familyCheck:
 *   get:
 *     summary: Check family last-name consistency
 *     description: Returns a list of families where members have differing last names, indicating possible data inconsistencies.
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     responses:
 *       200:
 *         description: List of inconsistent families
 *         content:
 *           application/json:
 *             schema:
 *               type: array
 *               items:
 *                 type: object
 *                 properties:
 *                   UIDfamily:
 *                     type: string
 *                     format: uuid
 *                   Display:
 *                     type: string
 *                   lastName:
 *                     type: string
 *                   members:
 *                     type: array
 *                     items:
 *                       type: string
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/familyCheck', /** @type {any} */ (checkFamilies) );

/**
 * @swagger
 * /maintenance/visibility/{UID}:
 *   get:
 *     summary: Rebuild visibility / access control entries
 *     description: |
 *       Rebuilds Visible table entries for the specified object(s).
 *       - `lists` – all list/dlist/email/event/eventT/location objects
 *       - `job`   – all job objects (person and list access)
 *       - UUID    – single object identified by UID
 *       An optional `types` query parameter (comma-separated) overrides the UID-based selection.
 *       Sends progress events via WebSocket.
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: path
 *         name: UID
 *         required: true
 *         schema:
 *           type: string
 *         description: Keyword (`lists`, `job`) or a specific object UUID
 *         example: lists
 *       - in: query
 *         name: types
 *         required: false
 *         schema:
 *           type: string
 *         description: Comma-separated list of object types to process (job, list, dlist, email, event, eventT, location)
 *         example: list,dlist
 *     responses:
 *       200:
 *         description: Visibility rebuild completed
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *       400:
 *         description: No valid types supplied
 *       401:
 *         description: Unauthorized - Admin rights required
 *       404:
 *         description: Object not found (when a UUID is supplied)
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/visibility/:UID',checkAdmin, /** @type {any} */ (getVisibility) );

/**
 * @swagger
 * /maintenance/eventLog:
 *   get:
 *     summary: Clean up old event log entries
 *     description: |
 *       Deletes eventLog entries older than the provided UNIX timestamp.
 *       If no timestamp is given, entries older than the first day of the previous month are removed.
 *       The table is optimised after deletion.
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: query
 *         name: timestamp
 *         required: false
 *         schema:
 *           type: number
 *         description: UNIX timestamp cutoff – entries older than this are deleted
 *         example: 1700000000
 *     responses:
 *       200:
 *         description: Event log cleaned
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/eventLog', /** @type {any} */ (getEventLog) );

/**
 * @swagger
 * /maintenance/rebuildListEntries/{UID}:
 *   get:
 *     summary: Rebuild dynamic list memberships for a person or all persons
 *     description: |
 *       First removes dangling list-entry links, then re-evaluates list memberships for
 *       the specified person UUID or all persons/externs in the organisation.
 *       Sends progress events via WebSocket.
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: path
 *         name: UID
 *         required: true
 *         schema:
 *           type: string
 *         description: Person UUID or the keyword `all`
 *         example: all
 *     responses:
 *       200:
 *         description: List entries rebuilt
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *       401:
 *         description: Unauthorized - Admin rights required
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/rebuildListEntries/:UID', checkAdmin, /** @type {any} */ (rebuildListEntries) );

/**
 * @swagger
 * /maintenance/birthdayFilter:
 *   get:
 *     summary: Rebuild time-based (birthday) filters
 *     description: Re-evaluates all time-based filter rules (e.g. birthday filters) across the organisation.
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     responses:
 *       200:
 *         description: Birthday filters rebuilt
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/birthdayFilter', /** @type {any} */ (createBirthdayFilter) );

/**
 * @swagger
 * /maintenance/cleanFilter:
 *   get:
 *     summary: Remove orphaned filter objects
 *     description: |
 *       Deletes ObjectBase entries of type include/exclude/intersect and visible/changeable that
 *       are no longer referenced by any dynamic list link, freeing up stale filter objects.
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     responses:
 *       200:
 *         description: Filters cleaned
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 filter:
 *                   type: object
 *                   description: Result of the filter deletion query
 *                 vfilter:
 *                   type: object
 *                   description: Result of the visibility filter deletion query
 *       401:
 *         description: Unauthorized - Admin rights required
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/cleanFilter', checkAdmin, /** @type {any} */ (cleanFilters) );

/**
 * @swagger
 * /maintenance/eventVisiblity/{UID}:
 *   get:
 *     summary: Rebuild event visibility / access control
 *     description: |
 *       Rebuilds the Visible table entries for the specified event or all events in the organisation.
 *       Note: the path contains the legacy typo `Visiblity` (single `i`).
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: path
 *         name: UID
 *         required: true
 *         schema:
 *           type: string
 *         description: Event UUID or the keyword `all`
 *         example: all
 *     responses:
 *       200:
 *         description: Event visibility rebuilt
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 message:
 *                   type: string
 *                   description: Present only on validation errors
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/eventVisiblity/:UID',  /** @type {any} */ (getEventVisibility) );

/**
 * @swagger
 * /maintenance/event/participantLists/{UID}:
 *   get:
 *     summary: Create or repair participant lists for events
 *     description: |
 *       Ensures that each event has a main participant dlist and per-group participant lists.
 *       Missing lists are created automatically. Supply a specific event UUID or `all` to process
 *       every event in the organisation.
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: path
 *         name: UID
 *         required: true
 *         schema:
 *           type: string
 *         description: Event UUID or the keyword `all`
 *         example: all
 *     responses:
 *       200:
 *         description: Participant lists created/verified
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 message:
 *                   type: string
 *                   description: Present only on validation errors
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/event/participantLists/:UID', /** @type {any} */ (getEventParticipantLists) );

/**
 * @swagger
 * /maintenance/events:
 *   delete:
 *     summary: Delete all events
 *     description: |
 *       Permanently deletes every event object together with its links and member data.
 *       **This operation is irreversible.**
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     responses:
 *       200:
 *         description: All events deleted
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.delete('/events', /** @type {any} */ (deleteEvents) );

/**
 * @swagger
 * /maintenance/restorePerson/{UID}/{timestamp}:
 *   get:
 *     summary: Restore a deleted person from historical data
 *     description: |
 *       Uses MariaDB system-versioned tables to locate and re-insert person/extern objects and their
 *       links as they existed at the given UNIX timestamp. Also restores visibility entries.
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: path
 *         name: UID
 *         required: true
 *         schema:
 *           type: string
 *           format: uuid
 *         description: UUID of the person to restore
 *       - in: path
 *         name: timestamp
 *         required: true
 *         schema:
 *           type: number
 *         description: UNIX timestamp of the historical state to restore from
 *         example: 1700000000
 *     responses:
 *       200:
 *         description: Restore result (success or not-found)
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                 message:
 *                   type: string
 *                   description: Present when the person was not found at the given timestamp
 *                 insertResults:
 *                   type: object
 *                   properties:
 *                     objects:
 *                       type: object
 *                       nullable: true
 *                     links:
 *                       type: object
 *                       nullable: true
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/restorePerson/:UID/:timestamp', validateSingleUID, /** @type {any} */ (restorePerson) );

/**
 * @swagger
 * /maintenance/lastschrift:
 *   get:
 *     summary: Process SEPA Lastschrift data
 *     description: |
 *       Assigns SEPA mandate numbers to familyFees accounts that are missing them, and
 *       normalises accounts without an IBANowner from `familyFees` to `family`.
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     responses:
 *       200:
 *         description: SEPA data processed
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/lastschrift/', /** @type {any} */ (processLastschrift) );

/**
 * @swagger
 * /maintenance/embeddings/{type}:
 *   get:
 *     summary: Regenerate AI embeddings for a given object type
 *     description: |
 *       Clears and rebuilds the AIEmbeddings table entries for all objects of the specified type
 *       in the current organisation. Objects are processed in batches of 50 with a single API call
 *       per batch. Already up-to-date embeddings (same content hash) are skipped.
 *       Sends progress events via WebSocket.
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: path
 *         name: type
 *         required: true
 *         schema:
 *           type: string
 *           enum: [person, extern, guest, job]
 *         description: Object type to regenerate embeddings for
 *         example: person
 *     responses:
 *       200:
 *         description: Embeddings regenerated
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 processed:
 *                   type: number
 *                   description: Total objects processed
 *                 succeeded:
 *                   type: number
 *                 failed:
 *                   type: number
 *                 model:
 *                   type: string
 *                   description: Embedding model used
 *       400:
 *         description: Invalid type parameter
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/embeddings/:type',  /** @type {any} */ (regenerateEmbeddings));

// Search index rebuild
/**
 * @swagger
 * /maintenance/searchindex/{type}:
 *   get:
 *     summary: Rebuild search index for object type
 *     description: |
 *       Clears and rebuilds the SearchIndex table entries (email, phone, etc.) 
 *       for all objects of the specified type in the current organization.
 *       Protected by admin rights.
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: path
 *         name: type
 *         required: true
 *         schema:
 *           type: string
 *           enum: [person, extern, guest, all]
 *         description: Object type to rebuild search index for
 *         example: "person"
 *     responses:
 *       200:
 *         description: Search index rebuilt successfully
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 message:
 *                   type: string
 *                   example: "Search index rebuilt for person"
 *                 processed:
 *                   type: number
 *                   description: Number of objects processed
 *                   example: 150
 *                 emailsInserted:
 *                   type: number
 *                   description: Number of email index entries created
 *                   example: 220
 *                 phonesInserted:
 *                   type: number
 *                   description: Number of phone index entries created
 *                   example: 180
 *                 failed:
 *                   type: number
 *                   description: Number of objects that failed processing
 *                   example: 0
 *       400:
 *         description: Invalid type parameter
 *       401:
 *         description: Unauthorized - Admin rights required
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/searchindex/:type', checkAdmin, /** @type {any} */ (rebuildSearchIndex));

/**
 * @swagger
 * /maintenance/compressHistory:
 *   get:
 *     summary: Compress history of system-versioned tables
 *     description: |
 *       Reduces the history size of system-versioned tables (ObjectBase, Links) by
 *       removing consecutive duplicate history entries. Each unique entity is examined:
 *       only the first occurrence and rows where data changes are kept; identical
 *       intermediate history rows are dropped.
 *
 *       **Workflow:**
 *       1. `GET /maintenance/compressHistory` (dry-run) — reports how many rows would be saved.
 *       2. `GET /maintenance/compressHistory?apply=true` — creates `_new` tables with compressed data.
 *       3. `GET /maintenance/compressHistory?apply=true&swap=true` — also performs the RENAME swap,
 *          replacing the original tables with the compressed ones (old tables become `_oldbak`).
 *
 *       Sends progress events via WebSocket.
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: query
 *         name: apply
 *         required: false
 *         schema:
 *           type: string
 *           enum: [true]
 *         description: Set to `true` to actually create compressed tables (default: dry-run)
 *       - in: query
 *         name: swap
 *         required: false
 *         schema:
 *           type: string
 *           enum: [true]
 *         description: Set to `true` to perform the RENAME swap (requires `apply=true`)
 *       - in: query
 *         name: chunkSize
 *         required: false
 *         schema:
 *           type: integer
 *           default: 50000
 *         description: Number of history rows to process per chunk
 *     responses:
 *       200:
 *         description: Compression completed
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 dryRun:
 *                   type: boolean
 *                   description: Whether this was a dry run (no actual changes)
 *                 swapPerformed:
 *                   type: boolean
 *                   description: Whether the RENAME swap was performed
 *                 results:
 *                   type: array
 *                   items:
 *                     type: object
 *                     properties:
 *                       table:
 *                         type: string
 *                         description: Table name
 *                       squeezed:
 *                         type: number
 *                         description: Number of history rows removed
 *                       inserted:
 *                         type: number
 *                         description: Number of rows inserted into _new table
 *                       originalTotal:
 *                         type: number
 *                         description: Total rows in original table (FOR SYSTEM_TIME ALL)
 *                       newTotal:
 *                         type: number
 *                         description: Total rows in compressed table (FOR SYSTEM_TIME ALL)
 *       401:
 *         description: Unauthorized - Admin rights required
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.get('/compressHistory', checkAdmin, /** @type {any} */ (compressHistory));

// Create a new database
/**
 * @swagger
 * /maintenance/create-db:
 *   post:
 *     summary: Create a new database
 *     description: |
 *       Creates a new database schema with all required tables, views, and functions.
 *       Protected by employee rights.
 *     tags:
 *       - Maintenance
 *     security:
 *       - bearerAuth: []
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             required:
 *               - database
 *             properties:
 *               database:
 *                 type: string
 *                 description: Name of the database to create
 *                 example: "tenant_db_123"
 *     responses:
 *       200:
 *         description: Database created successfully
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 message:
 *                   type: string
 *                   example: "Database created successfully"
 *                 database:
 *                   type: string
 *                   description: Name of the created database
 *       401:
 *         description: Unauthorized - Employee rights required
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Error'
 */
// @ts-ignore
api.post('/create-db', checkEmployee, /** @type {any} */ (createDB));

export default api;