<?php

// Strenge Typprüfung für Parameter- und Rückgabetypen aktivieren.
declare(strict_types=1);

namespace App\Services\Ldap;

use RuntimeException;

/**
 * Hilfsklasse zum Aufbau einer LDAP/LDAPS-Verbindung.
 *
 * Aufgaben:
 * - liest Server, Port und Timeout aus der LDAP-Konfiguration
 * - erstellt eine LDAP-Verbindung
 * - setzt die notwendigen Optionen (Protokollversion, Netzwerk-Timeout)
 *
 * Wichtig:
 * - Diese Klasse führt KEIN ldap_bind durch.
 * - Das Bind (mit Benutzer- oder Service-Konto) erfolgt in den Fach-Services
 *   wie LdapAuthService oder LdapDirectoryService.
 */
class LdapConnectionHelper
{
    /** @var array<string, mixed> LDAP-spezifische Konfiguration (server, port, timeout, etc.) */
    private array $config;

    /**
     * @param array<string, mixed> $ldapConfig Teilbereich "ldap" aus der config.php
     */
    public function __construct(array $ldapConfig)
    {
        // LDAP-Konfiguration in der Instanz speichern.
        // Dadurch steht sie in allen Methoden dieser Klasse zur Verfügung.
        $this->config = $ldapConfig;
    }

    /**
     * Erstellt eine LDAP-Verbindung mit gesetzten Optionen (Protokollversion, Timeout),
     * aber ohne Bind. Den Bind führen die aufrufenden Services durch.
     *
     * @return resource LDAP-Verbindungs-Handle
     *
     * @throws RuntimeException wenn der Server nicht konfiguriert ist oder die Verbindung scheitert
     */
    public function createConnection()
    {
        // Server, Port und Timeout aus der Konfiguration lesen.
        // Die Null-Koaleszenz-Operatoren (??) setzen Standardwerte, falls Keys fehlen.
        $server  = (string)($this->config['server'] ?? '');
        $port    = (int)($this->config['port'] ?? 636);
        $timeout = (int)($this->config['timeout'] ?? 5);

        // Ohne Server-Adresse kann keine Verbindung aufgebaut werden.
        if ($server === '') {
            throw new RuntimeException('LDAP-Konfiguration ist unvollständig (server fehlt).');
        }

        // Verbindung zum LDAP/AD-Server herstellen.
        // ldap_connect liefert entweder ein Verbindungs-Handle (Resource) oder false.
        $uri = "ldap://".$server . ':' . $port;
        $connection = ldap_connect($uri);

        // Wenn keine Verbindung aufgebaut werden konnte, Exception werfen.
        if ($connection === false) {
            throw new RuntimeException('LDAP-Verbindung konnte nicht aufgebaut werden.');
        }

        // LDAP-Version auf 3 setzen, dies ist die gängige Standardversion.
        ldap_set_option($connection, LDAP_OPT_PROTOCOL_VERSION, 3);

        // Netzwerk-Timeout setzen, damit Anfragen nicht ewig hängen bleiben.
        ldap_set_option($connection, LDAP_OPT_NETWORK_TIMEOUT, $timeout);

        // Referral-Following deaktivieren (0 = aus).
        // Das verhindert, dass der Client automatisch zu anderen LDAP-Servern weitergeleitet wird.
        ldap_set_option($connection, LDAP_OPT_REFERRALS, 0);

        // Verbindungs-Handle an aufrufende Services zurückgeben.
        // Dort wird dann der eigentliche ldap_bind durchgeführt.
        return $connection;
    }
}
