<?php

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

namespace App\Controllers;

use App\Services\Ldap\LdapAuthService;
use App\Services\Logging\LoggingService;

/**
 * Zuständig für alles rund um den Login:
 * - Login-Formular anzeigen
 * - Login-Daten verarbeiten (Authentifizierung gegen LDAP/AD)
 * - Logout durchführen
 *
 * NEU:
 * - Statt direkt HTML auszugeben oder header()-Redirects zu setzen,
 *   liefert der Controller "View-Results" zurück, die von index.php
 *   und einem zentralen Layout verarbeitet werden.
 */
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;

    /** @var LoggingService Logger für technische Fehler */
    private LoggingService $logger;

    /**
     * Ü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'] ?? []);

        // LoggingService mit dem Teilbereich "logging" aus der Konfiguration initialisieren.
        $this->logger = new LoggingService($config['logging'] ?? []);
    }

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

        // Wichtig: Die View erwartet aktuell die Variable $error.
        return [
            'view' => $viewPath,
            'data' => [
                'error'     => $errorMessage,
                'loginPage' => true,
            ],
            'pageTitle'  => 'Login',
            // Beim Login ist typischerweise kein Menüpunkt aktiv.
            'activeMenu' => null,
        ];
    }

    /**
     * Verarbeitet das Login-Formular:
     * - Liest Benutzername und Passwort aus $_POST
     * - Ruft den LdapAuthService zur Authentifizierung auf
     * - Liefert bei Erfolg ein Redirect-Result zum Dashboard
     * - Liefert bei Fehlern ein View-Result für das Login-Formular mit Fehlermeldung
     *
     * @return array<string, mixed> View-Result ODER Redirect-Result
     */
    public function processLogin(): array
    {
        // 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) {
            // HIER ist vorher dein Fehler entstanden:
            // - showLoginForm() wurde nur aufgerufen, das Ergebnis aber ignoriert
            // - danach kam ein "return;" ohne Rückgabewert → Rückgabetyp array wurde verletzt

            // Technischen Fehler ausführlich ins Log schreiben
            $this->logger->logException(
                'Technischer Fehler bei der Anmeldung.',
                $exception,
                [
                    'route'      => 'login.submit',
                    'username'   => $username,
                    'remote_addr'=> $_SERVER['REMOTE_ADDR'] ?? null,
                ]
            );

            // Für den Benutzer nur eine allgemeine, aber verständliche Meldung anzeigen
            return $this->showLoginForm(
                'Technischer Fehler bei der Anmeldung. Bitte versuchen Sie es später erneut '
                . 'oder wenden Sie sich an den Administrator.'
            );
        }

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

        // 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() bzw. im Layout ausgewertet.
        $_SESSION[$sessionKey] = [
            'username' => $username,
            'login_at' => date('c'), // ISO-8601 Datum/Zeit der Anmeldung
        ];

        // Nach erfolgreicher Anmeldung zum Dashboard weiterleiten.
        // Kein direkter header()-Aufruf, sondern ein Redirect-Result
        // für die zentrale Steuerung in index.php.
        return [
            'redirect' => 'index.php?route=dashboard',
        ];
    }

    /**
     * Meldet den aktuell eingeloggten Benutzer ab, indem der entsprechende Session-Eintrag entfernt wird,
     * und liefert anschließend ein Redirect-Result zurück auf die Login-Seite.
     *
     * @return array<string, mixed> Redirect-Result
     */
    public function logout(): array
    {
        // 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]);

        // Redirect-Result zur Login-Seite.
        return [
            'redirect' => 'index.php?route=login',
        ];
    }
}
