<?php

/*
 * Copyright 2005 - 2025 Centreon (https://www.centreon.com/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * For more information : contact@centreon.com
 *
 */

if (! isset($oreon)) {
    exit();
}

/**
 * Get the list of services id for a pool
 *
 * @param int $poolId The pool id
 * @throws CentreonDbException if a database error occurs
 * @return array
 */
function getListServiceForPool($poolId)
{
    global $pearDB;

    try {
        if ((int) $poolId <= 0) {
            return [];
        }

        // Get pool informations
        $statement = $pearDB->prepareQuery(
            <<<'SQL'
                    SELECT pool_host_id, pool_prefix
                    FROM mod_dsm_pool
                    WHERE pool_id = :pool_id
                SQL
        );
        $pearDB->executePreparedQuery($statement, [':pool_id' => [$poolId, PDO::PARAM_INT]], true);
        $row = $pearDB->fetch($statement);
        if (is_null($row['pool_host_id']) || $row['pool_host_id'] == '') {
            $pearDB->closeQuery($statement);

            return [];
        }

        $poolPrefix = $row['pool_prefix'];

        $statement = $pearDB->prepareQuery(
            <<<'SQL'
                    SELECT service_id, service_description
                    FROM service s, host_service_relation hsr
                    WHERE hsr.host_host_id = :host_id
                        AND service_id = service_service_id
                        AND service_description LIKE :pool_prefix
                SQL
        );

        $pearDB->executePreparedQuery($statement, [
            ':host_id' => [$row['pool_host_id'], PDO::PARAM_INT],
            ':pool_prefix' => [$poolPrefix . '%', PDO::PARAM_STR],
        ], true);

        $listServices = [];
        while ($row = $pearDB->fetch($statement)) {
            if (preg_match('/^' . preg_quote($poolPrefix, '/') . '(\d{4})$/', $row['service_description'])) {
                $listServices[] = $row['service_id'];
            }
        }
        $pearDB->closeQuery($statement);

        return $listServices;
    } catch (CentreonDbException $e) {
        CentreonLog::create()->error(
            logTypeId: CentreonLog::TYPE_BUSINESS_LOG,
            message: "Error fetching list of services for pool ID: {$poolId}",
            customContext: ['poolId' => $poolId],
            exception: $e
        );

        throw $e;
    }
}

/**
 * Return if a host is already used in DSM
 *
 * @param int $hostId The host id
 * @param string $poolPrefix The pool prefix
 * @param int|null $poolId The pool id (optional)
 * @throws CentreonDbException if a database error occurs
 * @return bool
 */
function hostPoolPrefixUsed($hostId, $poolPrefix, $poolId = null)
{
    global $pearDB;

    try {
        $query = <<<'SQL'
                SELECT COUNT(*) AS nb
                FROM mod_dsm_pool
                WHERE pool_host_id = :host_id
                    AND pool_prefix = :pool_prefix
            SQL;

        $params = [
            ':host_id' => [$hostId, PDO::PARAM_INT],
            ':pool_prefix' => [$poolPrefix, PDO::PARAM_STR],
        ];

        if ((int) $poolId > 0) {
            $query .= ' AND pool_id != :pool_id';
            $params[':pool_id'] = [$poolId, PDO::PARAM_INT];
        }

        $statement = $pearDB->prepareQuery($query);
        $pearDB->executePreparedQuery($statement, $params, true);

        $row = $pearDB->fetch($statement);
        $pearDB->closeQuery($statement);

        return $row['nb'] > 0;
    } catch (CentreonDbException $e) {
        CentreonLog::create()->error(
            logTypeId: CentreonLog::TYPE_BUSINESS_LOG,
            message: "Error checking if host {$hostId} is already used with prefix '{$poolPrefix}'",
            customContext: ['hostId' => $hostId, 'poolPrefix' => $poolPrefix, 'poolId' => $poolId],
            exception: $e
        );

        throw $e;
    }
}

/**
 * Enable a slot pool system
 *
 * @param int|null $pool_id The pool ID to enable (optional)
 * @param array $pool_arr An array of pool IDs to enable
 * @throws CentreonDbException if a database error occurs
 */
