<?php

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

namespace App\Controllers;

use App\Services\Ldap\LdapAuthService;

/**
 * Zuständig für alles rund um den Login:
 * - Login-Formular anzeigen
 * - Login-Daten verarbeiten (Authentifizierung gegen LDAP/AD)
 * - Logout durchführen
 */
class AuthController
{
    /** @var array<string, mixed> Konfigurationswerte der Anwendung (aus config.php) */
    private array $config;

    /** @var LdapAuthService Service, der die eigentliche LDAP/AD-Authentifizierung übernimmt */
    private LdapAuthService $ldapAuthService;

    /**
     * Übergibt die Konfiguration an den Controller und initialisiert den LDAP-Authentifizierungsservice.
     *
     * @param array<string, mixed> $config Vollständige Konfiguration aus config.php
     */
    public function __construct(array $config)
    {
        // Komplette Config in der Instanz speichern (z. B. für Zugriff auf security- oder ldap-Settings)
        $this->config = $config;

        // LdapAuthService mit dem Teilbereich "ldap" aus der Konfiguration initialisieren.
        // Wenn 'ldap' nicht gesetzt ist, wird ein leeres Array übergeben (Fail fast erfolgt dann im Service).
        $this->ldapAuthService = new LdapAuthService($config['ldap'] ?? []);
    }

    /**
     * Zeigt das Login-Formular an.
     * Optional kann eine Fehlermeldung übergeben werden, die in der View dargestellt wird.
     */
    public function showLoginForm(?string $errorMessage = null): void
    {
        // Pfad zur Login-View (Template-Datei) ermitteln.
        $viewPath = __DIR__ . '/../../public/views/login.php';

        // Variable für die View vorbereiten (wird in der eingebundenen Datei verwendet).
        $error = $errorMessage;

        // Falls die View-Datei (noch) nicht existiert, einen Fallback-HTML-Output verwenden.
        if (file_exists($viewPath) === false) {
            $this->renderInlineLogin($error);
            return;
        }

        // View-Datei einbinden. Variablen aus dieser Methode (z. B. $error) sind dort verfügbar.
        require $viewPath;
    }

    /**
     * Verarbeitet das Login-Formular:
     * - Liest Benutzername und Passwort aus $_POST
     * - Ruft den LdapAuthService zur Authentifizierung auf
     * - Setzt bei Erfolg die Session und leitet zum Dashboard weiter
     * - Zeigt bei Fehlern erneut das Login-Formular mit Fehlermeldung an
     */
    public function processLogin(): void
    {
        // Formulardaten aus dem POST-Request lesen.
        $username = trim($_POST['username'] ?? '');
        $password = (string)($_POST['password'] ?? '');

        try {
            // Versuch, den Benutzer per LDAP/AD zu authentifizieren.
            // true = Authentifizierung erfolgreich
            // false = Anmeldedaten fachlich ungültig (Benutzer/Passwort falsch)
            $authenticated = $this->ldapAuthService->authenticate($username, $password);
        } catch (\Throwable $exception) {
            // Technischer Fehler (z. B. LDAP-Server nicht erreichbar, falsche Konfiguration).
            // In diesem Fall wird eine technische Fehlermeldung im Login-Formular angezeigt.
            $this->showLoginForm('Technischer Fehler bei der Anmeldung: ' . $exception->getMessage());
            return;
        }

        // Fachlich fehlgeschlagene Anmeldung (z. B. falsches Passwort).
        if ($authenticated === false) {
            $this->showLoginForm('Benutzername oder Passwort ist ungültig.');
            return;
        }

        // Ab hier ist die Anmeldung erfolgreich.

        // Session-Key für den eingeloggten Benutzer aus der Konfiguration lesen.
        // Wenn nicht gesetzt, wird "admin_user" als Standard verwendet.
        $sessionKey = $this->config['security']['session_key_user'] ?? 'admin_user';

        // Benutzerinformationen in der Session hinterlegen.
        // Diese Daten werden später von requireLogin() ausgewertet.
        $_SESSION[$sessionKey] = [
                'username' => $username,
                'login_at' => date('c'), // ISO-8601 Datum/Zeit der Anmeldung
        ];

        // Nach erfolgreicher Anmeldung zum Dashboard weiterleiten.
        header('Location: index.php?route=dashboard');
        exit;
    }

    /**
     * Meldet den aktuell eingeloggten Benutzer ab, indem der entsprechende Session-Eintrag entfernt wird,
     * und leitet anschließend zurück auf die Login-Seite.
     */
    public function logout(): void
    {
        // Session-Key für den eingeloggten Benutzer aus der Konfiguration lesen.
        $sessionKey = $this->config['security']['session_key_user'] ?? 'admin_user';

        // Eintrag aus der Session entfernen → Benutzer gilt als ausgeloggt.
        unset($_SESSION[$sessionKey]);

        // Zur Login-Seite zurückleiten.
        header('Location: index.php?route=login');
        exit;
    }

    /**
     * Fallback-Ausgabe für das Login-Formular, falls noch keine separate View-Datei existiert.
     * Gibt direkt HTML aus (inline-Template).
     */
    private function renderInlineLogin(?string $errorMessage): void
    {
        ?>
        <!doctype html>
        <html lang="de">
        <head>
            <meta charset="utf-8">
            <title>AD Admin Tool – Login</title>
        </head>
        <body>
        <h1>AD Admin Tool – Login</h1>

        <?php if ($errorMessage !== null): ?>
            <!-- Fehlermeldung ausgeben, HTML-Ausgabe wird dabei sicher maskiert -->
            <p style="color: red;"><?php echo htmlspecialchars($errorMessage, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></p>
        <?php endif; ?>

        <!-- Einfaches Login-Formular, das per POST an die Route "login.submit" gesendet wird -->
        <form action="index.php?route=login.submit" method="post">
            <div>
                <label for="username">Benutzername:</label>
                <input type="text" id="username" name="username" required>
            </div>

            <div>
                <label for="password">Passwort:</label>
                <input type="password" id="password" name="password" required>
            </div>

            <button type="submit">Anmelden</button>
        </form>

        </body>
        </html>
        <?php
    }
}
