<?php
// src/DhcpBundle/Controller/DhcpController.php

namespace App\DhcpBundle\Controller;

use OpenApi\Annotations as OA;
use Psr\Log\LoggerInterface;
use App\DhcpBundle\Service\CurlKeaService;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Exception;


class DhcpController
{
    private $logger;
    
    private $curlKeaService;
    private $backup_dir;

    public function __construct(CurlKeaService $curlKeaService, LoggerInterface $logger, ParameterBagInterface $params)
    {
        $this->curlKeaService = $curlKeaService;
        $this->logger = $logger;
        $this->backup_dir = $params->get('backup_dir');
    }

    /**
     * @Route("/ogdhcp/v1/status", name="getDhcpStatus", methods={"GET"})
     * @OA\Get(
     *     path="/ogdhcp/v1/status",
     *     summary="Get ogDHCP status",
     *     @OA\Response(
     *         response=200,
     *         description="Status retrieved successfully",
     *         @OA\JsonContent(
     *             type="object",
     *             @OA\Property(property="disk_usage", type="object",
     *                 @OA\Property(property="total", type="string"),
     *                 @OA\Property(property="used", type="string"),
     *                 @OA\Property(property="available", type="string"),
     *                 @OA\Property(property="percentage", type="string")
     *             ),
     *             @OA\Property(property="default_oglive", type="string"),
     *             @OA\Property(property="installed_oglives", type="array", @OA\Items(type="string")),
     *             @OA\Property(property="services_status", type="object",
     *                 @OA\Property(property="dhcp_daemon", type="string"),
     *                 @OA\Property(property="nginx", type="string"),
     *                 @OA\Property(property="tftpboot", type="string")
     *             )
     *         )
     *     )
     * )
     */
    public function getDhcpStatus(): Response
    {
        try {
            // Obtener el uso de disco
            $diskUsageResult = $this->getDiskUsage();
            if (!$diskUsageResult) {
                throw new \Exception('Failed to retrieve disk usage');
            }
    
            // Obtener el estado de los servicios de ogDHCP
            $servicesStatusResult = $this->getServicesStatus();
            if (!$servicesStatusResult) {
                throw new \Exception('Failed to retrieve services status');
            }
    
            // Intentar obtener las subredes, pero si falla devolver un array vacío
            $subnetsResult = [];
            try {
                $subnetsResult = $this->getSubnetsService();
            } catch (\Exception $e) {
                // Si ocurre un error, simplemente dejar $subnetsResult vacío
                $subnetsResult = [];
            }
    
            // Componer la respuesta
            $response = [
                'disk_usage' => $diskUsageResult,
                'subnets' => $subnetsResult,
                'services_status' => $servicesStatusResult
            ];
    
            return new JsonResponse(['success' => "Información obtenida con éxito", 'message' => $response], Response::HTTP_OK);
    
        } catch (\Exception $e) {
            // Capturar la excepción y devolver el mensaje de error
            return new JsonResponse(['error' => $e->getMessage()], Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }
    
        private function getDiskUsage(): array
        {
            // Simular la salida del comando df para obtener el uso del disco
            $output = shell_exec("df -h " . realpath($this->backup_dir) . " | tail -1 | awk '{print $2, $3, $4, $5}'");
            if (!$output) {
                $this->logger->error("Failed to execute disk usage command");
                return null;
            }
    
            list($total, $used, $available, $percentage) = explode(' ', $output);
            return [
                'total' => trim($total),
                'used' => trim($used),
                'available' => trim($available),
                'percentage' => trim($percentage),
            ];
        }
    
    
    private function getServicesStatus(): array
    {
        $services = [
            'kea-dhcp4-server' => $this->getServiceStatus('kea-dhcp4-server.service'),
            'kea-ctrl-agent' => $this->getServiceStatus('kea-ctrl-agent.service'),
            'nginx' => $this->getServiceStatus('nginx.service')
        ];
    
        return $services;
    }
    
    private function getServiceStatus(string $service): string
    {
        // Ejecutar el comando systemctl para verificar el estado del servicio
        $output = shell_exec("systemctl is-active " . escapeshellarg($service));
    
        // Si el comando retorna "active", el servicio está corriendo
        if (trim($output) === 'active') {
            return 'active';
        } else {
            return 'inactive';
        }
    }
    
    private function getSubnetsService(): ?array
    {
        try {
            // Ejecutar el comando para obtener la configuración
            $response = $this->curlKeaService->executeCurlCommand('config-get');
    
            // Verificar si la respuesta es nula
            if (!$response) {
                throw new \Exception('Error: No se pudo acceder a la configuración de Kea. Respuesta nula.');
            }
    
            // Verificar el código de resultado
            $result_code = $response[0]["result"];
            if ($result_code != 0) {
                throw new \Exception("Error en la configuración de Kea: " . $response[0]["text"]);
            }
    
            // Verificar si el campo 'subnet4' está presente en la respuesta
            if (!isset($response[0]['arguments']['Dhcp4']['subnet4'])) {
                throw new \Exception("El campo 'subnet4' no está inicializado. Respuesta: " . json_encode($response[0]['arguments']));
            }
    
            // Subredes encontradas, devolver resultado
            return $response[0]['arguments']['Dhcp4']['subnet4'];
    
        } catch (\Exception $e) {
            // Escalar la excepción para que sea gestionada por la función que llama
            throw new \Exception("Error al obtener las subredes: " . $e->getMessage());
        }
    }
    

 /**
 * @OA\Schema(
 *     schema="Subnet",
 *     type="object",
 *     @OA\Property(property="id", type="integer", description="The ID of the subnet"),
 *     @OA\Property(property="subnet", type="string", description="The name of the subnet"),
 *     @OA\Property(property="next-server", type="string", description="The next server in the subnet"),
 *     @OA\Property(property="boot-file-name", type="string", description="The boot file name for the subnet"),
 *     @OA\Property(
 *         property="reservations",
 *         type="array",
 *         @OA\Items(type="object", description="The reservations in the subnet")
 *     )
 * )
 */

    
/**
 * @OA\Get(
 *     path="/ogdhcp/v1/subnets",
 *     summary="Obtiene todas las subredes DHCP",
 *     @OA\Response(
 *         response=200,
 *         description="Devuelve todas las subredes",
 *         @OA\JsonContent(
 *             type="object",
 *             @OA\Property(property="success", type="string", example="Subredes obtenidas correctamente"),
 *             @OA\Property(property="message", type="array",
 *                 @OA\Items(
 *                     type="object",
 *                     @OA\Property(property="id", type="integer", example=1),
 *                     @OA\Property(property="subnet", type="string", example="192.168.1.0/24"),
 *                     @OA\Property(property="next-server", type="string", example="192.168.1.1"),
 *                     @OA\Property(property="boot-file-name", type="string", example="pxelinux.0"),
 *                     @OA\Property(property="pools", type="array",
 *                         @OA\Items(
 *                             type="object",
 *                             @OA\Property(property="pool", type="string", example="192.168.1.10-192.168.1.100")
 *                         )
 *                     ),
 *                     @OA\Property(property="reservations", type="array",
 *                         @OA\Items(
 *                             type="object",
 * 
 *                             @OA\Property(property="ip-address", type="string", example="192.168.1.11"),
 *                             @OA\Property(property="hw-address", type="string", example="00:0c:29:6b:5e:71"),
 *                             @OA\Property(property="hostname", type="string", example="PC11")
 *                         )
 *                     )
 *                 )
 *             )
 *         )
 *     ),
 *     @OA\Response(
 *         response=400,
 *         description="No subnets found",
 *         @OA\JsonContent(
 *             type="object",
 *             @OA\Property(property="error", type="string", example="El campo subnet4 no está inicializado")
 *         )
 *     ),
 *     @OA\Response(
 *         response=500,
 *         description="Error occurred in kea configuration",
 *         @OA\JsonContent(
 *             oneOf={
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="No se pudo acceder al archivo de configuración de Kea")
 *                 ),
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="Error: La subred con el ID 'subnetId' ya existe.")
 *                 )
 *             }
 *         ),
 *         @OA\Examples(
 *             example="noResponse",
 *             summary="No response from kea configuration",
 *             value={"error": "No se pudo acceder al archivo de configuración de Kea"}
 *         ),
 *         @OA\Examples(
 *             example="keaError",
 *             summary="Kea agent down",
 *             value={"error": "Error al obtener la configuración de Kea DHCP"}
 *         )
 *     ),
 * )
 * @Route("/ogdhcp/v1/subnets", methods={"GET"})
 */
   
public function getSubnets(): JsonResponse
{
    try {
        $response = $this->curlKeaService->executeCurlCommand('config-get');

        if (!$response) {
            return new JsonResponse(['error' => 'No se pudo acceder al archivo de configuración de Kea'], 500);
        }

        $result_code = $response[0]["result"];
        if ($result_code == 0) {
            if (!isset($response[0]['arguments']['Dhcp4']['subnet4'])) {
                return new JsonResponse(['error' => 'El campo "subnet4" no está inicializado'], 400);
            } else {
                $subnets = $response[0]['arguments']['Dhcp4']['subnet4'];
                return new JsonResponse([
                    'success' => 'Subredes obtenidas correctamente',
                    'message' => $subnets
                ], 200);
            }
        } else {
            return new JsonResponse(['error' => "Error al obtener la configuración de Kea DHCP: " . $response[0]["text"]], 500);
        }
    } catch (Exception $e) {
        return new JsonResponse(['error' => "Error al obtener la configuración de Kea DHCP: " . $e->getMessage()], 500);
    }
}

/**
 * @OA\Post(
 *     path="/ogdhcp/v1/subnets",
 *     summary="Add a new DHCP subnet",
 *     @OA\RequestBody(
 *         description="JSON payload to create a new subnet",
 *         required=true,
 *         @OA\JsonContent(
 *             type="object",
 *             @OA\Property(property="subnetId", type="integer", example=2),
 *             @OA\Property(property="mask", type="string", example="255.255.255.0"),
 *             @OA\Property(property="address", type="string", example="192.168.1.0"),
 *             @OA\Property(property="nextServer", type="string", example="192.168.1.1"),
 *             @OA\Property(property="bootFileName", type="string", example="pxelinux.0"),
 *             @OA\Property(property="router", type="string", example="192.168.1.254")
 *         )
 *     ),
 *     @OA\Response(
 *         response=200,
 *         description="Subnet added successfully",
 *         @OA\JsonContent(
 *             type="object",
 *             @OA\Property(property="success", type="string", example="Subnet added successfully"),
 *             @OA\Property(property="message", ref="#/components/schemas/Subnet")
 *         )
 *     ),
 *     @OA\Response(
 *         response=400,
 *         description="Error occurred while adding the subnet",
 *         @OA\JsonContent(
 *             oneOf={
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="La subred con el nombre 'subnetName' ya existe.")
 *                 ),
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="La subred con el ID 'subnetId' ya existe.")
 *                 )
 *             }
 *         ),
 *         @OA\Examples(
 *             example="parameterMissing",
 *             summary="Missing required parameter",
 *             value={"error": "Falta un parámetro requerido: $paramFaltante"}
 *         ),
 *         @OA\Examples(
 *             example="nameConflict",
 *             summary="Subnet name already exists",
 *             value={"error": "La subred con la ip 'subnetName' ya existe."}
 *         ),
 *         @OA\Examples(
 *             example="idConflict",
 *             summary="Subnet ID already exists",
 *             value={"error": "La subred con el ID 'subnetId' ya existe."}
 *         ),
 *         @OA\Examples(
 *             example="subnetCreatedNotFound",
 *             summary="Subnet created not found",
 *             value={"error": "No se pudo encontrar la subred creada"}
 *         )
 *     ),
 *     @OA\Response(
 *         response=500,
 *         description="Server error",
 *         @OA\JsonContent(
 *             type="object",
 *             @OA\Property(property="error", type="string", example="Error al guardar la configuración en Kea DHCP.")
 *         )
 *     )
 * )
 * @Route("/ogdhcp/v1/subnets", methods={"POST"})
 */
public function addDhcpSubnet(Request $request): JsonResponse
{
    try {
        $input = json_decode($request->getContent());
        $subnetId = (int) htmlspecialchars($input->subnetId);
        $mask = htmlspecialchars($input->mask);
        $address = htmlspecialchars($input->address);

        // Verificar si next-server, boot-file-name y router están presentes
        $nextServer = isset($input->nextServer) ? htmlspecialchars($input->nextServer) : null;
        $bootFileName = isset($input->bootFileName) ? htmlspecialchars($input->bootFileName) : null;
        $router = isset($input->router) ? htmlspecialchars($input->router) : null;

        // Calcular el gatewayIP si no se proporciona el router
        $gatewayIP = $router ?: substr($address, 0, strrpos($address, '.')) . '.1';
    } catch (Exception $e) {
        $response["message"] = $e->getMessage();
        if (strpos($e->getMessage(), 'Undefined property') !== false) {
            preg_match('/Undefined property: stdClass::\$(\w+)/', $e->getMessage(), $matches);
            $paramFaltante = $matches[1] ?? 'desconocido';
            return new JsonResponse(['error' => "Falta un parámetro requerido: $paramFaltante"], 400);
        }
    }

    try {
        $response = $this->curlKeaService->executeCurlCommand('config-get');
        $subnetName = $address . '/' . $this->curlKeaService->convertMaskToCIDR($mask);

        // Crear el array newSubnet con los valores obligatorios
        $newSubnet = [
            "id" => $subnetId,
            "subnet" => $subnetName,
            "reservations" => [],
            "option-data" => [
                [
                    "name" => "routers",
                    "code" => 3,
                    "data" => $gatewayIP
                ]
            ]
        ];

        // Añadir next-server si está presente
        if ($nextServer) {
            $newSubnet["next-server"] = $nextServer;
        }

        // Añadir boot-file-name si está presente
        if ($bootFileName) {
            $newSubnet["boot-file-name"] = $bootFileName;
        }

        if (!isset($response[0]['arguments']['Dhcp4']['subnet4'])) {
            $response[0]['arguments']['Dhcp4']['subnet4'] = [];
        }

        $subnets = $response[0]['arguments']['Dhcp4']['subnet4'];

        // Verificar si el nombre de la subred o el ID ya existe
        $subnetNameExists = array_reduce($subnets, function ($exists, $subnetElement) use ($subnetName) {
            return $exists || ($subnetElement['subnet'] === $subnetName);
        }, false);

        $subnetIdExists = array_reduce($subnets, function ($exists, $subnetElement) use ($subnetId) {
            return $exists || ($subnetElement['id'] === $subnetId);
        }, false);

        if ($subnetNameExists) {
            return new JsonResponse(['error' => "La subred con la ip '$subnetName' ya existe."], 400);
        } elseif ($subnetIdExists) {
            return new JsonResponse(['error' => "La subred con el ID '$subnetId' ya existe."], 400);
        } else {
            $response[0]['arguments']['Dhcp4']['subnet4'][] = $newSubnet;

            // Eliminar el campo 'hash' si existe
            if (isset($response[0]['arguments']['hash'])) {
                unset($response[0]['arguments']['hash']);
            }

            $array_encoded = json_encode($response[0]['arguments']);
            $configurationParsed = str_replace('\\', '', $array_encoded);
            $configuration = json_decode($configurationParsed);
            $responseTest = $this->curlKeaService->executeCurlCommand('config-test', $configuration);

            if ($responseTest[0]["result"] == 0) {
                $responseSet = $this->curlKeaService->executeCurlCommand('config-set', $configuration);
                if ($responseSet == false || $responseSet[0]["result"] != 0) {
                    return new JsonResponse(['error' => "Error al guardar la configuración en Kea DHCP: " . $responseSet[0]["text"]], 400);
                } else {
                    $responseWrite = $this->curlKeaService->executeCurlCommand('config-write', $configuration);
                    if ($responseWrite == false || $responseWrite[0]["result"] != 0) {
                        return new JsonResponse(['error' => "Error al guardar la configuración en Kea DHCP: " . $responseWrite[0]["text"]], 400);
                    } else {
                        // Realizar una nueva consulta a Kea para obtener la subred recién creada
                        $configGetResponse = $this->curlKeaService->executeCurlCommand('config-get');

                        // Buscar la subred creada
                        $createdSubnet = null;
                        foreach ($configGetResponse[0]['arguments']['Dhcp4']['subnet4'] as $subnet) {
                            if ($subnet['id'] == $subnetId) {
                                $createdSubnet = $subnet;
                                break;
                            }
                        }

                        if ($createdSubnet === null) {
                            return new JsonResponse(['error' => "No se pudo encontrar la subred creada"], 400);
                        }

                        return new JsonResponse(['success' => "Subred agregada correctamente", 'message' => $createdSubnet], 200);
                    }
                }
            } else {
                return new JsonResponse(['error' => "Error en la configuración de Kea: " . $responseTest[0]["text"]], 400);
            }
        }
    } catch (Exception $e) {
        return new JsonResponse(['error' => "Error al obtener la configuración de Kea DHCP: " . $e->getMessage()], 500);
    }
}

 

   /**
    * @OA\Delete(
    *     path="/ogdhcp/v1/subnets/{subnetId}",
    *     summary="Delete a DHCP subnet",
    *     @OA\Parameter(
    *         name="subnetId",
    *         in="path",
    *         description="ID of the subnet to delete",
    *         required=true,
    *         @OA\Schema(type="integer")
    *     ),
    *     @OA\Response(
    *         response=200,
    *         description="Subnet deleted successfully",
    *         @OA\JsonContent(
    *             type="object",
    *             @OA\Property(property="success", type="string", example="Subred eliminada correctamente")
    *         )
    *     ),
    *     @OA\Response(
    *         response=400,
    *         description="Error occurred while deleting the subnet",
    *         @OA\JsonContent(
    *             oneOf={
    *                 @OA\Schema(
    *                     @OA\Property(property="error", type="string", example="No hay subredes definidas")
    *                 ),
    *                 @OA\Schema(
    *                     @OA\Property(property="error", type="string", example="Error configuracion de kea invalido")
    *                 ),
    *                 @OA\Schema(
    *                     @OA\Property(property="error", type="string", example="Error al guardar la configuración en Kea DHCP")
    *                 ),
    *                 @OA\Schema(
    *                     @OA\Property(property="error", type="string", example="Error al escribir en la configuración en Kea DHCP")
    *                 )
    *             }
    *         ),
    *         @OA\Examples(
    *             example="noSubnets",
    *             summary="Subnet name already exists",
    *             value={"error": "No hay subredes definidas"}
    *         ),
    *         @OA\Examples(
    *             example="invalidKea",
    *             summary="Error in config-test in kea",
    *             value={"error": "Error configuracion de kea invalido"}
    *         ),
    *         @OA\Examples(
    *             example="saveKea",
    *             summary="Error in config-set in kea",
    *             value={"error": "Error al guardar la configuración en Kea DHCP"}
    *         ),
    *         @OA\Examples(
    *             example="writeKea",
    *             summary="Error in config-write in kea",
    *             value={"error": "Error al escribir en la configuración en Kea DHCP"}
    *         )
    *     ),
    *     @OA\Response(
    *         response=404,
    *         description="Subnet not found",
    *         @OA\JsonContent(
    *             type="object",
    *             @OA\Property(property="error", type="string", example="La subred con el id '2' no existe")
    *         )
    *     ),
    *     @OA\Response(
    *         response=500,
    *         description="Error saving configuration in Kea DHCP",
    *         @OA\JsonContent(
    *             type="object",
    *             @OA\Property(property="error", type="string", example="Error al obtener la configuración de Kea DHCP")
    *         )
    *     )
    * )
    * @Route("/ogdhcp/v1/subnets/{subnetId}", methods={"DELETE"})
    */


    public function deleteDhcpSubnet(Request $request): JsonResponse
    {
        $subnetId = (int) $request->get('subnetId');

        try {
            $response = $this->curlKeaService->executeCurlCommand('config-get');

            if (!isset($response[0]['arguments']['Dhcp4']['subnet4'])) {
                $responseError =  "No hay subredes definidas";
                return new JsonResponse(['error' => $responseError], 400);
            }

            $subnetIndex = array_search($subnetId, array_column($response[0]['arguments']['Dhcp4']['subnet4'], 'id'));

            if ($subnetIndex === false) {
                $responseError =  "La subred con el id '$subnetId' no existe";
                return new JsonResponse(['error' => $responseError], 404);
            } else {
                //Borramos la subred con ese id 
                unset($response[0]['arguments']['Dhcp4']['subnet4'][$subnetIndex]);
                // Eliminar el campo 'hash' si existe
                if (isset($response[0]['arguments']['hash'])) {
                    unset($response[0]['arguments']['hash']);
                }
                $response[0]['arguments']['Dhcp4']['subnet4'] = array_values($response[0]['arguments']['Dhcp4']['subnet4']);
                $array_encoded = json_encode($response[0]['arguments']);
                $configurationParsed = str_replace('\\', '', $array_encoded);
                $configuration = json_decode($configurationParsed);
                $responseTest = $this->curlKeaService->executeCurlCommand('config-test', $configuration);

                if ($responseTest[0]["result"] == 0) {
                    $responseSet = $this->curlKeaService->executeCurlCommand('config-set', $configuration);
                    if ($responseSet == false || $responseSet[0]["result"] != 0) {
                        $responseError =  "Error al guardar la configuración en Kea DHCP: " . $responseSet[0]["text"];
                        return new JsonResponse(['error' => $responseError], 400);
                    } else {
                        $responseWrite = $this->curlKeaService->executeCurlCommand('config-write', $configuration);
                        if ($responseWrite == false || $responseWrite[0]["result"] != 0) {
                            $responseError =  "Error al escribir en la configuración en Kea DHCP: " . $responseWrite[0]["text"];
                            return new JsonResponse(['error' => $responseError], 400);
                        } else {
                            $responseSuccess =  "Subred eliminada correctamente";
                            return new JsonResponse(['success' => $responseSuccess], 200);
                        }
                    }
                } else {
                    $responseError =  "Error configuracion de kea invalido: " . $responseTest[0]["text"];
                    return new JsonResponse(['error' => $responseError], 400);
                }
            }
        } catch (Exception $e) {
            $responseError =  "Error al obtener la configuración de Kea DHCP: " . $e->getMessage();
            return new JsonResponse(['error' => $responseError], 500);
        }
    }

/**
 * @Route("/ogdhcp/v1/subnets/{subnetId}", methods={"PUT"})
 * @OA\Put(
 *     path="/ogdhcp/v1/subnets/{subnetId}",
 *     summary="Modify a DHCP subnet",
 *     @OA\Parameter(
 *         name="subnetId",
 *         in="path",
 *         description="ID of the subnet to modify",
 *         required=true,
 *         @OA\Schema(type="integer")
 *     ),
 *     @OA\RequestBody(
 *         description="Data to modify the subnet",
 *         required=true,
 *         @OA\JsonContent(
 *             type="object",
 *             @OA\Property(property="mask", type="string"),
 *             @OA\Property(property="address", type="string"),
 *             @OA\Property(property="router", type="string", example="192.168.1.254"),
 *             @OA\Property(property="nextServer", type="string"),
 *             @OA\Property(property="bootFileName", type="string")
 *         )
 *     ),
 *     @OA\Response(
 *         response=200,
 *         description="Subnet modified successfully",
 *         @OA\JsonContent(
 *             type="object",
 *             @OA\Property(property="success", type="string")
 *         )
 *     ),
 *     @OA\Response(
 *         response=400,
 *         description="Error occurred while modifying the subnet",
 *         @OA\JsonContent(
 *             oneOf={
 *                 @OA\Schema(@OA\Property(property="error", type="string", example="Falta un parámetro requerido: $paramFaltante")),
 *                 @OA\Schema(@OA\Property(property="error", type="string", example="No hay subredes definidas")),
 *                 @OA\Schema(@OA\Property(property="error", type="string", example="Error configuración de Kea inválido")),
 *                 @OA\Schema(@OA\Property(property="error", type="string", example="Error al guardar la configuración en Kea DHCP")),
 *                 @OA\Schema(@OA\Property(property="error", type="string", example="Error al escribir en la configuración en Kea DHCP"))
 *             }
 *         )
 *     ),
 *     @OA\Response(
 *         response=404,
 *         description="Subnet not found",
 *         @OA\JsonContent(type="object", @OA\Property(property="error", type="string", example="La subred con el id '2' no existe"))
 *     ),
 *     @OA\Response(
 *         response=500,
 *         description="Error saving configuration in Kea DHCP",
 *         @OA\JsonContent(type="object", @OA\Property(property="error", type="string", example="Error al obtener la configuración de Kea DHCP"))
 *     )
 * )
 */
public function modifyDhcpSubnet(Request $request): JsonResponse
{
    $subnetId = (int) $request->get('subnetId');

    try {
        $input = json_decode($request->getContent());
        $mask = htmlspecialchars($input->mask);
        $address = htmlspecialchars($input->address);

        // Verificar si next-server, boot-file-name y router están presentes
        $nextServer = isset($input->nextServer) ? htmlspecialchars($input->nextServer) : null;
        $bootFileName = isset($input->bootFileName) ? htmlspecialchars($input->bootFileName) : null;
        $router = isset($input->router) ? htmlspecialchars($input->router) : null;

        // Calcular el gateway añadiendo .1 al final de la subred si no se proporciona el router
        $gateway = $router ?: preg_replace('/\d+$/', '1', $address);
    } catch (Exception $e) {
        if (strpos($e->getMessage(), 'Undefined property') !== false) {
            preg_match('/Undefined property: stdClass::\$(\w+)/', $e->getMessage(), $matches);
            $paramFaltante = $matches[1] ?? 'desconocido';
            return new JsonResponse(['error' => "Falta un parámetro requerido: $paramFaltante"], 400);
        }
        return new JsonResponse(['error' => $e->getMessage()], 400);
    }

    try {
        $response = $this->curlKeaService->executeCurlCommand('config-get');
        $subnetName = $address . '/' . $this->curlKeaService->convertMaskToCIDR($mask);

        if (!isset($response[0]['arguments']['Dhcp4']['subnet4'])) {
            return new JsonResponse(['error' => "No hay subredes definidas"], 400);
        }

        $subnetIndex = array_search($subnetId, array_column($response[0]['arguments']['Dhcp4']['subnet4'], 'id'));

        if ($subnetIndex === false) {
            return new JsonResponse(['error' => "La subred con el id '$subnetId' no existe"], 400);
        } else {
            // Obtener la subred actual para mantener las reservas existentes
            $existingSubnet = $response[0]['arguments']['Dhcp4']['subnet4'][$subnetIndex];

            // Modificar la subred existente
            $newSubnet = [
                "id" => $subnetId,
                "subnet" => $subnetName,
                "reservations" => $existingSubnet['reservations'], // Mantener las reservas existentes
                "option-data" => [
                    [
                        "name" => "routers",
                        "code" => 3,
                        "data" => $gateway
                    ]
                ]
            ];

            // Añadir next-server si está presente, o eliminarlo de las reservas si no está
            if ($nextServer) {
                $newSubnet["next-server"] = $nextServer;
            } else {
                foreach ($newSubnet['reservations'] as &$reservation) {
                    unset($reservation['next-server']);
                }
            }

            // Añadir boot-file-name si está presente, o eliminarlo de las reservas si no está
            if ($bootFileName) {
                $newSubnet["boot-file-name"] = $bootFileName;
            } else {
                foreach ($newSubnet['reservations'] as &$reservation) {
                    unset($reservation['boot-file-name']);
                }
            }

            // Actualizar las reservas con los nuevos valores de next-server y boot-file-name
            foreach ($newSubnet['reservations'] as &$reservation) {
                if ($nextServer) {
                    $reservation['next-server'] = $nextServer;
                }
                if ($bootFileName) {
                    $reservation['boot-file-name'] = $bootFileName;
                }
            }

            // Reemplazar la subred en la configuración
            $response[0]['arguments']['Dhcp4']['subnet4'][$subnetIndex] = $newSubnet;

            // Eliminar el campo 'hash' si existe
            if (isset($response[0]['arguments']['hash'])) {
                unset($response[0]['arguments']['hash']);
            }

            $array_encoded = json_encode($response[0]['arguments']);
            $configurationParsed = str_replace('\\', '', $array_encoded);
            $configuration = json_decode($configurationParsed);

            $responseTest = $this->curlKeaService->executeCurlCommand('config-test', $configuration);

            if ($responseTest[0]["result"] == 0) {
                $responseSet = $this->curlKeaService->executeCurlCommand('config-set', $configuration);
                if ($responseSet == false || $responseSet[0]["result"] != 0) {
                    return new JsonResponse(['error' => "Error al guardar la configuración en Kea DHCP: " . $responseSet[0]["text"]], 400);
                } else {
                    $responseWrite = $this->curlKeaService->executeCurlCommand('config-write', $configuration);
                    if ($responseWrite == false || $responseWrite[0]["result"] != 0) {
                        return new JsonResponse(['error' => "Error al escribir en la configuración en Kea DHCP: " . $responseWrite[0]["text"]], 400);
                    } else {
                        // Volvemos a consultar la configuración para devolver la subred modificada
                        $updatedResponse = $this->curlKeaService->executeCurlCommand('config-get');
                        $updatedSubnet = array_filter($updatedResponse[0]['arguments']['Dhcp4']['subnet4'], function ($subnet) use ($subnetId) {
                            return $subnet['id'] == $subnetId;
                        });

                        return new JsonResponse(['success' => "Subred modificada correctamente", 'message' => reset($updatedSubnet)], 200);
                    }
                }
            } else {
                return new JsonResponse(['error' => "Error configuración de Kea inválida: " . $responseTest[0]["text"]], 400);
            }
        }
    } catch (Exception $e) {
        return new JsonResponse(['error' => "Error al obtener la configuración de Kea DHCP: " . $e->getMessage()], 500);
    }
}



   
/**
 * @OA\Get(
 *     path="/ogdhcp/v1/subnets/{subnetId}/hosts",
 *     summary="Get all hosts in a subnet",
 *     @OA\Parameter(
 *         name="subnetId",
 *         in="path",
 *         description="The ID of the subnet",
 *         required=true,
 *         @OA\Schema(type="integer")
 *     ),
 *     @OA\Response(
 *         response=200,
 *         description="List of hosts in the subnet",
 *         @OA\JsonContent(
 *             type="object",
 *             @OA\Property(property="success", type="string", example="Hosts obtenidos correctamente"),
 *             @OA\Property(property="message", type="array",
 *                 @OA\Items(ref="#/components/schemas/Host")
 *             )
 *         )
 *     ),
 *     @OA\Response(
 *         response=400,
 *         description="Error occurred",
 *         @OA\JsonContent(
 *             type="object",
 *             @OA\Property(property="error", type="string", example="Error: La subred con el id 'subnetId' no existe.")
 *         )
 *     ),
 *     @OA\Response(
 *         response=500,
 *         description="Server error when loading Kea DHCP configuration",
 *         @OA\JsonContent(
 *             type="object",
 *             @OA\Property(property="error", type="string", example="Error al obtener la configuración de Kea DHCP")
 *         )
 *     )
 * )
 * @Route("/ogdhcp/v1/subnets/{subnetId}/hosts", methods={"GET"})
 */
public function getHosts($subnetId): JsonResponse
{
    try {
        $response = $this->curlKeaService->executeCurlCommand('config-get');

        if (!$response) {
            $responseError =  "Error: No hay subredes definidas";
            return new JsonResponse(['error' => $responseError], 400);        
        }

        $result_code = $response[0]["result"];
        if ($result_code == 0) {
            if (!isset($response[0]['arguments']['Dhcp4']['subnet4'])) {
                throw new \Exception('Error: El campo \'subnet4\' no está inicializado.');
            }

            $subnets = $response[0]['arguments']['Dhcp4']['subnet4'];
            foreach ($subnets as $subnet) {
                if ($subnet['id'] == $subnetId) {
                    return new JsonResponse([
                        'success' => 'Hosts obtenidos correctamente correctamente',
                        'message' => $subnet['reservations']
                    ], 200);
                }
            }

            return new JsonResponse(['error' => 'Error: La subred con el id \'' . $subnetId . '\' no existe.'], 400);
        } else {
            $responseError =  "Error: No hay subredes definidas";
            return new JsonResponse(['error' => $responseError], 400);
        }
    } catch (\Exception $e) {
        $responseError =  "Error al obtener la configuración de Kea DHCP: " . $e->getMessage();
        return new JsonResponse(['error' => $responseError], 500);
    }
}


/**
 * @OA\Post(
 *     path="/ogdhcp/v1/subnets/{subnetId}/hosts",
 *     summary="Add a DHCP host to a subnet",
 *     @OA\Parameter(
 *         name="subnetId",
 *         in="path",
 *         description="ID of the subnet to add the host to",
 *         required=true,
 *         @OA\Schema(
 *             type="integer"
 *         )
 *     ),
 *     @OA\RequestBody(
 *         description="Data for the new host",
 *         required=true,
 *         @OA\JsonContent(
 *             type="object",
 *             @OA\Property(property="host", type="string", example="pc11"),
 *             @OA\Property(property="macAddress", type="string", example="56:6f:c7:4f:00:4f"),
 *             @OA\Property(property="address", type="string", example="172.30.4.11")
 *         )
 *     ),
 *     @OA\Response(
 *         response=200,
 *         description="Host added successfully and returns the new host details",
 *         @OA\JsonContent(
 *             type="object",
 *             @OA\Property(property="success", type="string", example="Host added successfully"),
 *             @OA\Property(property="message", ref="#/components/schemas/Host")
 *         )
 *     ),
 *     @OA\Response(
 *         response=400,
 *         description="Error occurred while adding the host",
 *         @OA\JsonContent(
 *             oneOf={
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="No hay subredes definidas")
 *                 ),
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="El host con el hostname 'host' ya existe en las reservaciones.")
 *                 ),
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="Error configuracion de kea invalido")
 *                 ),
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="Error al guardar la configuración en Kea DHCP")
 *                 ),
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="Error al escribir en la configuración en Kea DHCP")
 *                 ),
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="No se pudo encontrar el host recién creado")
 *                 ),
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="Falta un parámetro requerido: $paramFaltante")
 *                 )
 *             }
 *         ),
 *         @OA\Examples(
 *             example="parameterMissing",
 *             summary="Missing required parameter",
 *             value={"error": "Falta un parámetro requerido: $paramFaltante"}
 *         ),
 *         @OA\Examples(
 *             example="noSubnet",
 *             summary="No subnets initialized",
 *             value={"error": "No se encontró la subnet con id '$subnetId'"}
 *         ),
 *         @OA\Examples(
 *             example="hostExists",
 *             summary="Host already exists",
 *             value={"error": "El host con el hostname '$host' ya existe en las reservaciones."}
 *         ),
 *         @OA\Examples(
 *             example="invalidKea",
 *             summary="Error in config-test in kea",
 *             value={"error": "Error configuracion de kea invalido"}
 *         ),
 *         @OA\Examples(
 *             example="saveKea",
 *             summary="Error in config-set in kea",
 *             value={"error": "Error al guardar la configuración en Kea DHCP"}
 *         ),
 *         @OA\Examples(
 *             example="writeKea",
 *             summary="Error in config-write in kea",
 *             value={"error": "Error al escribir en la configuración en Kea DHCP"}
 *         ),
 *         @OA\Examples(
 *             example="notFound",
 *             summary="Host created not found",
 *             value={"error": "No se pudo encontrar el host recién creado"}
 *         )
 *     )
 * )
 * @Route("/ogdhcp/v1/subnets/{subnetId}/hosts", methods={"POST"})
 */
public function addDhcpHost(Request $request, $subnetId): JsonResponse
{
    try {
        $input = json_decode($request->getContent());
        $host = htmlspecialchars($input->host);
        $macAddress = htmlspecialchars($input->macAddress);
        $address = htmlspecialchars($input->address);
    } catch (Exception $e) {
        $response["message"] = $e->getMessage();
        if (strpos($e->getMessage(), 'Undefined property') !== false) {
            preg_match('/Undefined property: stdClass::\$(\w+)/', $e->getMessage(), $matches);
            $paramFaltante = $matches[1] ?? 'desconocido';
            return new JsonResponse(['error' => "Falta un parámetro requerido: $paramFaltante"], 400);
        }
    }

    try {
        $response = $this->curlKeaService->executeCurlCommand('config-get');
        $newHost = [
            "hostname" => $host,
            "hw-address" => $macAddress,
            "ip-address" => $address
        ];

        $subnetFound = false;

        foreach ($response[0]['arguments']['Dhcp4']['subnet4'] as &$subnet) {
            if ($subnet['id'] == $subnetId) {
                $subnetFound = true;

                // Añadir boot-file-name y next-server de la subred si están definidos
                if (isset($subnet['boot-file-name'])) {
                    $newHost['boot-file-name'] = $subnet['boot-file-name'];
                }
                if (isset($subnet['next-server'])) {
                    $newHost['next-server'] = $subnet['next-server'];
                }

                if (!isset($subnet['reservations'])) {
                    $subnet['reservations'] = [];
                }

                $exists = array_reduce($subnet['reservations'], function ($exists, $reservation) use ($host) {
                    return $exists || ($reservation['hostname'] === $host);
                });

                if ($exists) {
                    return new JsonResponse(['error' => "Error: El host con el hostname '$host' ya existe en las reservaciones."], 400);
                } else {
                    $subnet['reservations'][] = $newHost;
                    break;
                }
            }
        }

        if (!$subnetFound) {
            return new JsonResponse(['error' => "Error: No se encontró la subnet con id '$subnetId'."], 400);
        }

        // Eliminar el campo 'hash' si existe
        if (isset($response[0]['arguments']['hash'])) {
            unset($response[0]['arguments']['hash']);
        }

        $array_encoded = json_encode($response[0]['arguments']);
        $configurationParsed = str_replace('\\', '', $array_encoded);
        $configuration = json_decode($configurationParsed);
        $responseTest = $this->curlKeaService->executeCurlCommand('config-test', $configuration);

        if ($responseTest[0]["result"] == 0) {
            $responseSet = $this->curlKeaService->executeCurlCommand('config-set', $configuration);
            if ($responseSet == false || $responseSet[0]["result"] != 0) {
                return new JsonResponse(['error' => "Error al guardar la configuración en Kea DHCP: " . $responseSet[0]["text"]], 400);
            } else {
                $responseWrite = $this->curlKeaService->executeCurlCommand('config-write', $configuration);
                if ($responseWrite == false || $responseWrite[0]["result"] != 0) {
                    return new JsonResponse(['error' => "Error al escribir en la configuración en Kea DHCP: " . $responseWrite[0]["text"]], 400);
                } else {
                    // Ahora volvemos a consultar el host recién creado
                    $updatedResponse = $this->curlKeaService->executeCurlCommand('config-get');
                    $createdHost = null;

                    foreach ($updatedResponse[0]['arguments']['Dhcp4']['subnet4'] as $subnet) {
                        if ($subnet['id'] == $subnetId) {
                            foreach ($subnet['reservations'] as $reservation) {
                                if ($reservation['hw-address'] === $macAddress) {
                                    $createdHost = $reservation;
                                    break;
                                }
                            }
                        }
                    }
                    if ($createdHost) {
                        return new JsonResponse(['success' => "Host agregado correctamente", 'message' => $createdHost], 200);
                    } else {
                        return new JsonResponse(['error' => "No se pudo encontrar el host recién creado"], 400);
                    }
                }
            }
        } else {
            return new JsonResponse(['error' => "Error kea configuration invalid: " . $responseTest[0]["text"]], 400);
        }
    } catch (Exception $e) {
        $responseError =  "Error al obtener la configuración de Kea DHCP: " . $e->getMessage();
        return new JsonResponse(['error' => $responseError], 500);
    }
}



/**
 * @OA\Delete(
 *     path="/ogdhcp/v1/subnets/{subnetId}/hosts",
 *     summary="Delete a DHCP host from a specific subnet",
 *     @OA\Parameter(
 *         name="subnetId",
 *         in="path",
 *         description="The ID of the subnet",
 *         required=true,
 *         @OA\Schema(type="integer")
 *     ),
 *     @OA\RequestBody(
 *         description="Data for the host to delete",
 *         required=true,
 *         @OA\JsonContent(
 *             type="object",
 *             @OA\Property(property="macAddress", type="string", example="56:6f:c7:4f:00:4f")
 *         )
 *     ),
 *     @OA\Response(
 *         response=200,
 *         description="Host deleted successfully",
 *         @OA\JsonContent(
 *             type="object",
 *             @OA\Property(property="success", type="string")
 *         )
 *     ),
 *     @OA\Response(
 *         response=404,
 *         description="Host or subnet not found",
 *         @OA\JsonContent(
 *             type="object",
 *             @OA\Property(property="error", type="string")
 *         )
 *     ),
 *     @OA\Response(
 *         response=400,
 *         description="Error occurred while adding the host",
 *         @OA\JsonContent(
 *             oneOf={
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="No se encontró la subnet con id '$subnetId'")
 *                 ),
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="El host con la MAC '$mac' no existe en las reservaciones")
 *                 ),
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="Error configuracion de kea invalido")
 *                 ),
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="Error al guardar la configuración en Kea DHCP")
 *                 ),
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="Error al escribir en la configuración en Kea DHCP")
 *                 )
 *             }
 *         ),
 *         @OA\Examples(
 *             example="noSubnet",
 *             summary="No subnets initialized",
 *             value={"error": "No se encontró la subnet con id '$subnetId'"}
 *         ),
 *         @OA\Examples(
 *             example="hostNotFound",
 *             summary="Host not found",
 *             value={"error": "El host con la MAC '$mac' no existe en las reservaciones"}
 *         ),
 *         @OA\Examples(
 *             example="invalidKea",
 *             summary="Error in config-test in kea",
 *             value={"error": "Error configuracion de kea invalido"}
 *         ),
 *         @OA\Examples(
 *             example="saveKea",
 *             summary="Error in config-set in kea",
 *             value={"error": "Error al guardar la configuración en Kea DHCP"}
 *         ),
 *         @OA\Examples(
 *             example="writeKea",
 *             summary="Error in config-write in kea",
 *             value={"error": "Error al escribir en la configuración en Kea DHCP"}
 *         )
 *     )
 * )
 * @Route("/ogdhcp/v1/subnets/{subnetId}/hosts", methods={"DELETE"})
 */
public function deleteDhcpHost(Request $request, $subnetId): JsonResponse
{
    try {
        $input = json_decode($request->getContent());
        $macAddress = htmlspecialchars($input->macAddress);
    } catch (Exception $e) {
        return new JsonResponse(['error' => $e->getMessage()], 400);
    }

    try {
        $response = $this->curlKeaService->executeCurlCommand('config-get');
        $subnetFound = false;
        $hostFound = false;

        foreach ($response[0]['arguments']['Dhcp4']['subnet4'] as &$subnet) {
            if ($subnet['id'] == $subnetId) {
                $subnetFound = true;
                if (!isset($subnet['reservations'])) {
                    $subnet['reservations'] = [];
                }

                foreach ($subnet['reservations'] as $key => $reservation) {
                    if ($reservation['hw-address'] === $macAddress) {
                        unset($subnet['reservations'][$key]);
                        $subnet['reservations'] = array_values($subnet['reservations']);
                        $hostFound = true;
                        break;
                    }
                }
            }
        }

        if (!$subnetFound) {
            return new JsonResponse(['error' => "No se encontró la subnet con id '$subnetId'"], 400);
        }

        if (!$hostFound) {
            return new JsonResponse(['error' => "El host con la MAC '$macAddress' no existe en las reservaciones"], 400);
        }

        // Eliminar el campo 'hash' si existe
        if (isset($response[0]['arguments']['hash'])) {
            unset($response[0]['arguments']['hash']);
        }

        $array_encoded = json_encode($response[0]['arguments']);
        $configurationParsed = str_replace('\\', '', $array_encoded);
        $configuration = json_decode($configurationParsed);

        $responseTest = $this->curlKeaService->executeCurlCommand('config-test', $configuration);
        if ($responseTest[0]["result"] == 0) {
            $responseSet = $this->curlKeaService->executeCurlCommand('config-set', $configuration);
            if ($responseSet == false || $responseSet[0]["result"] != 0) {
                return new JsonResponse(['error' => "Error al guardar la configuración en Kea DHCP: " . $responseSet[0]["text"]], 400);
            } else {
                $responseWrite = $this->curlKeaService->executeCurlCommand('config-write', $configuration);
                if ($responseWrite == false || $responseWrite[0]["result"] != 0) {
                    return new JsonResponse(['error' => "Error al escribir en la configuración en Kea DHCP: " . $responseWrite[0]["text"]], 400);
                } else {
                    return new JsonResponse(['success' => "Host eliminado correctamente"], 200);
                }
            }
        } else {
            return new JsonResponse(['error' => "Error configuracion de kea invalido: " . $responseTest[0]["text"]], 400);
        }
    } catch (Exception $e) {
        $responseError =  "Error al obtener la configuración de Kea DHCP: " . $e->getMessage();
        return new JsonResponse(['error' => $responseError], 500);
    }
}


/**
 * @OA\Put(
 *     path="/ogdhcp/v1/subnets/{subnetId}/hosts",
 *     summary="Update a DHCP host",
 *     @OA\Parameter(
 *         name="subnetId",
 *         in="path",
 *         description="The ID of the subnet",
 *         required=true,
 *         @OA\Schema(type="integer")
 *     ),
 *     @OA\RequestBody(
 *         description="Data for the host to update",
 *         required=true,
 *         @OA\JsonContent(
 *             type="object",
 *             @OA\Property(property="oldMacAddress", type="string", example="56:6f:c7:4f:00:4f", description="Old MAC address of the host to update"),
 *             @OA\Property(property="macAddress", type="string", example="56:6f:c7:4f:01:01", description="New MAC address"),
 *             @OA\Property(property="address", type="string", example="192.168.1.11", description="New IP address"),
 *             @OA\Property(property="hostname", type="string", example="PC11", description="New or existing hostname")
 *         )
 *     ),
 *     @OA\Response(
 *         response=200,
 *         description="Host updated successfully",
 *         @OA\JsonContent(
 *             type="object",
 *             @OA\Property(property="success", type="string", example="Host updated successfully"),
 *             @OA\Property(property="message", ref="#/components/schemas/Host")
 *         )
 *     ),
 *     @OA\Response(
 *         response=400,
 *         description="Error occurred while updating the host",
 *         @OA\JsonContent(
 *             oneOf={
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="No se encontró la subnet con id '$subnetId'")
 *                 ),
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="El host con la MAC '$oldMacAddress' no existe en las reservaciones")
 *                 ),
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="Error configuración de kea inválida")
 *                 ),
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="Error al guardar la configuración en Kea DHCP")
 *                 ),
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="Error al escribir la configuración en Kea DHCP")
 *                 ),
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="Falta un parámetro requerido: $paramFaltante")
 *                 )
 *             }
 *         )
 *     ),
 *     @OA\Response(
 *         response=500,
 *         description="Server error",
 *         @OA\JsonContent(
 *             type="object",
 *             @OA\Property(property="error", type="string", example="Internal server error")
 *         )
 *     )
 * )
 * @Route("/ogdhcp/v1/subnets/{subnetId}/hosts", methods={"PUT"})
 */
public function updateDhcpHost(Request $request, $subnetId): JsonResponse
{
    try {
        $input = json_decode($request->getContent());
        $host = htmlspecialchars($input->hostname);
        $oldMacAddress = htmlspecialchars($input->oldMacAddress);
        $macAddress = htmlspecialchars($input->macAddress);
        $address = htmlspecialchars($input->address);
    } catch (Exception $e) {
        $response["message"] = $e->getMessage();
        if (strpos($e->getMessage(), 'Undefined property') !== false) {
            preg_match('/Undefined property: stdClass::\$(\w+)/', $e->getMessage(), $matches);
            $paramFaltante = $matches[1] ?? 'desconocido';
            return new JsonResponse(['error' => "Falta un parámetro requerido: $paramFaltante"], 400);
        }
    }

    try {
        // Ejecutar el comando para obtener la configuración actual
        $response = $this->curlKeaService->executeCurlCommand('config-get');
        $subnetFound = false;
        $hostFound = false;
        $updatedHost = null;

        foreach ($response[0]['arguments']['Dhcp4']['subnet4'] as &$subnet) {
            if ($subnet['id'] == $subnetId) {
                $subnetFound = true;
                if (!isset($subnet['reservations'])) {
                    $subnet['reservations'] = [];
                }

                foreach ($subnet['reservations'] as &$reservation) {
                    if ($reservation['hw-address'] == $oldMacAddress) {
                        $hostFound = true;

                        // Conservar boot-file-name y next-server si existen en el host original
                        $bootFileName = $reservation['boot-file-name'] ?? $subnet['boot-file-name'] ?? null;
                        $nextServer = $reservation['next-server'] ?? $subnet['next-server'] ?? null;

                        // Actualizar los valores del host
                        $reservation['hw-address'] = $macAddress;
                        $reservation['ip-address'] = $address;
                        $reservation['hostname'] = $host;

                        // Restaurar boot-file-name y next-server si estaban definidos
                        if ($bootFileName !== null) {
                            $reservation['boot-file-name'] = $bootFileName;
                        }
                        if ($nextServer !== null) {
                            $reservation['next-server'] = $nextServer;
                        }

                        $updatedHost = $reservation;
                        break;
                    }
                }
            }
        }

        if ($subnetFound && $hostFound) {
            // Eliminar el campo 'hash' si existe
            if (isset($response[0]['arguments']['hash'])) {
                unset($response[0]['arguments']['hash']);
            }

            // Preparar la configuración modificada
            $array_encoded = json_encode($response[0]['arguments']);
            $configurationParsed = str_replace('\\', '', $array_encoded);
            $configuration = json_decode($configurationParsed);

            // Test de la configuración
            $responseTest = $this->curlKeaService->executeCurlCommand('config-test', $configuration);
            if ($responseTest[0]["result"] == 0) {
                // Guardar la configuración
                $responseSet = $this->curlKeaService->executeCurlCommand('config-set', $configuration);
                if ($responseSet == false || $responseSet[0]["result"] != 0) {
                    return new JsonResponse(['error' => "Error al guardar la configuración en Kea DHCP: " . $responseSet[0]["text"]], 400);
                } else {
                    // Escribir la configuración en disco
                    $responseWrite = $this->curlKeaService->executeCurlCommand('config-write', $configuration);
                    if ($responseWrite == false || $responseWrite[0]["result"] != 0) {
                        return new JsonResponse(['error' => "Error al escribir la configuración en Kea DHCP: " . $responseWrite[0]["text"]], 400);
                    } else {
                        // Devolver el host actualizado
                        return new JsonResponse(['success' => "Host actualizado correctamente", 'message' => $updatedHost], 200);
                    }
                }
            } else {
                return new JsonResponse(['error' => "Error en la configuración de Kea: " . $responseTest[0]["text"]], 400);
            }
        } elseif (!$subnetFound) {
            return new JsonResponse(['error' => "Error: La subred con el id '$subnetId' no existe."], 400);
        } elseif (!$hostFound) {
            return new JsonResponse(['error' => "Error: El host con la MAC '$oldMacAddress' no existe en las reservaciones."], 400);
        }
    } catch (Exception $e) {
        return new JsonResponse(['error' => "Error al obtener la configuración de Kea DHCP: " . $e->getMessage()], 500);
    }
}

/**
 * @OA\Get(
 *     path="/ogdhcp/v1/backup",
 *     summary="Get the latest backup configuration of Kea DHCP (only subnet4)",
 *     @OA\Response(
 *         response=200,
 *         description="Latest backup configuration of Kea DHCP",
 *         @OA\JsonContent(
 *             type="object",
 *             @OA\Property(property="success", type="string", example="Backup obtenido con exito"),
 *             @OA\Property(property="message", type="array",
 *                 @OA\Items(ref="#/components/schemas/Host")
 *             )
 *         )
 *     ),
 *     @OA\Response(
 *         response=400,
 *         description="Error occurred while retrieving the backup",
 *         @OA\JsonContent(
 *             type="object",
 *             @OA\Property(property="error", type="string", example="No se encontraron archivos de backup")
 *         )
 *     )
 * )
 * @Route("/ogdhcp/v1/backup", methods={"GET"})
 */
public function getLatestBackupConfiguration(): JsonResponse
{
    #$backup_dir = '/opt/ogdhcp/etc/kea/backup';
    $backup_dir = $this->backup_dir;
    try {
        // Obtener los archivos de backup
        $backup_files = glob($backup_dir . '/*.conf');
        if (empty($backup_files)) {
            $responseError = "No se encontraron archivos de backup";
            return new JsonResponse(['error' => $responseError], 400);
        }

        // Ordenar por fecha de modificación y obtener el más reciente
        usort($backup_files, function ($a, $b) {
            return filemtime($b) - filemtime($a);
        });

        // Leer el archivo más reciente
        $backup_file = reset($backup_files);
        $config = file_get_contents($backup_file);
        $configuration = json_decode($config, true);

        if (!isset($configuration['Dhcp4']['subnet4'])) {
            $responseError = "No se encontró el parámetro 'subnet4' en el backup";
            return new JsonResponse(['error' => $responseError], 400);
        }

        $responseSuccess = "Backup obtenido con exito";
        return new JsonResponse(['success' => $responseSuccess, 'message' => ['subnet4' => $configuration['Dhcp4']['subnet4']]], 200);
    } catch (Exception $e) {
        $responseError = "Error al obtener la configuración de backup: " . $e->getMessage();
        return new JsonResponse(['error' => $responseError], 400);
    }
}

/**
 * @OA\Post(
 *     path="/ogdhcp/v1/backup",
 *     summary="Restore the latest DHCP configuration from backup",
 *     description="This endpoint restores the last saved DHCP configuration from a backup file and applies it to the Kea DHCP server, returning all currently loaded subnets.",
 *     @OA\Response(
 *         response=200,
 *         description="Configuration restored successfully",
 *         @OA\JsonContent(
 *             type="object",
 *             @OA\Property(property="success", type="string", example="Configuración cargada correctamente"),
 *             @OA\Property(property="message", type="array",
 *                 @OA\Items(ref="#/components/schemas/Host")
 *             )
 *         )
 *     ),
 *     @OA\Response(
 *         response=400,
 *         description="Error occurred while restoring the configuration",
 *         @OA\JsonContent(
 *             oneOf={
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="No se encontraron archivos de backup")
 *                 ),
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="Error configuracion de kea invalido")
 *                 ),
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="Error al guardar la configuración en Kea DHCP")
 *                 ),
 *                 @OA\Schema(
 *                     @OA\Property(property="error", type="string", example="Error al escribir en la configuración en Kea DHCP")
 *                 )
 *             }
 *         ),
 *         @OA\Examples(
 *             example="noBackup",
 *             summary="No backup files found",
 *             value={"error": "No se encontraron archivos de backup"}
 *         ),
 *         @OA\Examples(
 *             example="invalidKea",
 *             summary="Error in config-test in kea",
 *             value={"error": "Error configuracion de kea invalido"}
 *         ),
 *         @OA\Examples(
 *             example="saveKea",
 *             summary="Error in config-set in kea",
 *             value={"error": "Error al guardar la configuración en Kea DHCP"}
 *         ),
 *         @OA\Examples(
 *             example="writeKea",
 *             summary="Error in config-write in kea",
 *             value={"error": "Error al escribir en la configuración en Kea DHCP"}
 *         )
 *     )
 * )
 * @Route("/ogdhcp/v1/backup", methods={"POST"})
 */
public function restoreDhcpConfiguration(): JsonResponse
{
    #$backup_dir = '/opt/ogdhcp/etc/kea/backup';
    $backup_dir = $this->backup_dir;
    try {
        $backup_files = glob($backup_dir . '/*.conf');
        if (empty($backup_files)) {
            $response = "No se encontraron archivos de backup";
            return new JsonResponse(['error' => $response], 400);
        } else {
            usort($backup_files, function ($a, $b) {
                return filemtime($b) - filemtime($a);
            });
            $backup_file = reset($backup_files);
            $config = file_get_contents($backup_file);
            // Eliminar el campo 'hash' si existe
            $configuration = json_decode($config);
            if (isset($configuration->hash)) {
                unset($configuration->hash);
            }

            $test_command = 'config-test';
            $test_output = $this->curlKeaService->executeCurlCommand($test_command, $configuration);
            if ($test_output == false || $test_output[0]["result"] != 0) {
                $responseError = "Error al comprobar la configuración de Kea: " . $test_output[0]["text"];
                return new JsonResponse(['error' => $responseError], 400);
            } else {
                $set_command = 'config-set';
                $set_output = $this->curlKeaService->executeCurlCommand($set_command, $configuration, false);
                if ($set_output == false || $set_output[0]["result"] != 0) {
                    $responseError = "Error al guardar la última configuración de Kea: " . $set_output[0]["text"];
                    return new JsonResponse(['error' => $responseError], 400);
                } else {
                    unlink($backup_file);
                    $responseWrite = $this->curlKeaService->executeCurlCommand('config-write', $configuration);
                    if ($responseWrite == false || $responseWrite[0]["result"] != 0) {
                        $responseError = "Error al guardar la configuración en Kea DHCP: " . $responseWrite[0]["text"];
                        return new JsonResponse(['error' => $responseError], 400);
                    } else {
                        // Consultar las subredes cargadas
                        $config_get = $this->curlKeaService->executeCurlCommand('config-get');
                        if ($config_get == false || $config_get[0]["result"] != 0) {
                            return new JsonResponse(['error' => 'Error al obtener la configuración de Kea DHCP'], 500);
                        }

                        $subnets = $config_get[0]['arguments']['Dhcp4']['subnet4'] ?? [];
                        return new JsonResponse(['success' => "Configuración cargada correctamente", 'subnets' => $subnets], 200);
                    }
                }
            }
        }
    } catch (Exception $e) {
        $responseError = "Error al restaurar la configuración: " . $e->getMessage();
        return new JsonResponse(['error' => $responseError], 400);
    }
}



}