function enablePoolInDB($pool_id = null, $pool_arr = [])
{
    global $pearDB;

    try {
        if (! $pool_id && empty($pool_arr)) {
            return;
        }

        if ($pool_id) {
            $pool_arr = [$pool_id => '1'];
        }

        // Update services in Centreon configuration
        foreach ($pool_arr as $id => $values) {
            if ((int) $id <= 0) {
                continue;
            }

            $statement = $pearDB->prepareQuery(
                <<<'SQL'
                        UPDATE mod_dsm_pool
                        SET pool_activate = '1'
                        WHERE pool_id = :pool_id
                    SQL
            );
            $pearDB->executePreparedQuery($statement, [':pool_id' => [$id, PDO::PARAM_INT]], true);
            $pearDB->closeQuery($statement);

            $listServices = getListServiceForPool($id);
            if (! empty($listServices)) {
                $bindPlaceholders = array_map(fn (int $index) => ':service_id_' . $index, array_keys($listServices));
                $bindPlaceholdersAsString = implode(', ', $bindPlaceholders);
                $query = sprintf(
                    <<<'SQL'
                            UPDATE service
                            SET service_activate = '1'
                            WHERE service_id IN (%s)
                        SQL,
                    $bindPlaceholdersAsString
                );

                $bindValues = array_map(fn (int $serviceId) => [$serviceId, PDO::PARAM_INT], $listServices);
                $bindParams = array_combine($bindPlaceholders, $bindValues);
                $statement = $pearDB->prepareQuery($query);
                $pearDB->executePreparedQuery($statement, $bindParams, true);
                $pearDB->closeQuery($statement);
            }
        }
    } catch (CentreonDbException $e) {
        CentreonLog::create()->error(
            logTypeId: CentreonLog::TYPE_BUSINESS_LOG,
            message: 'Error enabling pool(s) in DB',
            customContext: ['pool_id' => $pool_id, 'pool_arr' => $pool_arr],
            exception: $e
        );

        throw $e;
    }
}

/**
 * Disable a slot pool system
 *
 * @param int|null $pool_id The pool ID to disable (optional)
 * @param array $pool_arr An array of pool IDs to disable
 * @throws CentreonDbException if a database error occurs
 */
function disablePoolInDB($pool_id = null, $pool_arr = [])
{
    global $pearDB;

    try {
        if (! $pool_id && empty($pool_arr)) {
            return;
        }

        if ($pool_id) {
            $pool_arr = [$pool_id => '1'];
        }

        foreach ($pool_arr as $id => $values) {
            if ((int) $id <= 0) {
                continue;
            }

            $statement = $pearDB->prepareQuery(
                <<<'SQL'
                        UPDATE mod_dsm_pool
                        SET pool_activate = '0'
                        WHERE pool_id = :pool_id
                    SQL
            );
            $pearDB->executePreparedQuery($statement, [':pool_id' => [$id, PDO::PARAM_INT]], true);
            $pearDB->closeQuery($statement);

            // Update services in Centreon configuration
            $listServices = getListServiceForPool($id);
            if (! empty($listServices)) {
                $bindPlaceholders = array_map(fn (int $index) => ':service_id_' . $index, array_keys($listServices));
                $bindPlaceholdersAsString = implode(', ', $bindPlaceholders);
                $query = sprintf(
                    <<<'SQL'
                            UPDATE service
                            SET service_activate = '0'
                            WHERE service_id IN (%s)
                        SQL,
                    $bindPlaceholdersAsString
                );

                $bindValues = array_map(fn (int $serviceId) => [$serviceId, PDO::PARAM_INT], $listServices);
                $bindParams = array_combine($bindPlaceholders, $bindValues);
                $statement = $pearDB->prepareQuery($query);
                $pearDB->executePreparedQuery($statement, $bindParams, true);
                $pearDB->closeQuery($statement);
            }
        }
    } catch (CentreonDbException $e) {
        CentreonLog::create()->error(
            logTypeId: CentreonLog::TYPE_BUSINESS_LOG,
            message: 'Error disabling pool(s) in DB',
            customContext: ['pool_id' => $pool_id, 'pool_arr' => $pool_arr],
            exception: $e
        );

        throw $e;
    }
}

/**
 * Delete a slot pool system
 * @param array $pools An array of pool IDs to delete
 * @throws CentreonDbException if a database error occurs
 */
function deletePoolInDB($pools = [])
{
    global $pearDB;

    try {
        foreach ($pools as $key => $value) {
            // Delete services in Centreon configuration
            $listServices = getListServiceForPool($key);
            if (! empty($listServices)) {
                $bindPlaceholders = array_map(fn (int $index) => ':service_id_' . $index, array_keys($listServices));
                $bindPlaceholdersAsString = implode(', ', $bindPlaceholders);
                $query = sprintf(
                    <<<'SQL'
                            DELETE FROM service
                            WHERE service_id IN (%s)
                        SQL,
                    $bindPlaceholdersAsString
                );

                $bindValues = array_map(fn (int $serviceId) => [$serviceId, PDO::PARAM_INT], $listServices);
                $bindParams = array_combine($bindPlaceholders, $bindValues);
                $statement = $pearDB->prepareQuery($query);
                $pearDB->executePreparedQuery($statement, $bindParams, true);
                $pearDB->closeQuery($statement);
            }

            $statement = $pearDB->prepareQuery(
                <<<'SQL'
                        DELETE FROM mod_dsm_pool
                        WHERE pool_id = :pool_id
                    SQL
            );
            $pearDB->executePreparedQuery($statement, [':pool_id' => [$key, PDO::PARAM_INT]], true);
            $pearDB->closeQuery($statement);
        }
    } catch (CentreonDbException $e) {
        CentreonLog::create()->error(
            logTypeId: CentreonLog::TYPE_BUSINESS_LOG,
            message: 'Error deleting pool(s) in DB',
            customContext: ['pools' => $pools],
            exception: $e
        );

        throw $e;
    }
}

/**
 * Update a slot pool in DB
 *
 * @param int|null $pool_id The pool ID to update
 * @throws CentreonDbException if a database error occurs
 * @return bool
 */
function updatePoolInDB($pool_id = null)
{
    global $form;

    if (! $pool_id) {
        return false;
    }

    $ret = $form->getSubmitValues();

    // Global function to use
    return updatePool($pool_id);
}

/**
 * Insert a slot pool in DB
 *
 * @param array $ret The values for new pool
 * @throws CentreonDbException if a database error occurs
 * @return int $pool_id The pool id, return -1 if error
 */
function insertPoolInDB($ret = [])
{
    return insertPool($ret);
}

/**
 * Check Pool Existence
 * @param string $pool_name The pool name to check
 * @throws CentreonDbException if a database error occurs
 * @return int 0 if the pool does not exist, 1 if it does
 */
function testPoolExistence($pool_name)
{
    global $pearDB;

    try {
        $statement = $pearDB->prepareQuery(
            <<<'SQL'
                    SELECT COUNT(*) AS nb
                    FROM `mod_dsm_pool`
                    WHERE `pool_name` = :pool_name
                SQL
        );
        $pearDB->executePreparedQuery($statement, [':pool_name' => [$pool_name, PDO::PARAM_STR]], true);

        $row = $pearDB->fetch($statement);
        $pearDB->closeQuery($statement);

        return ($row['nb'] > 0) ? 1 : 0;
    } catch (CentreonDbException $e) {
        CentreonLog::create()->error(
            logTypeId: CentreonLog::TYPE_BUSINESS_LOG,
            message: "Error checking pool existence for pool name: {$pool_name}",
            customContext: ['pool_name' => $pool_name],
            exception: $e
        );

        throw $e;
    }
}

/**
 * Duplicate Pool
 *
 * @param array $pool An array of pool IDs to duplicate
 * @param array $nbrDup An array of the number of duplications for each pool
 * @throws CentreonDbException if a database error occurs
 */
function multiplePoolInDB($pool = [], $nbrDup = [])
{
    global $pearDB;

    try {
        foreach ($pool as $key => $value) {
            $statement = $pearDB->prepareQuery(
                <<<'SQL'
                    SELECT *
                    FROM `mod_dsm_pool`
                    WHERE `pool_id` = :pool_id
                    LIMIT 1
                    SQL
            );
            $pearDB->executePreparedQuery($statement, [':pool_id' => [$key, PDO::PARAM_INT]], true);

            if (($row = $pearDB->fetch($statement)) !== false) {
                unset($row['pool_id']);

                $fields = [
                    'pool_name' => PDO::PARAM_STR,
                    'pool_host_id' => PDO::PARAM_INT,
                    'pool_description' => PDO::PARAM_STR,
                    'pool_number' => PDO::PARAM_INT,
                    'pool_prefix' => PDO::PARAM_STR,
                    'pool_cmd_id' => PDO::PARAM_INT,
                    'pool_args' => PDO::PARAM_STR,
                    'pool_activate' => PDO::PARAM_STR,
                    'pool_service_template_id' => PDO::PARAM_INT,
                ];

                $dupCount = (int) ($nbrDup[$key] ?? 0);
                for ($i = 1; $i <= $dupCount; $i++) {
                    $parameters = [];
                    $row['pool_name'] = isset($row['pool_name']) ? $row['pool_name'] . '_' . $i : null;
                    $row['pool_host_id'] = null;
                    $row['pool_activate'] = '0';

                    foreach ($fields as $field => $type) {
                        $parameters[":{$field}"] = [$row[$field], $row[$field] === null ? PDO::PARAM_NULL : $type];
                    }

                    if (! testPoolExistence($row['pool_name'])) {
                        $statement = $pearDB->prepareQuery(
                            <<<'SQL'
                                INSERT INTO `mod_dsm_pool` (
                                    `pool_name`,
                                    `pool_host_id`,
                                    `pool_description`,
                                    `pool_number`,
                                    `pool_prefix`,
                                    `pool_cmd_id`,
                                    `pool_args`,
                                    `pool_activate`,
                                    `pool_service_template_id`
                                ) VALUES (
                                    :pool_name,
                                    :pool_host_id,
                                    :pool_description,
                                    :pool_number,
                                    :pool_prefix,
                                    :pool_cmd_id,
                                    :pool_args,
                                    :pool_activate,
                                    :pool_service_template_id
                                )
                                SQL
                        );
                        $pearDB->executePreparedQuery($statement, $parameters, true);
                        $pearDB->closeQuery($statement);
                    }
                }
            }
        }
    } catch (CentreonDbException $e) {
        CentreonLog::create()->error(
            logTypeId: CentreonLog::TYPE_BUSINESS_LOG,
            message: 'Error duplicating pools with pool IDs: ' . implode(', ', array_keys($pool)),
            customContext: ['pool' => $pool, 'nbrDup' => $nbrDup],
            exception: $e
        );

        throw $e;
    }
}

/**
 * Generate Slot services for a pool
 *
 * @param string $prefix The prefix for the service
 * @param int $number The number of services to generate
 * @param int $host_id The host ID for the services
 * @param int $template The template ID for the services
 * @param int|null $cmd The command ID (optional)
 * @param string|null $args The command arguments (optional)
 * @param string $oldPrefix The old prefix to be replaced
 * @throws CentreonDbException if a database error occurs
 */
function generateServices($prefix, $number, $host_id, $template, $cmd, $args, $oldPrefix)
{
    global $pearDB;

    try {
        if (! isset($oldPrefix)) {
            $oldPrefix = '213343434334343434343';
        }

        $statement = $pearDB->prepareQuery(
            <<<'SQL'
                    SELECT service_id, service_description
                    FROM service s, host_service_relation hsr
                    WHERE hsr.host_host_id = :host_id
                        AND service_id = service_service_id
                        AND service_description LIKE :oldPrefix
                    ORDER BY service_description ASC
                SQL
        );
        $pearDB->executePreparedQuery($statement, [
            ':host_id' => [$host_id, PDO::PARAM_INT],
            ':oldPrefix' => [$oldPrefix . '%', PDO::PARAM_STR],
        ], true);

        $currentNumber = $statement->rowCount();

        if ($currentNumber == 0) {
            for ($i = 1; $i <= $number; $i++) {
                $suffix = '';
                for ($t = $i; $t < 1000; $t *= 10) {
                    $suffix .= '0';
                }
                $suffix .= $i;
                $statementInsert = $pearDB->prepareQuery(
                    <<<'SQL'
                            INSERT INTO service (
                                service_description,
                                service_template_model_stm_id,
                                command_command_id,
                                command_command_id_arg,
                                service_activate,
                                service_register,
                                service_active_checks_enabled,
                                service_passive_checks_enabled,
                                service_parallelize_check,
                                service_obsess_over_service,
                                service_check_freshness,
                                service_event_handler_enabled,
                                service_process_perf_data,
                                service_retain_status_information,
                                service_notifications_enabled,
                                service_is_volatile
                            ) VALUES (
                                :service_description, :template, :cmd, :args, '1', '1', '0', '1', '2', '2', '2', '2', '2', '2', '2', '2'
                            )
                        SQL
                );
                $pearDB->executePreparedQuery($statementInsert, [
                    ':service_description' => [$prefix . $suffix, PDO::PARAM_STR],
                    ':template' => [$template, PDO::PARAM_INT],
                    ':cmd' => [$cmd ?: null, $cmd ? PDO::PARAM_INT : PDO::PARAM_NULL],
                    ':args' => [$args ?: null, $args ? PDO::PARAM_STR : PDO::PARAM_NULL],
                ], true);
                $pearDB->closeQuery($statementInsert);

                $service_id = (int) $pearDB->lastInsertId();

                if ($service_id === 0) {
                    throw new RuntimeException('Failed to retrieve last insert ID for service');
                }

                $statementInsertHostRelation = $pearDB->prepareQuery(
                    'INSERT INTO host_service_relation (service_service_id, host_host_id)
                    VALUES (:service_id, :host_id)'
                );
                $pearDB->executePreparedQuery($statementInsertHostRelation, [
                    ':service_id' => [$service_id, PDO::PARAM_INT],
                    ':host_id' => [$host_id, PDO::PARAM_INT],
                ], true);
                $pearDB->closeQuery($statementInsertHostRelation);

                $statementInsertExtended = $pearDB->prepareQuery(
                    'INSERT INTO extended_service_information (service_service_id) VALUES (:service_id)'
                );
                $pearDB->executePreparedQuery($statementInsertExtended, [':service_id' => [$service_id, PDO::PARAM_INT]], true);
                $pearDB->closeQuery($statementInsertExtended);
            }
        } elseif ($currentNumber <= $number) {
            for ($i = 1; $data = $pearDB->fetch($statement); $i++) {
                $suffix = str_pad($i, 4, '0', STR_PAD_LEFT);
                $statementUpdate = $pearDB->prepareQuery(
                    <<<'SQL'
                            UPDATE service
                            SET service_template_model_stm_id = :template,
                                service_description = :service_description,
                                command_command_id = :cmd,
                                command_command_id_arg = :args
                            WHERE service_id = :service_id
                        SQL
                );
                $pearDB->executePreparedQuery($statementUpdate, [
                    ':template' => [$template, PDO::PARAM_INT],
                    ':service_description' => [$prefix . $suffix, PDO::PARAM_STR],
                    ':cmd' => [$cmd ?: null, $cmd ? PDO::PARAM_INT : PDO::PARAM_NULL],
                    ':args' => [$args ?: null, $args ? PDO::PARAM_STR : PDO::PARAM_NULL],
                    ':service_id' => [$data['service_id'], PDO::PARAM_INT],
                ], true);
                $pearDB->closeQuery($statementUpdate);

                $statementDeleteHostRelation = $pearDB->prepareQuery(
                    'DELETE FROM host_service_relation WHERE service_service_id = :service_id'
                );
                $pearDB->executePreparedQuery($statementDeleteHostRelation, [':service_id' => [$data['service_id'], PDO::PARAM_INT]], true);
                $pearDB->closeQuery($statementDeleteHostRelation);

                $statementInsertHostRelation = $pearDB->prepareQuery(
                    'INSERT INTO host_service_relation (service_service_id, host_host_id)
                    VALUES (:service_id, :host_id)'
                );
                $pearDB->executePreparedQuery($statementInsertHostRelation, [
                    ':service_id' => [$data['service_id'], PDO::PARAM_INT],
                    ':host_id' => [$host_id, PDO::PARAM_INT],
                ], true);
                $pearDB->closeQuery($statementInsertHostRelation);
            }
            while ($i <= $number) {
                $suffix = '';
                for ($t = $i; $t < 1000; $t *= 10) {
                    $suffix .= '0';
                }
                $suffix .= $i;
                $statementInsert = $pearDB->prepareQuery(
                    <<<'SQL'
                            INSERT INTO service (
                                service_description,
                                service_template_model_stm_id,
                                command_command_id,
                                command_command_id_arg,
                                service_activate,
                                service_register,
                                service_active_checks_enabled,
                                service_passive_checks_enabled,
                                service_parallelize_check,
                                service_obsess_over_service,
                                service_check_freshness,
                                service_event_handler_enabled,
                                service_process_perf_data,
                                service_retain_status_information,
                                service_notifications_enabled,
                                service_is_volatile
                            ) VALUES (
                                :service_description, :template, :cmd, :args, '1', '1', '0', '1', '2', '2', '2', '2', '2', '2', '2', '2'
                            )
                        SQL
                );
                $pearDB->executePreparedQuery($statementInsert, [
                    ':service_description' => [$prefix . $suffix, PDO::PARAM_STR],
                    ':template' => [$template, PDO::PARAM_INT],
                    ':cmd' => [$cmd ?: null, $cmd ? PDO::PARAM_INT : PDO::PARAM_NULL],
                    ':args' => [$args ?: null, $args ? PDO::PARAM_STR : PDO::PARAM_NULL],
                ], true);
                $pearDB->closeQuery($statementInsert);

                $service_id = (int) $pearDB->lastInsertId();

                if ($service_id === 0) {
                    throw new RuntimeException('Failed to retrieve last insert ID for service');
                }

                $statementInsertHostRelation = $pearDB->prepareQuery(
                    'INSERT INTO host_service_relation (service_service_id, host_host_id)
                    VALUES (:service_id, :host_id)'
                );
                $pearDB->executePreparedQuery($statementInsertHostRelation, [
                    ':service_id' => [$service_id, PDO::PARAM_INT],
                    ':host_id' => [$host_id, PDO::PARAM_INT],
                ], true);
                $pearDB->closeQuery($statementInsertHostRelation);

                $statementInsertExtended = $pearDB->prepareQuery(
                    'INSERT INTO extended_service_information (service_service_id) VALUES (:service_id)'
                );
                $pearDB->executePreparedQuery($statementInsertExtended, [':service_id' => [$service_id, PDO::PARAM_INT]], true);
                $pearDB->closeQuery($statementInsertExtended);
                $i++;
            }
        } elseif ($currentNumber > $number) {
            for ($i = 1; $data = $pearDB->fetch($statement); $i++) {
                if ($i > $number) {
                    $statementDeleteService = $pearDB->prepareQuery('DELETE FROM service WHERE service_id = :service_id');
                    $pearDB->executePreparedQuery($statementDeleteService, [':service_id' => [$data['service_id'], PDO::PARAM_INT]], true);
                    $pearDB->closeQuery($statementDeleteService);
                }
            }
        }

        $pearDB->closeQuery($statement);
    } catch (CentreonDbException $e) {
        CentreonLog::create()->error(
            logTypeId: CentreonLog::TYPE_BUSINESS_LOG,
            message: "Error generating services for pool with prefix: {$prefix}",
            customContext: [
                'prefix' => $prefix,
                'number' => $number,
                'host_id' => $host_id,
                'template' => $template,
                'cmd' => $cmd,
                'args' => $args,
                'oldPrefix' => $oldPrefix,
            ],
            exception: $e
        );

        throw $e;
    }
}

/**
 * Insert Pool
 *
 * @param array $ret The values for new pool
 * @throws CentreonDbException if a database error occurs
 * @return int The pool ID, or -1 if an error occurs
 */
function insertPool($ret = [])
{
    global $form, $pearDB;

    try {
        if (empty($ret)) {
            $ret = $form->getSubmitValues();
        }

        if (hostPoolPrefixUsed($ret['pool_host_id'], $ret['pool_prefix'])) {
            throw new Exception(_('Hosts is already using that pool prefix'));
        }

        $statement = $pearDB->prepareQuery(
            <<<'SQL'
                    INSERT INTO `mod_dsm_pool` (
                        `pool_name`,
                        `pool_host_id`,
                        `pool_description`,
                        `pool_number`,
                        `pool_prefix`,
                        `pool_cmd_id`,
                        `pool_args`,
                        `pool_activate`,
                        `pool_service_template_id`
                    ) VALUES (
                        :pool_name,
                        :pool_host_id,
                        :pool_description,
                        :pool_number,
                        :pool_prefix,
                        :pool_cmd_id,
                        :pool_args,
                        :pool_activate,
                        :pool_service_template_id
                    )
                SQL
        );

        // Generate all services
        generateServices(
            $ret['pool_prefix'],
            $ret['pool_number'],
            $ret['pool_host_id'],
            $ret['pool_service_template_id'],
            $ret['pool_cmd_id'],
            $ret['pool_args'],
            'kjqsddlqkjdqslkjdqsldkj'
        );

        $fields = [
            'pool_name' => PDO::PARAM_STR,
            'pool_host_id' => PDO::PARAM_INT,
            'pool_description' => PDO::PARAM_STR,
            'pool_number' => PDO::PARAM_INT,
            'pool_prefix' => PDO::PARAM_STR,
            'pool_cmd_id' => PDO::PARAM_INT,
            'pool_args' => PDO::PARAM_STR,
            'pool_activate' => PDO::PARAM_STR,
            'pool_service_template_id' => PDO::PARAM_INT,
        ];

        $parameters = [];
        foreach ($fields as $field => $type) {
            $value = $field === 'pool_activate' ? $ret[$field][$field] : $ret[$field] ?? null;
            $parameters[":{$field}"] = [$value, $value !== null ? $type : PDO::PARAM_NULL];
        }

        $pearDB->executePreparedQuery($statement, $parameters, true);
        $pearDB->closeQuery($statement);

        $pool_id = (int) $pearDB->lastInsertId();

        if ($pool_id === 0) {
            throw new RuntimeException('Failed to retrieve last insert ID for pool');
        }

        if ($ret['pool_activate']['pool_activate'] == 1) {
            enablePoolInDB($pool_id);
        } else {
            disablePoolInDB($pool_id);
        }

        return $pool_id;
    } catch (CentreonDbException $e) {
        CentreonLog::create()->error(
            logTypeId: CentreonLog::TYPE_BUSINESS_LOG,
            message: 'Error inserting pool with name: ' . ($ret['pool_name'] ?? 'N/A'),
            customContext: [
                'pool_name' => $ret['pool_name'] ?? null,
                'pool_host_id' => $ret['pool_host_id'] ?? null,
                'pool_prefix' => $ret['pool_prefix'] ?? null,
            ],
            exception: $e
        );

        throw $e;
    }
}

/**
 * Update Pool
 *
 * @param int|null $pool_id The pool ID
 * @throws CentreonDbException if a database error occurs
 * @return bool
 */
function updatePool($pool_id = null)
{
    global $form, $pearDB;

    try {
        if (! $pool_id) {
            return false;
        }

        // Get Old Prefix
        $statement = $pearDB->prepareQuery('SELECT pool_prefix FROM mod_dsm_pool WHERE pool_id = :pool_id');
        $pearDB->executePreparedQuery($statement, [':pool_id' => [$pool_id, PDO::PARAM_INT]], true);
        $data = $pearDB->fetch($statement);
        $oldPrefix = $data['pool_prefix'];
        $pearDB->closeQuery($statement);

        $ret = $form->getSubmitValues();

        // Validate if host is not already used
        if (isset($ret['pool_host_id'], $ret['pool_prefix']) && hostPoolPrefixUsed($ret['pool_host_id'], $ret['pool_prefix'], $pool_id)) {
            throw new Exception(_('Host is already using that pool prefix'));
        }

        $statement = $pearDB->prepareQuery(
            <<<'SQL'
                    UPDATE mod_dsm_pool SET
                        pool_name = :pool_name,
                        pool_description = :pool_description,
                        pool_host_id = :pool_host_id,
                        pool_number = :pool_number,
                        pool_prefix = :pool_prefix,
                        pool_cmd_id = :pool_cmd_id,
                        pool_args = :pool_args,
                        pool_activate = :pool_activate,
                        pool_service_template_id = :pool_service_template_id
                    WHERE pool_id = :pool_id
                SQL
        );

        $fields = [
            'pool_name' => PDO::PARAM_STR,
            'pool_description' => PDO::PARAM_STR,
            'pool_host_id' => PDO::PARAM_INT,
            'pool_number' => PDO::PARAM_INT,
            'pool_prefix' => PDO::PARAM_STR,
            'pool_cmd_id' => PDO::PARAM_INT,
            'pool_args' => PDO::PARAM_STR,
            'pool_activate' => PDO::PARAM_STR,
            'pool_service_template_id' => PDO::PARAM_INT,
        ];

        $parameters = [];
        foreach ($fields as $field => $type) {
            $value = $field === 'pool_activate' ? $ret[$field][$field] : $ret[$field] ?? null;
            $parameters[":{$field}"] = [$value, $value !== null ? $type : PDO::PARAM_NULL];
        }

        $parameters[':pool_id'] = [$pool_id, PDO::PARAM_INT];

        $pearDB->executePreparedQuery($statement, $parameters, true);
        $pearDB->closeQuery($statement);

        generateServices(
            $ret['pool_prefix'],
            $ret['pool_number'],
            $ret['pool_host_id'],
            $ret['pool_service_template_id'],
            $ret['pool_cmd_id'],
            $ret['pool_args'],
            $oldPrefix
        );

        if ($ret['pool_activate']['pool_activate'] === '1') {
            enablePoolInDB($pool_id);
        } else {
            disablePoolInDB($pool_id);
        }

        return true;
    } catch (CentreonDbException $e) {
        CentreonLog::create()->error(
            logTypeId: CentreonLog::TYPE_BUSINESS_LOG,
            message: 'Error updating pool with ID: ' . ($pool_id ?? 'N/A'),
            customContext: [
                'pool_id' => $pool_id,
                'pool_name' => $ret['pool_name'] ?? null,
                'pool_prefix' => $ret['pool_prefix'] ?? null,
                'pool_activate' => $ret['pool_activate'] ?? null,
            ],
            exception: $e
        );

        throw $e;
    }
}

/**
 * Update Pool ContactGroups
 * @param array $ret
 * @param null|mixed $pool_id
 * @throws CentreonDbException if a database error occurs
 */
function updatePoolContactGroup($pool_id = null, $ret = [])
{
    global $form, $pearDB;

    try {
        if (! $pool_id) {
            return;
        }

        $pearDB->beginTransaction();

        $statement = $pearDB->prepareQuery('DELETE FROM mod_dsm_cg_relation WHERE pool_id = :pool_id');
        $pearDB->executePreparedQuery($statement, [':pool_id' => [$pool_id, PDO::PARAM_INT]], true);
        $pearDB->closeQuery($statement);

        $ret = $ret['pool_cg'] ?? $form->getSubmitValue('pool_cg');

        foreach ($ret as $cg_id) {
            $statement = $pearDB->prepareQuery(
                'INSERT INTO mod_dsm_cg_relation (pool_id, cg_cg_id) VALUES (:pool_id, :cg_cg_id)'
            );
            $pearDB->executePreparedQuery($statement, [
                ':pool_id' => [$pool_id, PDO::PARAM_INT],
                ':cg_cg_id' => [$cg_id, PDO::PARAM_INT],
            ], true);
            $pearDB->closeQuery($statement);
        }

        $pearDB->commit();
    } catch (CentreonDbException $e) {
        if ($pearDB->inTransaction()) {
            $pearDB->rollBack();
        }

        CentreonLog::create()->error(
            logTypeId: CentreonLog::TYPE_BUSINESS_LOG,
            message: 'Error updating contact groups for pool with ID: ' . ($pool_id ?? 'N/A'),
            customContext: [
                'pool_id' => $pool_id,
                'contact_groups' => $ret,
            ],
            exception: $e
        );

        throw $e;
    }
}

/**
 * Update Pool Contacts
 * @param int|null $pool_id The pool ID to update
 * @param array $ret The contacts to update
 * @throws CentreonDbException if a database error occurs
 */
function updatePoolContact($pool_id = null, $ret = [])
{
    global $form, $pearDB;

    try {
        if (! $pool_id) {
            return;
        }

        $pearDB->beginTransaction();

        $statement = $pearDB->prepareQuery('DELETE FROM mod_dsm_cct_relation WHERE pool_id = :pool_id');
        $pearDB->executePreparedQuery($statement, [':pool_id' => [$pool_id, PDO::PARAM_INT]], true);
        $pearDB->closeQuery($statement);

        $ret = $ret['pool_cct'] ?? $form->getSubmitValue('pool_cct');

        foreach ($ret as $cct_id) {
            $statement = $pearDB->prepareQuery(
                'INSERT INTO mod_dsm_cct_relation (pool_id, cct_cct_id) VALUES (:pool_id, :cct_cct_id)'
            );
            $pearDB->executePreparedQuery($statement, [
                ':pool_id' => [$pool_id, PDO::PARAM_INT],
                ':cct_cct_id' => [$cct_id, PDO::PARAM_INT],
            ], true);
            $pearDB->closeQuery($statement);
        }

        $pearDB->commit();
    } catch (CentreonDbException $e) {
        if ($pearDB->inTransaction()) {
            $pearDB->rollBack();
        }

        CentreonLog::create()->error(
            logTypeId: CentreonLog::TYPE_BUSINESS_LOG,
            message: 'Error updating contacts for pool with ID: ' . ($pool_id ?? 'N/A'),
            customContext: [
                'pool_id' => $pool_id,
                'contacts' => $ret,
            ],
            exception: $e
        );

        throw $e;
    }
}
